bmp的格式是RGBRGB.....排列下来的,每个像素的三个分量靠在一起,描述完一个像素,接着描述下一个像素。
tif的格式更多样。通常的格式也是BGRBGR.....(次序与bmp相反)排列下来的,但偶尔有一些tif文件采用RRRRRR.......GGGGG.........BBBBB.....的安排。还有的tif文件内容是压缩过的。。。。这里我们只考虑三个颜色分量靠在一起的情况。
下面的例子是一个tif文件,宽896,高608,三个分量。这里直接用gdal读取tif,再写入bmp。与前面《一个tif转bmp的示例》不同,使用gdal不需要手动交换B-R的位置。
具体项目见我的资源中的"gdalTif.rar"
#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");
}