bmp的格式是RGBRGB.....排列下来的,每个像素的三个分量靠在一起,描述完一个像素,接着描述下一个像素。
tif的格式更多样。通常的格式也是BGRBGR.....(次序与bmp相反)排列下来的,但偶尔有一些tif文件采用RRRRRR.......GGGGG.........BBBBB.....的安排。还有的tif文件内容是压缩过的。。。。这里我们只考虑三个颜色分量靠在一起的情况。
下面的例子是一个tif文件,宽896,高608,三个分量。这里直接用gdal读取tif,再写入bmp。与前面《一个tif转bmp的示例》不同,使用gdal不需要手动交换B-R的位置。
具体项目见我的资源中的gdalTif.rar_GDAL批量处理TIF到BMP资源-CSDN下载
#include <gdal_priv.h> #include <algorithm> #include <iostream> #include <fstream> #pragma comment(lib, "gdal_i.lib") bool bReadImageMultiBand(unsigned char * & pImgData, int & iWidth, int & iHeight, int & iChannel, char * strPath); bool bWriteImageData(char *, unsigned char *, int, int, int, int); void vFindImageTypeGDAL(char *, char *); int main(void) { GDALAllRegister(); int iWidth, iHeight, iChannel; unsigned char * pImgData; if(bReadImageMultiBand(pImgData, iWidth, iHeight, iChannel, "earthRGBRGB.tif")) { bWriteImageData("earth.bmp", pImgData, iWidth, iHeight, iChannel, iChannel); delete [] pImgData; } return 0; } bool bReadImageMultiBand(unsigned char * & pImgData, int & iWidth, int & iHeight, int & iChannel, char * strPath) { GDALDataset * pDataSet = nullptr; pDataSet = (GDALDataset *)GDALOpen(strPath, GA_ReadOnly); if(pDataSet == nullptr) { GDALClose(pDataSet); return false; } GDALDataType dt = pDataSet->GetRasterBand(1)->GetRasterDataType(); iWidth = pDataSet->GetRasterXSize(); iHeight = pDataSet->GetRasterYSize(); iChannel = std::min(pDataSet->GetRasterCount(), 3); int arrBandMap[] = {1,2,3}; pImgData = new unsigned char[iWidth * iHeight * iChannel]; pDataSet->RasterIO(GF_Read, 0,0, iWidth, iHeight, pImgData, iWidth, iHeight, dt, iChannel, arrBandMap, 0,0,0); GDALClose(pDataSet); return true; } bool bWriteImageData(char * strDestPath, unsigned char * pData, int iWidth, int iHeight, int iSrcChannel, int iDestChannel) { char arrType[1024] = {0}; vFindImageTypeGDAL(strDestPath, arrType); if(arrType) { std::fstream file; file.open(strDestPath, std::ios_base::out); file.close(); GDALDriver * pMemDriver = GetGDALDriverManager()->GetDriverByName("MEM"); if(pMemDriver == nullptr) return false; GDALDataset * pMemDataSet = pMemDriver->Create("",iWidth,iHeight,iDestChannel,GDT_Byte,NULL); GDALRasterBand *pBand = NULL; int arrBandMap[3] = { 1, 2, 3 }; pMemDataSet->RasterIO(GF_Write, 0, 0, iWidth, iHeight, pData, iWidth, iHeight, GDT_Byte, iDestChannel, arrBandMap, 0,0,0); GDALDriver *pDstDriver = NULL; pDstDriver = (GDALDriver *)GDALGetDriverByName(arrType); if (pDstDriver == NULL) { GDALClose(pMemDataSet); return false; } GDALDataset * pDataSet = pDstDriver->CreateCopy(strDestPath,pMemDataSet,FALSE, NULL, NULL, NULL); if (pDataSet == NULL) { GDALClose(pMemDataSet); return false; } GDALClose(pDataSet); GDALClose(pMemDataSet); return true; } else { return false; } } void vFindImageTypeGDAL(char * pDstImgFileName, char * pDst) { char * dstExtension = strlwr(strrchr(pDstImgFileName, '.') + 1); if (0 == strcmp(dstExtension, "bmp")) sprintf(pDst, "%s", "BMP"); else if (0 == strcmp(dstExtension, "jpg")) sprintf(pDst, "%s", "JPEG"); else if (0 == strcmp(dstExtension, "png")) sprintf(pDst, "%s", "PNG"); else if (0 == strcmp(dstExtension, "tif")) sprintf(pDst, "%s", "GTiff"); else if (0 == strcmp(dstExtension, "gif")) sprintf(pDst, "%s", "GIF"); }