16位TIFF灰度图像转存BMP图像总结
来源:互联网 发布:小众旅游 知乎 编辑:程序博客网 时间:2024/05/22 08:19
在自己写代码之前,参考了站内许多前辈的文章,其中对我比较有用的是这三篇,
1、tiff文件读取
http://blog.csdn.net/zhouxuguang236/article/details/7846615
2、TIFF图像文件详解
http://blog.csdn.net/han_jiang_xue/article/details/8266207
3、libtiff使用小记
http://blog.csdn.net/nli123/article/details/4300949
其中第一篇是两段源码,我的代码就是在其中第一段源码基础上修改的,第二第三篇都是类似帮助文档的东西,比较有用。
首先,我觉得对TIFF和BMP这两种图像格式的一些基本知识需要掌握,在写代码过程中因为有些知识点的理解不清着实吃了不少苦头,然而这些网络上都有,这里就不再介绍了。
下面就开始介绍我做的事情:
我所使用的TIFF图像的部分信息是这样的:
TIFF image
XYZdim:2448/2984/1
XYZ size [mm ormicron]:1.00/1.00/1.00
Bits persample/Samples per pixel: 16/1
Data offset:512
可以看到这里的Samples per pixel为1,而Bits per sample为16,我想知道的朋友大概也可以猜出这幅图像的作用了,然后上面第一篇文章中代码适用于24位图,也就是3*8的tiff图。我本身也用网上下载的一些tiff图像做了测试,确实可以正确存储为BMP并显示出来。然而直接对我的图像做操作的话,在读取图像数据时需要做些变化。
文章中读取图像数据是通过这样的代码来实现:
raster = (uint32*)malloc(width * height * sizeof (uint32));TIFFReadRGBAImage(tiff, width, height, raster,0);
可以推测,TIFFReadRGBAImage是适用于三通道采样的TIFF图像的,而单通道采样的或许可以使用TIFFReadScanline来读取,可我经过尝试没有成功,可能是我自己本身没有使用正确吧。
这样,我就不得不放弃使用libtiff所提供的函数了,没办法我就去使用了windows的API,现在回头一看,其实完全不需要libtiff也应该是可以实现的吧。直接上代码:
FILE * finput = fopen("C:\\Users\\Administrator.WIN7U-20141205O\\Desktop\\image.tif", "rb");if(finput){long size = filesize(finput);byte *pbuf = new byte[size+1];fread(pbuf, sizeof(byte), size, finput);uint32 IFDOffset=pbuf[4]+255*pbuf[5]+65535*pbuf[6]+16721425*pbuf[7]; //第一个IFD偏移量uint16 num = pbuf[IFDOffset]+pbuf[IFDOffset+1]*255; //DE(目录入口)个数long Size = size-(IFDOffset+6+12*num);BYTE* pImageData = new BYTE[Size];MoveMemory(pImageData,(pbuf+size-dwLeng),dwLeng);<pre name="code" class="cpp"> for (int i=0;i<(width*height);i++){uint16 temp=pImageData[2*i]+255*pImageData[2*i+1]; //第i点的像素值uint8 tmp = 255*temp/65535; //新的像素值pData[i*3+0]=tmp;pData[i*3+1]=tmp;pData[i*3+2]=tmp;}LPBITMAPINFO pInfo = new BITMAPINFO;pInfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);pInfo->bmiHeader.biWidth = width;pInfo->bmiHeader.biHeight = height;pInfo->bmiHeader.biCompression = BI_RGB;//BI_BITFIELDS; //bmp为16位色bmp//BI_RGB;pInfo->bmiHeader.biClrUsed = 0;pInfo->bmiHeader.biClrImportant = 0;pInfo->bmiHeader.biPlanes = 1;pInfo->bmiHeader.biBitCount = 24; //记录像素的位数,很重要的数值,图像的颜色数由该值决定。pInfo->bmiHeader.biSizeImage = width*height*3;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.biYPelsPerMeterBITMAPFILEHEADER bmheader;bmheader.bfType=0x4d42;bmheader.bfSize=0;bmheader.bfReserved1=0;bmheader.bfReserved2=0;bmheader.bfOffBits=54;//这几句是生成bmp文件的头结构CFile bmpFile;bmpFile.Open(_T("test.bmp"),CFile::modeCreate|CFile::modeWrite);bmpFile.Write(&bmheader,sizeof(BITMAPFILEHEADER));bmpFile.Write(&(pInfo->bmiHeader),sizeof(BITMAPINFOHEADER));bmpFile.Write(pData,height*width*3);bmpFile.Close();//这里,把该帧TIFF保存到了C盘的test.bmp中,可以用看图软件打开浏览一下。delete pImageData;pImageData = NULL;delete pInfo;pInfo = NULL;//delete pData;pData = NULL;}
这段用windows API实现的代码其实也使用了部分libtiff库的功能,主要是一些读取文件信息头的函数,通过读取文件信息头,计算出实际图像数据的偏移量,再通过文件流的方式将图像数据读取出来,然后16位深转换为8位深BMP图像,并显示即可。
本实验所用libtiff库我已上传至资源中心,站内一些资源貌似都不是很全,需要的可以去下载。
http://download.csdn.net/detail/ssuperliang/8336293
- 16位TIFF灰度图像转存BMP图像总结
- 24位bmp图像转成灰度图像
- 8位灰度图像BMP的保存
- 8位灰度图像BMP的保存
- 8位灰度图像BMP的保存
- 8位灰度图像BMP的保存
- 8位灰度图像BMP的保存
- BMP图像灰度化
- BMP--24位真彩色转换为灰度图像
- 4位16色灰度图像处理
- Symbian下16位bmp图像缩放
- 图像灰度化总结
- 16位灰度图之TIFF
- 灰度图像转存入二维数组并验证
- 任意宽度灰度BMP图像读写 V1
- 任意宽度灰度BMP图像读写 V2
- BMP图像的灰度化---C++实现
- 任意宽度灰度BMP图像读写 V1
- UINavigationController和UITabBarController混用
- Fragment复习总结
- WinExec、ShellExec、CrateProcess用法及区别
- 对于Netty的十一个疑问
- rabbitmq(5)
- 16位TIFF灰度图像转存BMP图像总结
- MFC对话框与任务栏相关操作
- 程序员玩的游戏
- 彩色建模(四色原型) Object Modeling in Color
- 支持向量机SVM整理
- 函数模板——函数重载-多组数求和
- OJ刷题之1!到n!的和
- android刮刮卡的实现
- IOS动画核心 之 KeyFrameAnimation简介