使用GDAL打开和保存常见格式图像(代码)
2013-04-28 19:49
459 查看
习惯了使用OpenCV的cvLoadImage函数和imread函数打开图像,但是貌似老师不喜欢opencv,实验室也用惯了GDAL,于是乎,就搜集各种资源,整理了使用GDAL读写图像的代码。
以上代码是比较长,不过实现的功能适合cvLoadImage函数功能差不多的。特别是nChannels参数,如果在输入中指定为1,则不管图像文件时彩色还是灰度图像,都会转换为成为灰度图像存储在数组中,如果指定为3,则只有图像时彩色图像时,才会真的存成3通道图像。如果指定为负值,则按照图像的实际通道数目读取。
另外,注意一点,这个图像只读上述各种格式的灰度图像和3通道图像,其它的通道数目不支持。
#include "gdal.h"
#include "gdal_priv.h"
#pragma comment(lib,"gdal_i.lib")</pre>
其中,gdal_i.lib是GDAL库的导出库文件,另外还需要制定对应的dll文件的path路径。
1.使用GDAL打开常见格式图像,并且保存到一维数组中
首先,需要判定图像后缀名,因为GDAL使用不同的驱动器打开对应的图像格式文件,笔者写了个支持JPG、BMP、PNG、GIF、TIFF格式判断的函数。注意,GDAL实际上可以说是个万能的图像格式转换库了,支持几十种图像格式,但是我们一般人常用的也就这么几种。调用GDAL驱动器,打开图像,送进内存数组。
/****************************************************************************** 函数名: readImageGDAL 功能: 读取图像 参数: unsigned char **pImageData - 指向图像数据指针的指针,将由new操作符动态创建,需要在函数外部由调用者使用delete[]销毁,否则内存泄露 int &width,int &height - 图像宽度、高度,由于是引用,可以作为返回值。 nChannels - 图像通道,可选值为1或3。1代表灰度图像,3代表RGB图像,-1表示按照图像自身通道数目读取。 const char *filePath - 图像文件路径名称 说明:******************************************************************************/ bool readImageGDAL(unsigned char **pImageData,int &width,int &height,int &nChannels, const char *filePath) { GDALAllRegister(); GDALDataset *poDataset = NULL; poDataset=(GDALDataset*) GDALOpen(filePath,GA_ReadOnly); if(poDataset == NULL) { GDALClose(poDataset); return false; } width = poDataset->GetRasterXSize(); height = poDataset->GetRasterYSize(); GDALRasterBand* pBand; int i = 0; int nRastercount = poDataset->GetRasterCount(); if (nRastercount == 1) //只有1个通道,则为灰度图像 { nChannels = 1; pBand = poDataset->GetRasterBand(1); *pImageData = new unsigned char[width * height]; pBand->RasterIO(GF_Read, 0,0, //nXOff,nYOff:从左上角坐标point(nXOff,nYOff)处读取图像数据 width,height, //nXSize,nXSize:要读取的图像数据尺寸,注意可以不是band的实际尺寸,这样就是读取roi区域数据 *pImageData, //pData:读取的数据即将存储的目的地址。 width,height, //nBufXSize,nBufYSize:目的地址处图像的尺寸,如果与roi尺寸不一致,则缩放。 GDT_Byte, //eBufType:读取图像后,将要存储为的类型 0, //nPixelSpace:控制同一行相邻像素间隔,0代表使用目的数据类型大小 0); //nLineSpace:控制相邻行的行间隔,0代表使用[目的数据类型大小 * nXsize] GDALClose(poDataset); return true; } else if ( nRastercount == 3 && (nChannels == 3 || nChannels < 0) ) //有3个通道,并且输出为RGB图像 { nChannels = 3; *pImageData = new unsigned char[nRastercount * width * height]; for (i = 1; i <= nRastercount; ++ i) { //GDAL内band存储顺序为RGB,需要转换为我们一般的BGR存储,即低地址->高地址为:B G R unsigned char *pImageOffset = *pImageData + i - 1; GDALRasterBand* pBand = poDataset->GetRasterBand(nRastercount-i+1); pBand->RasterIO( GF_Read, 0,0, width,height, pImageOffset, width,height, GDT_Byte, 3, 0); } GDALClose(poDataset); return true; } else if ( nRastercount == 3 && nChannels == 1 ) //有3个通道,但是要求输出灰度图像 { unsigned char **img = new unsigned char*[nRastercount]; for (i = 0; i < nRastercount; i++) { img[i] = new unsigned char[width * height]; } for (i = 1; i <= nRastercount; ++ i) { //GDAL内band存储顺序为RGB,需要转换为我们一般的BGR存储,即低地址->高地址为:B G R pBand = poDataset->GetRasterBand(nRastercount-i+1); pBand->RasterIO(GF_Read, 0,0, width,height, img[i-1], width,height, GDT_Byte, 0, 0); } GDALClose(poDataset); *pImageData = new unsigned char[width*height]; for (int r = 0; r < height; ++ r) { for (int c = 0; c < width; ++ c) { int t = (r*width+c); //r g b分量依次占:0.299 0.587 0.144,可简化为3:6:1 //img[1.2.3]依次对应BGR (*pImageData)[t] = (img[2][t]*3 + img[1][t]*6 + img[0][t] + 5)/10; } } for (i = 0; i < nRastercount; ++ i) { delete [] img[i]; } delete []img; img = NULL; return true; } else { return false; } }
以上代码是比较长,不过实现的功能适合cvLoadImage函数功能差不多的。特别是nChannels参数,如果在输入中指定为1,则不管图像文件时彩色还是灰度图像,都会转换为成为灰度图像存储在数组中,如果指定为3,则只有图像时彩色图像时,才会真的存成3通道图像。如果指定为负值,则按照图像的实际通道数目读取。
另外,注意一点,这个图像只读上述各种格式的灰度图像和3通道图像,其它的通道数目不支持。
2.保存图像到文件中
2.1根据文件后缀名判断图像格式。
函数代码如下:char* findImageTypeGDAL( char *pDstImgFileName) { char *dstExtension = strlwr(strrchr(pDstImgFileName,'.') + 1); char *Gtype = NULL; if (0 == strcmp(dstExtension,"bmp")) Gtype = "BMP"; else if (0 == strcmp(dstExtension,"jpg")) Gtype = "JPEG"; else if (0 == strcmp(dstExtension,"png")) Gtype = "PNG"; else if (0 == strcmp(dstExtension,"tif")) Gtype = "GTiff"; else if (0 == strcmp(dstExtension,"gif")) Gtype = "GIF"; else Gtype = NULL; return Gtype; }呵呵,太弱智了。
2.2保存图像代码
bool WriteImageGDAL(const char* pDstImgFileName,bool *pImageData,int width,int height,int nChannels) { assert ( !(pDstImgFileName == NULL || pImageData == NULL || width <1 || height < 1 || nChannels < 1)); GDALAllRegister(); char *GType = NULL; GType = findImageTypeGDAL(pDstImgFileName); if (GType == NULL) { return false; } GDALDriver *pMemDriver = NULL; pMemDriver = GetGDALDriverManager()->GetDriverByName("MEM"); if( pMemDriver == NULL ) { return false; } GDALDataset * pMemDataSet = pMemDriver->Create("",width,height,nChannels,GDT_Byte,NULL); GDALRasterBand *pBand = NULL; int nLineCount = width * nChannels; unsigned char *ptr1 = (unsigned char *)pImageData; for (int i = 1; i <= nChannels; i++) { pBand = pMemDataSet->GetRasterBand(nChannels-i+1); pBand->RasterIO(GF_Write, 0, 0, width, height, ptr1+i-1 , width, height, GDT_Byte, nChannels, nLineCount); } GDALDriver *pDstDriver = NULL; pDstDriver = (GDALDriver *)GDALGetDriverByName(GType); if (pDstDriver == NULL) { return false; } pDstDriver->CreateCopy(pDstImgFileName,pMemDataSet,FALSE, NULL, NULL, NULL); GDALClose(pMemDataSet); return true; }保存的结果文件格式,通过其后缀名给出。
3.补充说明
调用的GDAL库可在网上下载,在上述代码前部加入以下包含命令:#include "gdal.h"
#include "gdal_priv.h"
#pragma comment(lib,"gdal_i.lib")</pre>
其中,gdal_i.lib是GDAL库的导出库文件,另外还需要制定对应的dll文件的path路径。
相关文章推荐
- 把正文保存为.hta或.htm格式,用IE打开后即可使用(直接运行EXE程序的脚本)
- 使用hta保存utf8格式的文件的代码
- 今天在Mac机器上使用了Flex Builder编辑了一个源代码文件,保存后使用vim命令去打开时发现系统自动在每一行的结尾添加了^M符号,其实^M在Linux/Unix中是非常常见的,也就是我们在Win中见过的/r回车符号。由于编辑软件的编码问题,某些IDE的编辑器在编辑完文件之后会自动加上这个^M符号。看起来对我们的源代码没有任何影响,其实并不然,当我们把源代码文件Check In到svn之类
- 使用GDAL构造OpenCV的图像格式
- 使用Batik绘制SVG图并保存为png图像格式
- 使用GDAL构造OpenCV的图像格式
- RGB2UYVY 图像格式转换代码,使用乘法查表,没有使用汇编优化
- 使用java代码打开chm格式的帮助文档
- 不使用CFileDialog类产生保存和打开对话框的代码(直接拷贝)
- 数字图像处理 CImage类的使用与封装(jpg png gif tif bmp等格式图像的加载、数据读写、保存等功能)
- C#使用GDAL将tif图像转换为jpg、bmp、png和gif格式的图像
- 猎豹MFC--使用GDI+打开保存图片--把bmp格式图像 保存为了 jpeg格式
- 使用Batik绘制SVG图并保存为png图像格式
- 常见图像格式类型区别及使用说明&绝对路径和相对路径的使用场景&css3实现loading效果
- CxImage与OpenGL结合,用于读入多种格式的纹理以及用来把屏幕保存为各种格式的图像文件
- vc6.0使用gdi+在内存中绘图并将其保存为bmp,jpg,gif,png等格式的图片
- Python复制Word内容并使用格式设字体与大小实例代码
- Python下使用OpenCV——图像显示与保存
- 将图像数据保存成文本格式(字符串)
- 把MATLAB数据转换成1QN格式,并保存到文件供ISE使用