欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

【TIFF】八.价值五千元的TIFF存储代码,你确定不来看看?

程序员文章站 2022-03-11 10:33:58
...

 

目录

一 准备图片

三.存储每一张图片

四. 存储每一个tile

五.简单的存储DEMO

六.源码


首先准备几张图片

【TIFF】八.价值五千元的TIFF存储代码,你确定不来看看?

我要把这几张图片拼成一张大图,拼接效果如下所示:

【TIFF】八.价值五千元的TIFF存储代码,你确定不来看看?

你看看值不值五千块钱?

继续往下看。

一 准备图片

        std::vector<std::string> fileNames;
	fileNames.push_back("./Scan-Compare/1.jpg");
	fileNames.push_back("./Scan-Compare/2.jpg");
	fileNames.push_back("./Scan-Compare/3.jpg");
	fileNames.push_back("./Scan-Compare/4.jpg");
	fileNames.push_back("./Scan-Compare/5.jpg");
	fileNames.push_back("./Scan-Compare/6.jpg");
	std::vector<cv::Mat> mats;
	CTileTiff tiff("D:/1.tiff");

	for (int i = 0; i < fileNames.size(); i++)
	{
		cv::Mat img = cv::imread(fileNames[i]);
		cv::Mat dst;
		resize(img, dst, Size(4096, 4096), 0.0, 0.0);
		//cv::imshow("dst", dst);
		cv::cvtColor(dst, dst, CV_BGR2RGB);
		mats.push_back(dst);
	}

二.设置TIFF的文件信息

bool CTileTiff::SetTileInfo(int nTileW, int nTileH, int nLayer,int nHeight,int nWidth)
{
	m_nTileWidth = nTileW;
	m_nTileHeight = nTileH;
	m_nLayers = nLayer;
	m_nWidth = nWidth;
	m_nHeight = nHeight;
}

 

三.存储每一张图片


bool CTileTiff::SaveImage(cv::Mat &img, const int nLeft, const int nTop,
	const int nRight, const int nBottom)
{
	int nX = nLeft, nY = nTop;

	//int nWidth = nRight - nX, nHeight = nBottom - nY;
	const int nRows = img.rows / m_nTileHeight;
	const int nCols = img.cols / m_nTileWidth;
	cout << "nRows,nCols:" << nRows << "," << nCols << endl;

	const int nPitch = (nRight - nLeft) * 3;
	const int nLayerID = 0;

	for (int i = 0; i < nRows; ++i)
	{
		const int nT = nY + i * m_nTileHeight;
		const int nB = nT + m_nTileWidth;
		for (int j = 0; j < nCols; ++j)
		{
			const int nL = nX + j * m_nTileWidth;
			const int nR = nL + m_nTileWidth;
			cout << nT << "," << nL  << endl;

			cv::Rect rect(j * m_nTileWidth, i * m_nTileHeight, m_nTileWidth, m_nTileHeight);

			cv::Mat roi = img(rect).clone();


			bool bOk = saveTile(roi, nL, nT, nR, nB, nLayerID);
			if (!bOk)
			{
				continue;
			}
		}
	}
//这里是为了下采样,按金字塔格式存储
	int nSubW = nCols, nSubH = nRows;
	int nSubLayer = nLayerID;
	while (true)
	{
		nSubW /= 2;
		nSubH /= 2;
		nSubLayer++;
		if (1 > nSubW || 1 > nSubH)
		{
			break;
		}

		const int nScale = 1 << nSubLayer;
		for (int i = 0; i < nSubH; ++i)
		{
			const int nT = nY + i * m_nTileWidth * nScale;
			const int nB = nT + m_nTileHeight * nScale;
			for (int j = 0; j < nSubW; ++j)
			{
				const int nL = nX + j * m_nTileWidth * nScale;
				const int nR = nL + m_nTileWidth * nScale;
       


				cv::Rect rect(nL - nX, nT - nY, m_nTileWidth * nScale, m_nTileHeight * nScale);

				cv::Mat roi = img(rect).clone();

				cv::Mat resized;

				ResizeImg(roi.data,
					resized.data, m_nTileWidth * nScale, m_nTileHeight * nScale, 3, nPitch, m_nTileWidth, m_nTileHeight,
					3, m_nTileWidth*3);

				
				bool bOk = saveTile(resized, nL, nT, nR, nB, nSubLayer);
				if (!bOk)
				{
					continue;
				}
			}
		}
	}
	

	return true;
}

 

