首先准备几张图片
我要把这几张图片拼成一张大图,拼接效果如下所示:
继续往下看。
一 准备图片
1 std::vector<std::string> fileNames;
2 fileNames.push_back("./Scan-Compare/1.jpg");
3 fileNames.push_back("./Scan-Compare/2.jpg");
4 fileNames.push_back("./Scan-Compare/3.jpg");
5 fileNames.push_back("./Scan-Compare/4.jpg");
6 fileNames.push_back("./Scan-Compare/5.jpg");
7 fileNames.push_back("./Scan-Compare/6.jpg");
8 std::vector<cv::Mat> mats;
9 CTileTiff tiff("D:/1.tiff");
10
11 for (int i = 0; i < fileNames.size(); i++)
12 {
13 cv::Mat img = cv::imread(fileNames[i]);
14 cv::Mat dst;
15 resize(img, dst, Size(4096, 4096), 0.0, 0.0);
16 //cv::imshow("dst", dst);
17 cv::cvtColor(dst, dst, CV_BGR2RGB);
18 mats.push_back(dst);
19 }
二.设置TIFF的文件信息
1 bool CTileTiff::SetTileInfo(int nTileW, int nTileH, int nLayer,int nHeight,int nWidth)
2 {
3 m_nTileWidth = nTileW;
4 m_nTileHeight = nTileH;
5 m_nLayers = nLayer;
6 m_nWidth = nWidth;
7 m_nHeight = nHeight;
8 }
三.存储每一张图片
1 bool CTileTiff::SaveImage(cv::Mat &img, const int nLeft, const int nTop,
2 const int nRight, const int nBottom)
3 {
4 int nX = nLeft, nY = nTop;
5
6 //int nWidth = nRight - nX, nHeight = nBottom - nY;
7 const int nRows = img.rows / m_nTileHeight;
8 const int nCols = img.cols / m_nTileWidth;
9 cout << "nRows,nCols:" << nRows << "," << nCols << endl;
10
11 const int nPitch = (nRight - nLeft) * 3;
12 const int nLayerID = 0;
13
14 for (int i = 0; i < nRows; ++i)
15 {
16 const int nT = nY + i * m_nTileHeight;
17 const int nB = nT + m_nTileWidth;
18 for (int j = 0; j < nCols; ++j)
19 {
20 const int nL = nX + j * m_nTileWidth;
21 const int nR = nL + m_nTileWidth;
22 cout << nT << "," << nL << endl;
23
24 cv::Rect rect(j * m_nTileWidth, i * m_nTileHeight, m_nTileWidth, m_nTileHeight);
25
26 cv::Mat roi = img(rect).clone();
27
28
29 bool bOk = saveTile(roi, nL, nT, nR, nB, nLayerID);
30 if (!bOk)
31 {
32 continue;
33 }
34 }
35 }
36 //这里是为了下采样,按金字塔格式存储
37 int nSubW = nCols, nSubH = nRows;
38 int nSubLayer = nLayerID;
39 while (true)
40 {
41 nSubW /= 2;
42 nSubH /= 2;
43 nSubLayer++;
44 if (1 > nSubW || 1 > nSubH)
45 {
46 break;
47 }
48
49 const int nScale = 1 << nSubLayer;
50 for (int i = 0; i < nSubH; ++i)
51 {
52 const int nT = nY + i * m_nTileWidth * nScale;
53 const int nB = nT + m_nTileHeight * nScale;
54 for (int j = 0; j < nSubW; ++j)
55 {
56 const int nL = nX + j * m_nTileWidth * nScale;
57 const int nR = nL + m_nTileWidth * nScale;
58
59
60
61 cv::Rect rect(nL - nX, nT - nY, m_nTileWidth * nScale, m_nTileHeight * nScale);
62
63 cv::Mat roi = img(rect).clone();
64
65 cv::Mat resized;
66
67 ResizeImg(roi.data,
68 resized.data, m_nTileWidth * nScale, m_nTileHeight * nScale, 3, nPitch, m_nTileWidth, m_nTileHeight,
69 3, m_nTileWidth*3);
70
71
72 bool bOk = saveTile(resized, nL, nT, nR, nB, nSubLayer);
73 if (!bOk)
74 {
75 continue;
76 }
77 }
78 }
79 }
80
81
82 return true;
83 }
四. 存储每一个tile
1 bool CTileTiff::saveTile(cv::Mat& roi, const int nL, const int nT,const int nR, const int nB, const int nLayer)
2 {
3 if (roi.empty())
4 {
5 return false;
6 }
7 const int nWidth = nR - nL;
8 const int nHeight = nB - nT;
9 int nLength = 0;
10
11 cout << nL << "," << nT << "," << nR << "," << nB << endl;
12
13 try
14 {
15 TIFFSetDirectory(m_pFile, nLayer);
16 TIFFSetField(m_pFile, TIFFTAG_IMAGEWIDTH, m_nWidth/(nLayer+1));
17 TIFFSetField(m_pFile, TIFFTAG_IMAGELENGTH, m_nHeight/(nLayer + 1));
18 TIFFSetField(m_pFile, TIFFTAG_TILEWIDTH, m_nTileWidth);
19 TIFFSetField(m_pFile, TIFFTAG_TILELENGTH, m_nTileHeight);
20 TIFFSetField(m_pFile, TIFFTAG_SUBFILETYPE, FILETYPE_REDUCEDIMAGE);
21 TIFFSetField(m_pFile, TIFFTAG_BITSPERSAMPLE, 8);
22 TIFFSetField(m_pFile, TIFFTAG_SAMPLESPERPIXEL, 3);
23 TIFFSetField(m_pFile, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
24 TIFFSetField(m_pFile, TIFFTAG_COMPRESSION, COMPRESSION_JPEG);
25 TIFFSetField(m_pFile, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB);
26 int nJpegQuality = 60;
27 TIFFSetField(m_pFile, TIFFTAG_JPEGQUALITY, nJpegQuality);
28
29 //根据需要设置分辨率
30 /*if (nLayer == 0)
31 {
32 float fPixelSize = 0.00068f;
33 int nScale = 20;
34 fPixelSize = fPixelSize * 100 / max(1, nScale);
35 TIFFSetField(m_pFile, TIFFTAG_XRESOLUTION, 1.0 / (fPixelSize / 10));
36 TIFFSetField(m_pFile, TIFFTAG_YRESOLUTION, 1.0 / (fPixelSize / 10));
37 TIFFSetField(m_pFile, TIFFTAG_RESOLUTIONUNIT, 3);
38 }*/
39
40
41 // save tile information
42 const int nTileRow = nT / m_nTileHeight;
43 const int nTileCol = nL / m_nTileWidth;
44 int tiffIndex = nTileRow * (m_nWidth / (nLayer+1)/m_nTileWidth) + nTileCol;
45 cout << "tiffIndex:" << tiffIndex << "," << nTileRow << "," << nTileCol << "," << endl;
46
47 TIFFWriteEncodedTile(m_pFile, tiffIndex, (void*)roi.data, m_nTileWidth * m_nTileHeight * 3);
48
49 TIFFWriteDirectory(m_pFile);
50
51
52 }
53 catch (const std::exception& e)
54 {
55 //LOG_E("write tiff error:%s", e.what());
56 }
57
58 return true;
59 }
五.简单的存储DEMO
1 int nWidth = mats[0].cols;
2 int nHeight = mats[0].rows;
3 tiff.SetTileInfo(256, 256, 1, nHeight*2, nWidth*3);
4
5 //第一行. 这样是为了demo 看起来容易理解,真正开发的时候你至少得用循环吧。。。
6 tiff.SaveImage(mats[0], 0, 0, nWidth, nHeight);
7 tiff.SaveImage(mats[1], nWidth, 0, nWidth * 2, nHeight);
8 tiff.SaveImage(mats[2], nWidth*2, 0, nWidth * 3, nHeight);
9 //第二行
10 tiff.SaveImage(mats[3], 0, nHeight, nWidth, nHeight*2);
11 tiff.SaveImage(mats[4], nWidth, nHeight, nWidth * 2, nHeight * 2);
12 tiff.SaveImage(mats[5], nWidth * 2, nHeight, nWidth * 3, nHeight * 3);