转自:http://blog.youkuaiyun.com/zhouxuguang236/article/details/7846615
以下是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;