四. 存储每一个tile


bool CTileTiff::saveTile(cv::Mat& roi, const int nL, const int nT,const int nR, const int nB, const int nLayer)
{
	if (roi.empty())
	{
		return false;
	}
	const int nWidth = nR - nL;
	const int nHeight = nB - nT;
	int nLength = 0;

	cout << nL << "," << nT << "," << nR << "," << nB << endl;

	try
	{
		TIFFSetDirectory(m_pFile, nLayer);
		TIFFSetField(m_pFile, TIFFTAG_IMAGEWIDTH, m_nWidth/(nLayer+1));
		TIFFSetField(m_pFile, TIFFTAG_IMAGELENGTH, m_nHeight/(nLayer + 1));
		TIFFSetField(m_pFile, TIFFTAG_TILEWIDTH, m_nTileWidth);
		TIFFSetField(m_pFile, TIFFTAG_TILELENGTH, m_nTileHeight);
		TIFFSetField(m_pFile, TIFFTAG_SUBFILETYPE, FILETYPE_REDUCEDIMAGE);
		TIFFSetField(m_pFile, TIFFTAG_BITSPERSAMPLE, 8);
		TIFFSetField(m_pFile, TIFFTAG_SAMPLESPERPIXEL, 3);
		TIFFSetField(m_pFile, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
		TIFFSetField(m_pFile, TIFFTAG_COMPRESSION, COMPRESSION_JPEG);
		TIFFSetField(m_pFile, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB);
		int nJpegQuality = 60;
		TIFFSetField(m_pFile, TIFFTAG_JPEGQUALITY, nJpegQuality);

		//根据需要设置分辨率
		/*if (nLayer == 0)
		{
			float fPixelSize = 0.00068f;
			int nScale = 20;
			fPixelSize = fPixelSize * 100 / max(1, nScale);
			TIFFSetField(m_pFile, TIFFTAG_XRESOLUTION, 1.0 / (fPixelSize / 10));
			TIFFSetField(m_pFile, TIFFTAG_YRESOLUTION, 1.0 / (fPixelSize / 10));
			TIFFSetField(m_pFile, TIFFTAG_RESOLUTIONUNIT, 3);
		}*/


		// save tile information
		const int nTileRow = nT / m_nTileHeight;
		const int nTileCol = nL / m_nTileWidth;
		int tiffIndex = nTileRow * (m_nWidth / (nLayer+1)/m_nTileWidth) + nTileCol;
		cout << "tiffIndex:" << tiffIndex << "," << nTileRow << "," << nTileCol << ","   << endl;

		TIFFWriteEncodedTile(m_pFile, tiffIndex, (void*)roi.data, m_nTileWidth * m_nTileHeight * 3);

		TIFFWriteDirectory(m_pFile);

		
	}
	catch (const std::exception& e)
	{
		//LOG_E("write tiff error:%s", e.what());
	}

	return true;
}

五.简单的存储DEMO

        int nWidth = mats[0].cols;
	int nHeight = mats[0].rows;
	tiff.SetTileInfo(256, 256, 1, nHeight*2, nWidth*3);
	
	//第一行. 这样是为了demo 看起来容易理解,真正开发的时候你至少得用循环吧。。。
	tiff.SaveImage(mats[0], 0, 0, nWidth, nHeight);
	tiff.SaveImage(mats[1], nWidth, 0, nWidth * 2, nHeight);
	tiff.SaveImage(mats[2], nWidth*2, 0, nWidth * 3, nHeight);
	//第二行
	tiff.SaveImage(mats[3], 0, nHeight, nWidth, nHeight*2);
	tiff.SaveImage(mats[4], nWidth, nHeight, nWidth * 2, nHeight * 2);
	tiff.SaveImage(mats[5], nWidth * 2, nHeight, nWidth * 3, nHeight * 3);

六.源码

具体代码见 https://github.com/Mayi-Keiji/libtiff-x64-build.git

 

如果对代码有疑问的,可以在评论区留言~~~


 

相关标签: IMAGE FORMATS