心如止水-GISer的成長之路
阿新 • • 發佈:2019-01-04
以下是VC下讀取TIFF檔案的程式碼
char* szFileName = "K:\\地圖\\fujian-DEM\\fujian1.tif"; TIFF* tiff = TIFFOpen(szFileName, "r");//開啟Tiff檔案,得到指標,以後所有的操作都通過指標進行 int nTotalFrame = TIFFNumberOfDirectories(tiff); //得到影象的總幀數 //TIFFSetDirectory(tiff,0); //我們開啟第一幅圖,也就是第0幀,如果是第1幀,第二個引數寫1,由此類推。因為Windows下影象基本 //操作都是以BMP格式進行,我們讀出該幀並轉成BMP格式。 char *dtitle; TIFFGetField(tiff,TIFFTAG_PAGENAME,&dtitle); //得到該幀的名字,存放在dtitle中。 int width,height; TIFFGetField(tiff, TIFFTAG_IMAGEWIDTH, &width); //得到寬度 TIFFGetField(tiff, TIFFTAG_IMAGELENGTH, &height);//得到高度 float resolution = max(width,height); uint16 bitspersample = 1; uint16 samplesperpixel = 1; TIFFGetField(tiff, TIFFTAG_SAMPLESPERPIXEL, &samplesperpixel); //每個畫素佔多少機器字,24點陣圖samplesperpixel應該等於3。 TIFFGetField(tiff, TIFFTAG_BITSPERSAMPLE, &bitspersample); //每一個機器字長,這裡應為8。 uint16 bitsperpixel = bitspersample * samplesperpixel; //算出每個畫素佔多少bit,24點陣圖,值為24 DWORD dwBytePerLine = (width*bitsperpixel+31)/32 *4; //由上面幾個引數算出影象每行所佔位元組(BYTE)數。 DWORD64 dwLeng = height*dwBytePerLine;//在記憶體裡存放這幀影象資料所需要的長度 BYTE* pData = new BYTE[dwLeng]; //為存放資料分配記憶體空間 uint32* raster; uint32 *row; raster = (uint32*)malloc(width * height * sizeof (uint32)); TIFFReadRGBAImage(tiff, width, height, (uint32*)pData, 1); //以上幾行讀出該幀資料,儲存到raster中。 row = &raster[0]; LPBYTE bits2 = pData; for (int y = 0; y < height; y++) { LPBYTE bits = bits2; for (int x = 0; x < width; x++) { *bits++ = (BYTE)TIFFGetB(row[x]); *bits++ = (BYTE)TIFFGetG(row[x]); *bits++ = (BYTE)TIFFGetR(row[x]); } row += width; bits2 += dwBytePerLine; } _TIFFfree(raster); //因為Tif的資料存放順序和Windows下的BMP相反,上面這幾句進行轉換。 //轉換結束後,資料存在pData裡,釋放raster所用記憶體。 LPBITMAPINFO pInfo = new BITMAPINFO; pInfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); pInfo->bmiHeader.biWidth = width; pInfo->bmiHeader.biHeight = width; pInfo->bmiHeader.biCompression = BI_RGB; pInfo->bmiHeader.biClrUsed = 0; pInfo->bmiHeader.biClrImportant = 0; pInfo->bmiHeader.biPlanes = 1; pInfo->bmiHeader.biBitCount = 24; pInfo->bmiHeader.biSizeImage = dwLeng; float xres,yres; uint16 res_unit; //解析度單位:如是英寸,釐米 TIFFGetFieldDefaulted(tiff, TIFFTAG_RESOLUTIONUNIT, &res_unit); if(TIFFGetField(tiff, TIFFTAG_XRESOLUTION, &xres) == 0) { pInfo->bmiHeader.biXPelsPerMeter = 0; } else { if(res_unit == 2) //英寸 { pInfo->bmiHeader.biXPelsPerMeter = xres * 10000 / 254; } else if(res_unit == 3) //釐米 { pInfo->bmiHeader.biXPelsPerMeter = xres * 100; } else { pInfo->bmiHeader.biXPelsPerMeter = 0; } } //得到該幀TIFF橫向解析度,並計算出m_pInfo->bmiHeader.biXPelsPerMeter if(TIFFGetField(tiff, TIFFTAG_YRESOLUTION, &yres) == 0) { pInfo->bmiHeader.biYPelsPerMeter = 0; } else { if(res_unit == 2) //英寸 { pInfo->bmiHeader.biYPelsPerMeter = yres * 10000 / 254; } else if(res_unit == 3) //釐米 { pInfo->bmiHeader.biYPelsPerMeter = yres * 100; } else { pInfo->bmiHeader.biYPelsPerMeter = 0; } } //得到該幀TIFF縱向解析度,並計算出m_pInfo->bmiHeader.biYPelsPerMeter BITMAPFILEHEADER bmheader; bmheader.bfType=0x4d42; bmheader.bfSize=0; bmheader.bfReserved1=0; bmheader.bfReserved2=0; bmheader.bfOffBits=54; //這幾句是生成bmp檔案的頭結構 CFile bmpFile; bmpFile.Open(_T("c://test.bmp"),CFile::modeCreate|CFile::modeWrite); bmpFile.Write(&bmheader,sizeof(BITMAPFILEHEADER)); bmpFile.Write(&(pInfo->bmiHeader),sizeof(BITMAPINFOHEADER)); bmpFile.Write(pData,dwLeng); bmpFile.Close(); //這裡,把該幀TIFF儲存到了C盤的test.bmp中,可以用看圖軟體開啟瀏覽一下。 //記得釋放記憶體空間 delete pInfo; pInfo = NULL; delete pData; pData = NULL; //如果想直接顯示,就不需要釋放,呼叫StretchDIBits在客戶區的DC上就可以顯示了。 //如果再開啟其他幀的話,從TIFFSetDirectory開始迴圈執行,比如取下一幀就是 TIFFSetDirectory(tiff,1); //記得儲存時另換一個bmp檔名。 //最後,對這個TIFF檔案全部操作結束,記得呼叫 TIFFClose(tiff);
下面的程式碼是用GDAL開啟的
char* szFileName = "K:\\地圖\\fujian-DEM\\fujian1.tif"; GDALDataset *poDataset; //GDAL資料集 GDALAllRegister(); poDataset = (GDALDataset*)GDALOpen(szFileName,GA_ReadOnly); if( poDataset == NULL ) { AfxMessageBox(_T("檔案開啟失敗!!!")); return; } GDALRasterBand *poBand; //遙感的一個波段 int nBandCount = poDataset->GetRasterCount(); poBand = poDataset->GetRasterBand(1); //和陣列下標有點不同 //獲得影象顯示視窗的尺寸 GetClientRect(&m_ViewRect); int nImgSizeX = poDataset->GetRasterXSize(); int nImgSizeY = poDataset->GetRasterYSize(); double adfGeoTransform[6]; poDataset->GetGeoTransform( adfGeoTransform ); double right = adfGeoTransform[0] + nImgSizeX*adfGeoTransform[1]; double bottom = adfGeoTransform[3] + nImgSizeY*adfGeoTransform[5]; int nBufferSizeX,nBufferSizeY; nBufferSizeX = nImgSizeX; nBufferSizeY = nImgSizeY; int nScrrenWidth = m_ViewRect.Width(); int nScrrenHeight= m_ViewRect.Height(); BYTE *pafScanblock1,*TempLock1; pafScanblock1 = (BYTE *) CPLMalloc((nScrrenWidth)*(nScrrenHeight)); TempLock1 = pafScanblock1; poBand->RasterIO( GF_Read, 0, 0,nBufferSizeX,nBufferSizeY, pafScanblock1,nScrrenWidth,nScrrenHeight, GDT_Byte,0, 0 ); //在View逐點顯示影象 DWORD dwBytes = (nScrrenWidth * 24) / 8; while(((DWORD) dwBytes) % 4) { dwBytes++; } BYTE *szBuffer = new BYTE[nScrrenHeight*dwBytes]; memset(szBuffer,0,nScrrenHeight*dwBytes); BYTE *pTemp = szBuffer; CClientDC dc(this); int nIndex = 0; for (int i=0;i<nScrrenHeight;i++) { for (int j=0;j<nScrrenWidth;j++) { BYTE dn1 = *pafScanblock1; memcpy(szBuffer,(char*)(&dn1),1); szBuffer += 1; pafScanblock1 ++; } szBuffer = pTemp+dwBytes*i; } CPLFree(TempLock1); BITMAPINFOHEADER bmiHdr; BITMAPINFO MapInfo; memset(&bmiHdr, 0, sizeof(BITMAPINFOHEADER)); bmiHdr.biBitCount = 3*8; bmiHdr.biClrImportant = 0; bmiHdr.biClrUsed = 0; bmiHdr.biCompression = BI_RGB; bmiHdr.biHeight = -nScrrenHeight; bmiHdr.biPlanes = 1; bmiHdr.biSize = sizeof(BITMAPINFOHEADER); bmiHdr.biSizeImage = 0; bmiHdr.biWidth = nScrrenWidth; bmiHdr.biXPelsPerMeter = 0; bmiHdr.biYPelsPerMeter = 0; MapInfo.bmiHeader = bmiHdr; MapInfo.bmiColors[0].rgbBlue = 0; MapInfo.bmiColors[0].rgbGreen = 0; MapInfo.bmiColors[0].rgbRed = 0; MapInfo.bmiColors[0].rgbReserved = 0; dc.SetStretchBltMode(MAXSTRETCHBLTMODE); ::StretchDIBits(dc.GetSafeHdc(), 0, 0, nScrrenWidth, nScrrenHeight, 0, 0, bmiHdr.biWidth, -bmiHdr.biHeight, pTemp, (LPBITMAPINFO)(&MapInfo), DIB_RGB_COLORS, SRCCOPY); GDALClose(poDataset); delete []pTemp;