libTIFF 图像读取与保存
2015-11-15 12:54
267 查看
本系列文章由 @YhL_Leo 出品,转载请注明出处。
文章链接: http://blog.csdn.net/YhL_Leo/article/details/49848391
不同于
下面列出几种常用的
以
如果想把4通道
创建并保存4通道
这段代码读取了两张图像,一张为灰度图,另一张为对应的
Scanline-based
Strip-oriented
Tile-oriented
此处不做过的介绍,详情请阅读 Using The TIFF Library~
Opencv中也有对
PS:
LibTIFF (libtiff.org)
LibTIFF (remotesensing.org)
TIFF Documentation
文章链接: http://blog.csdn.net/YhL_Leo/article/details/49848391
1 头文件
libtiff定义一系列C语言类型的数据结构,调用时包含的头文件为:
[code]#include "tiffio.h"
2 文件读写
[code]/* read from an existing TIFF image */ void main() { TIFF* tif = TIFFOpen("foo.tif", "r"); ... do stuff ... TIFFClose(tif); // or TIFFFlush(tif); } /* create or overwrite a TIFF image */ void main() { TIFF* tif = TIFFOpen("foo.tif", "w"); ... do stuff ... TIFFClose(tif); // or TIFFFlush(tif); }
不同于
stdio library对TIFF文件的操作可以同时支持读和写,
libtiff对于
TIFF文件的操作模式是不可变更的,也就是说对一个指定的
TIFF文件,一次只能支持对文件的读或写中的一种操作。
3 多目录文件读写
TIFF格式支持将多个图像文件存储为一个文件的功能,每个图片都有一个对应的数据结构称为一个目录,其中包括全部的信息格式和图像数据内容。图像之间可以是相关的也可以使不相关的。
[code]#include "tiffio.h" int main(int argc, char* argv[]) { TIFF* tif = TIFFOpen(argv[1], "r"); if (tif) { int dircount = 0; do { dircount++; } while (TIFFReadDirectory(tif)); printf("%d directories in %s\n", dircount, argv[1]); TIFFClose(tif); } return 0; } // write: TIFFWriteDirectory()
4 标签读取与设置
图像相关的信息例如宽、高、通道数、定向信息、颜色信息等。libtiff中提供了获取和设置标签值的函数:
TIFFGetField和
TIFFSetField:
[code]/* read the tags */ uint32 width, height; uint16 ncn; TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &width); // image width in pixels TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &height); // image height in pixels TIFFGetField(tif, TIFFTAG_SAMPLESPERPIXEL, &ncn); // samples per pixel -> channels cout << width << " " << height << " " << ncn << endl; /* set the tags */ TIFFSetField( imageWrite, TIFFTAG_IMAGEWIDTH, width ); TIFFSetField( imageWrite, TIFFTAG_IMAGELENGTH, height ); TIFFSetField( imageWrite, TIFFTAG_BITSPERSAMPLE, 8); // 8 bits per channel TIFFSetField( imageWrite, TIFFTAG_SAMPLESPERPIXEL, 4); // 4 channels
下面列出几种常用的
TIFF图像信息标签:
[code]#define TIFFTAG_IMAGEWIDTH 256 /* image width in pixels */ #define TIFFTAG_IMAGELENGTH 257 /* image height in pixels */ #define TIFFTAG_BITSPERSAMPLE 258 /* bits per channel (sample) */ #define TIFFTAG_SAMPLESPERPIXEL 277 /* samples per pixel */ #define TIFFTAG_COMPRESSION 259 /* data compression technique */ #define TIFFTAG_PHOTOMETRIC 262 /* photometric interpretation */ #define TIFFTAG_PLANARCONFIG 284 /* storage organization */ #define TIFFTAG_XRESOLUTION 282 /* pixels/resolution in x */ #define TIFFTAG_YRESOLUTION 283 /* pixels/resolution in y */ #define TIFFTAG_RESOLUTIONUNIT 296 /* units of resolutions */
5 RGBA 图像读取与存储
对于4通道的图像,libtiff提供的数据颜色顺序为A B G R,并且整合为32-bit无符号整型数据(每个通道为8 bits),数据读取方法为使用
TIFFReadRGBAImage函数:
[code]#include "tiffio.h" // first method: TIFFReadRGBAImage int main(int argc, char* argv[]) { TIFF* tif = TIFFOpen(argv[1], "r"); if (tif) { uint32 w, h; size_t npixels; uint32* raster; TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &w); TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &h); npixels = w * h; raster = (uint32*) _TIFFmalloc(npixels * sizeof (uint32)); if (raster != NULL) { if (TIFFReadRGBAImage(tif, w, h, raster, 0)) { ...process raster data... } _TIFFfree(raster); } TIFFClose(tif); } return 0; } // second method: TIFFRGBAImageBegin & TIFFRGBAImageGet int main(int argc, char* argv[]) { TIFF* tif = TIFFOpen(argv[1], "r"); if (tif) { TIFFRGBAImage img; char emsg[1024]; if (TIFFRGBAImageBegin(&img, tif, 0, emsg)) { size_t npixels; uint32* raster; npixels = img.width * img.height; raster = (uint32*) _TIFFmalloc(npixels * sizeof (uint32)); if (raster != NULL) { if (TIFFRGBAImageGet(&img, raster, img.width, img.height)) { ...process raster data... } _TIFFfree(raster); } TIFFRGBAImageEnd(&img); } else TIFFError(argv[1], emsg); TIFFClose(tif); } return 0; }
以
TIFFReadRGBAImage为例,读取图像后,获得其某一通道的结果,可使用:
[code]// image channel read order : A B G R if ( TIFFReadRGBAImage(tif, width, height, raster, 0) ) { BYTE *imageR = new BYTE[nPixels]; // image pixels are in an inverted order, which is same as bmp format uint32* rowPoint2Src = raster + (height-1)*width; BYTE *rowPointerToR = imageR; for ( int rows = height-1; rows >= 0; --rows ) { uint32 *colPoint2Src = rowPoint2Src; BYTE* colPoint2R = rowPointerToR; for ( int cols = 0; cols < width; cols ++ ) { // read the channel : A *colPoint2R = (BYTE)TIFFGetA(*colPoint2Src); // or : colPoint2R[0] = (BYTE)TIFFGetA(colPoint2Src[0]); colPoint2R++; colPoint2Src++; } rowPoint2Src -= width; rowPointerToR += width; } cv::Mat imageR_mat( height, width, CV_8UC1, imageR, width ); imwrite("E:\\0-Alpha.jpg", imageR_mat); _TIFFfree(imageR); }
如果想把4通道
TIFF文件,读入内存后转为
Mat格式,可以这么做:
[code]/* save as a Mat */ cv::Mat image(height, width, CV_8UC4, cv::Scalar::all(0)); if ( TIFFReadRGBAImage(tif, width, height, raster, 0) ) { uchar* imageData = (uchar*)image.data; uint32* rowPoint2Src = raster + (height-1)*width; for ( int rows = height-1; rows >= 0; --rows ) { uint32 *colPoint2Src = rowPoint2Src; // image pixels are in an inverted order, which is same as bmp format uchar* colPoint = image.ptr<uchar>( height - rows - 1 ); for ( int cols = 0; cols < width; cols ++ ) { *colPoint++ = (uchar)TIFFGetB(*colPoint2Src); // B *colPoint++ = (uchar)TIFFGetG(*colPoint2Src); // G *colPoint++ = (uchar)TIFFGetR(*colPoint2Src); // R *colPoint++ = (uchar)TIFFGetA(*colPoint2Src); // A colPoint2Src++; } rowPoint2Src -= width; } }
创建并保存4通道
TIFF图像可以按照下面的方法:
[code]/* creat and write a ABGR tiff image */ #include <iostream> #include <vector> #include "cv.h" #include "highgui.h" #include "tiffio.h" using namespace std; using namespace cv; void main() { cv::Mat imageGray = cv::imread( "C:\\Users\\Leo\\Desktop\\Test\\0.jpg" ); cv::Mat imageAlpha = cv::imread( "C:\\Users\\Leo\\Desktop\\Test\\0-R.jpg" ); if ( imageGray.channels() == 3 ) cv::cvtColor( imageGray, imageGray, CV_RGB2GRAY ); if ( imageAlpha.channels() == 3 ) cv::cvtColor( imageAlpha, imageAlpha, CV_RGB2GRAY ); int cols = imageGray.cols; int rows = imageGray.rows; cv::Mat imageMerged(rows, cols, CV_8UC4, cv::Scalar::all(0)); uchar* data = (uchar*) imageMerged.data; uchar* data_gray = (uchar*) imageGray.data; uchar* data_alpha = (uchar*) imageAlpha.data; for ( int i=0; i<rows; i++ ) { for ( int j=0; j<cols; j++ ) { int index = i*cols + j; data[index*4] = data_gray[index]; data[index*4+1] = data_gray[index]; data[index*4+2] = data_gray[index]; data[index*4+3] = data_alpha[index]; } } uint32 width, height; width = cols; height = rows; /* save as PNG */ std::vector<int> compression_params; compression_params.push_back(CV_IMWRITE_PNG_COMPRESSION); compression_params.push_back(9); cv::imwrite( "C:\\Users\\Leo\\Desktop\\Test\\0-1.png", imageMerged, compression_params ); /* save as TIFF */ TIFF *imageWrite = TIFFOpen( "C:\\Users\\Leo\\Desktop\\Test\\0-2.tif", "w" ); if ( imageWrite ) { TIFFSetField( imageWrite, TIFFTAG_IMAGEWIDTH, width ); TIFFSetField( imageWrite, TIFFTAG_IMAGELENGTH, height ); TIFFSetField( imageWrite, TIFFTAG_COMPRESSION, COMPRESSION_PACKBITS); TIFFSetField( imageWrite, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG); TIFFSetField( imageWrite, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB); TIFFSetField( imageWrite, TIFFTAG_BITSPERSAMPLE, 8); TIFFSetField( imageWrite, TIFFTAG_SAMPLESPERPIXEL, 4); uchar *bits = (uchar*) imageMerged.data; // uchar* pdst = new uchar[cols*4]; for ( int i=0; i<rows; i++ ) { // int curidx_bit = i * cols * 4; // for ( int idx = 0; idx < cols; idx ++ ) // { // int curidx_dst = idx * 4; // int curidx_bit2 = curidx_bit + curidx_dst; // // pdst[curidx_dst] = bits[curidx_bit2]; // pdst[curidx_dst+1] = bits[curidx_bit2+1]; // pdst[curidx_dst+2] = bits[curidx_bit2+2]; // pdst[curidx_dst+3] = bits[curidx_bit2+3]; // } TIFFWriteScanline( imageWrite, &bits[i*cols*4], i, 0 ); // TIFFWriteScanline( imageWrite, pdst, i, 0 ); } TIFFClose( imageWrite ); } else { std::cout << "Open file error!" << std::endl; exit(1); } }
这段代码读取了两张图像,一张为灰度图,另一张为对应的
Alpha通道图像,然后将其转换为
RGBA图像。代码里给出了
TIFFWriteScanline写
TIFF的两种方法,其中注释掉的部分即为另一种方法。
6 三种图像I/O读写方法
libTIFF中提供了三种文件读写方式:
Scanline-based
Strip-oriented
Tile-oriented
此处不做过的介绍,详情请阅读 Using The TIFF Library~
Opencv中也有对
TIFF文件的操作,也是基于
libTIFF库,详情参考文件:
grfmt_tiff.cpp。
PS:
LibTIFF (libtiff.org)
LibTIFF (remotesensing.org)
TIFF Documentation
相关文章推荐
- 基础树状数组
- Windows下Fortran编译Lapack库及使用的方法(转自新浪)
- 设计一款给父母用的手机
- 支付宝支付--手机支付(转)
- ALM
- iOS开发之简单加法计算器
- 解决IE(IE6/IE7/IE8)不兼容HTML5标签的方法
- (java)Remove Duplicates from Sorted List
- 使用jQuery的validation插件来完成表单的验证
- 致失去的五年
- GDAL命令行入门
- 半监督学习小结
- 6.2 自定义异常的学习
- 洛谷1021 邮票面值设计
- java_12-24-part three
- 与欧姆龙PLC以太网通信学习总结
- 【Alpha阶段】测试报告
- 【VMCloud云平台】私有云门户第一朵Web云(一)
- rsync 不真正同步,只显示更新的内容
- LeetCode-Add and Search Word - Data structure design