tiff檔案讀取

pamxy發表於2013-05-20

轉自:http://blog.csdn.net/zhouxuguang236/article/details/7846615

以下是VC下讀取TIFF檔案的程式碼

  1. char* szFileName = "K:\\地圖\\fujian-DEM\\fujian1.tif";  
  2.     TIFF* tiff = TIFFOpen(szFileName, "r");//開啟Tiff檔案,得到指標,以後所有的操作都通過指標進行  
  3.   
  4.     int nTotalFrame = TIFFNumberOfDirectories(tiff);    //得到影象的總幀數  
  5.   
  6.     //TIFFSetDirectory(tiff,0);  
  7.     //我們開啟第一幅圖,也就是第0幀,如果是第1幀,第二個引數寫1,由此類推。因為Windows下影象基本  
  8.     //操作都是以BMP格式進行,我們讀出該幀並轉成BMP格式。  
  9.   
  10.     char *dtitle;  
  11.     TIFFGetField(tiff,TIFFTAG_PAGENAME,&dtitle);  
  12.     //得到該幀的名字,存放在dtitle中。  
  13.   
  14.     int width,height;  
  15.     TIFFGetField(tiff, TIFFTAG_IMAGEWIDTH, &width);  //得到寬度  
  16.     TIFFGetField(tiff, TIFFTAG_IMAGELENGTH, &height);//得到高度  
  17.   
  18.     float resolution = max(width,height);  
  19.   
  20.     uint16 bitspersample = 1;  
  21.     uint16 samplesperpixel = 1;  
  22.   
  23.     TIFFGetField(tiff, TIFFTAG_SAMPLESPERPIXEL, &samplesperpixel);  
  24.     //每個畫素佔多少機器字,24點陣圖samplesperpixel應該等於3。  
  25.     TIFFGetField(tiff, TIFFTAG_BITSPERSAMPLE, &bitspersample);  
  26.     //每一個機器字長,這裡應為8。  
  27.   
  28.     uint16 bitsperpixel = bitspersample * samplesperpixel;  
  29.     //算出每個畫素佔多少bit,24點陣圖,值為24  
  30.     DWORD dwBytePerLine = (width*bitsperpixel+31)/32 *4;  
  31.     //由上面幾個引數算出影象每行所佔位元組(BYTE)數。  
  32.   
  33.   
  34.     DWORD64 dwLeng = height*dwBytePerLine;//在記憶體裡存放這幀影象資料所需要的長度  
  35.     BYTE* pData = new BYTE[dwLeng];    //為存放資料分配記憶體空間  
  36.   
  37.   
  38.     uint32* raster;          
  39.     uint32 *row;  
  40.     raster = (uint32*)malloc(width * height * sizeof (uint32));  
  41.     TIFFReadRGBAImage(tiff, width, height, (uint32*)pData, 1);   
  42.     //以上幾行讀出該幀資料,儲存到raster中。  
  43.   
  44.     row = &raster[0];  
  45.     LPBYTE bits2 = pData;  
  46.     for (int y = 0; y < height; y++)   
  47.     {  
  48.   
  49.         LPBYTE bits = bits2;  
  50.         for (int x = 0; x < width; x++)   
  51.         {  
  52.             *bits++ = (BYTE)TIFFGetB(row[x]);  
  53.             *bits++ = (BYTE)TIFFGetG(row[x]);  
  54.             *bits++ = (BYTE)TIFFGetR(row[x]);  
  55.         }  
  56.         row += width;  
  57.         bits2 += dwBytePerLine;  
  58.     }  
  59.     _TIFFfree(raster);  
  60.   
  61.     //因為Tif的資料存放順序和Windows下的BMP相反,上面這幾句進行轉換。  
  62.     //轉換結束後,資料存在pData裡,釋放raster所用記憶體。  
  63.   
  64.   
  65.   
  66.     LPBITMAPINFO pInfo = new BITMAPINFO;  
  67.     pInfo->bmiHeader.biSize        = sizeof(BITMAPINFOHEADER);  
  68.     pInfo->bmiHeader.biWidth        = width;  
  69.     pInfo->bmiHeader.biHeight        = width;  
  70.     pInfo->bmiHeader.biCompression    = BI_RGB;  
  71.   
  72.     pInfo->bmiHeader.biClrUsed        = 0;  
  73.     pInfo->bmiHeader.biClrImportant    = 0;  
  74.     pInfo->bmiHeader.biPlanes        = 1;  
  75.     pInfo->bmiHeader.biBitCount = 24;  
  76.     pInfo->bmiHeader.biSizeImage        = dwLeng;  
  77.   
  78.     float xres,yres;  
  79.     uint16 res_unit;   
  80.     //解析度單位:如是英寸,釐米  
  81.     TIFFGetFieldDefaulted(tiff, TIFFTAG_RESOLUTIONUNIT, &res_unit);  
  82.   
  83.     if(TIFFGetField(tiff, TIFFTAG_XRESOLUTION, &xres) == 0)  
  84.     {  
  85.         pInfo->bmiHeader.biXPelsPerMeter = 0;  
  86.     }  
  87.     else  
  88.     {  
  89.         if(res_unit == 2)    //英寸  
  90.         {  
  91.             pInfo->bmiHeader.biXPelsPerMeter = xres * 10000 / 254;  
  92.         }  
  93.         else if(res_unit == 3)    //釐米  
  94.         {  
  95.             pInfo->bmiHeader.biXPelsPerMeter = xres * 100;  
  96.         }  
  97.         else  
  98.         {  
  99.             pInfo->bmiHeader.biXPelsPerMeter = 0;  
  100.         }  
  101.     }  
  102.     //得到該幀TIFF橫向解析度,並計算出m_pInfo->bmiHeader.biXPelsPerMeter  
  103.   
  104.     if(TIFFGetField(tiff, TIFFTAG_YRESOLUTION, &yres) == 0)  
  105.     {  
  106.         pInfo->bmiHeader.biYPelsPerMeter = 0;  
  107.     }  
  108.     else  
  109.     {  
  110.         if(res_unit == 2)    //英寸  
  111.         {  
  112.             pInfo->bmiHeader.biYPelsPerMeter = yres * 10000 / 254;  
  113.         }  
  114.         else if(res_unit == 3)    //釐米  
  115.         {  
  116.             pInfo->bmiHeader.biYPelsPerMeter = yres * 100;  
  117.         }  
  118.         else  
  119.         {  
  120.             pInfo->bmiHeader.biYPelsPerMeter = 0;  
  121.         }  
  122.     }  
  123.     //得到該幀TIFF縱向解析度,並計算出m_pInfo->bmiHeader.biYPelsPerMeter  
  124.   
  125.   
  126.     BITMAPFILEHEADER bmheader;  
  127.     bmheader.bfType=0x4d42;  
  128.     bmheader.bfSize=0;  
  129.     bmheader.bfReserved1=0;  
  130.     bmheader.bfReserved2=0;  
  131.     bmheader.bfOffBits=54;  
  132.     //這幾句是生成bmp檔案的頭結構  
  133.   
  134.     CFile bmpFile;  
  135.     bmpFile.Open(_T("c://test.bmp"),CFile::modeCreate|CFile::modeWrite);  
  136.     bmpFile.Write(&bmheader,sizeof(BITMAPFILEHEADER));  
  137.     bmpFile.Write(&(pInfo->bmiHeader),sizeof(BITMAPINFOHEADER));  
  138.     bmpFile.Write(pData,dwLeng);  
  139.     bmpFile.Close();  
  140.   
  141.     //這裡,把該幀TIFF儲存到了C盤的test.bmp中,可以用看圖軟體開啟瀏覽一下。  
  142.   
  143.     //記得釋放記憶體空間  
  144.     delete pInfo;  
  145.     pInfo = NULL;  
  146.     delete pData;  
  147.     pData = NULL;  
  148.     //如果想直接顯示,就不需要釋放,呼叫StretchDIBits在客戶區的DC上就可以顯示了。  
  149.   
  150.   
  151.     //如果再開啟其他幀的話,從TIFFSetDirectory開始迴圈執行,比如取下一幀就是  
  152.     TIFFSetDirectory(tiff,1);  
  153.     //記得儲存時另換一個bmp檔名。  
  154.     //最後,對這個TIFF檔案全部操作結束,記得呼叫  
  155.     TIFFClose(tiff);  

下面的程式碼是用GDAL開啟的

  1. char* szFileName = "K:\\地圖\\fujian-DEM\\fujian1.tif";  
  2.     GDALDataset *poDataset;   //GDAL資料集  
  3.     GDALAllRegister();  
  4.   
  5.     poDataset = (GDALDataset*)GDALOpen(szFileName,GA_ReadOnly);  
  6.     if( poDataset == NULL )  
  7.     {  
  8.         AfxMessageBox(_T("檔案開啟失敗!!!"));  
  9.         return;  
  10.     }   
  11.   
  12.     GDALRasterBand *poBand;   //遙感的一個波段  
  13.     int nBandCount = poDataset->GetRasterCount();  
  14.     poBand = poDataset->GetRasterBand(1);   //和陣列下標有點不同  
  15.   
  16.     //獲得影象顯示視窗的尺寸  
  17.     GetClientRect(&m_ViewRect);  
  18.   
  19.     int nImgSizeX = poDataset->GetRasterXSize();  
  20.     int nImgSizeY = poDataset->GetRasterYSize();  
  21.   
  22.     double adfGeoTransform[6];  
  23.     poDataset->GetGeoTransform( adfGeoTransform );  
  24.   
  25.     double right  = adfGeoTransform[0] + nImgSizeX*adfGeoTransform[1];  
  26.     double bottom  = adfGeoTransform[3] + nImgSizeY*adfGeoTransform[5];  
  27.   
  28.     int nBufferSizeX,nBufferSizeY;  
  29.   
  30.     nBufferSizeX = nImgSizeX;  
  31.     nBufferSizeY = nImgSizeY;  
  32.   
  33.     int nScrrenWidth = m_ViewRect.Width();  
  34.     int nScrrenHeight= m_ViewRect.Height();  
  35.   
  36.     BYTE *pafScanblock1,*TempLock1;  
  37.     pafScanblock1 = (BYTE *) CPLMalloc((nScrrenWidth)*(nScrrenHeight));  
  38.     TempLock1 = pafScanblock1;  
  39.   
  40.     poBand->RasterIO( GF_Read, 0, 0,nBufferSizeX,nBufferSizeY,   
  41.         pafScanblock1,nScrrenWidth,nScrrenHeight, GDT_Byte,0, 0 );  
  42.   
  43.     //在View逐點顯示影象  
  44.     DWORD dwBytes = (nScrrenWidth * 24) / 8;  
  45.     while(((DWORD) dwBytes) % 4)   
  46.     {  
  47.         dwBytes++;  
  48.     }  
  49.   
  50.     BYTE *szBuffer = new BYTE[nScrrenHeight*dwBytes];  
  51.     memset(szBuffer,0,nScrrenHeight*dwBytes);  
  52.     BYTE *pTemp = szBuffer;  
  53.     CClientDC dc(this);  
  54.     int nIndex = 0;  
  55.     for (int i=0;i<nScrrenHeight;i++)  
  56.     {  
  57.         for (int j=0;j<nScrrenWidth;j++)  
  58.         {  
  59.   
  60.             BYTE dn1 = *pafScanblock1;  
  61.   
  62.             memcpy(szBuffer,(char*)(&dn1),1);  
  63.             szBuffer += 1;  
  64.   
  65.             pafScanblock1 ++;  
  66.   
  67.         }  
  68.   
  69.         szBuffer = pTemp+dwBytes*i;  
  70.   
  71.     }  
  72.     CPLFree(TempLock1);  
  73.   
  74.     BITMAPINFOHEADER bmiHdr;  
  75.     BITMAPINFO MapInfo;  
  76.     memset(&bmiHdr, 0, sizeof(BITMAPINFOHEADER));  
  77.     bmiHdr.biBitCount = 3*8;  
  78.     bmiHdr.biClrImportant = 0;  
  79.     bmiHdr.biClrUsed = 0;  
  80.     bmiHdr.biCompression = BI_RGB;  
  81.     bmiHdr.biHeight = -nScrrenHeight;  
  82.     bmiHdr.biPlanes = 1;  
  83.     bmiHdr.biSize = sizeof(BITMAPINFOHEADER);  
  84.     bmiHdr.biSizeImage = 0;  
  85.     bmiHdr.biWidth = nScrrenWidth;  
  86.   
  87.     bmiHdr.biXPelsPerMeter = 0;  
  88.     bmiHdr.biYPelsPerMeter = 0;  
  89.   
  90.     MapInfo.bmiHeader = bmiHdr;  
  91.     MapInfo.bmiColors[0].rgbBlue = 0;  
  92.     MapInfo.bmiColors[0].rgbGreen = 0;  
  93.     MapInfo.bmiColors[0].rgbRed = 0;  
  94.     MapInfo.bmiColors[0].rgbReserved = 0;  
  95.   
  96.     dc.SetStretchBltMode(MAXSTRETCHBLTMODE);  
  97.     ::StretchDIBits(dc.GetSafeHdc(), 0, 0, nScrrenWidth, nScrrenHeight,  
  98.         0, 0, bmiHdr.biWidth, -bmiHdr.biHeight,  
  99.         pTemp, (LPBITMAPINFO)(&MapInfo), DIB_RGB_COLORS, SRCCOPY);  
  100.   
  101.     GDALClose(poDataset);  
  102.     delete []pTemp;