opencv对tiff的保存只做了简单的封装。
使得在raw转为tiff时 有些功能没法实现。
比如设置数据压缩方式
本文使用tiff库来实现raw到tiff的转化
流程如下
下载tiflib源码包tiff-4.0.1.zip 解压到d:盘 tiff-4.0.1下
#include <tif_config.h> #include <stdio.h> #include <stdlib.h> #include <string.h> //strcmp #include <math.h> // sqrt #include <ctype.h> //isdigit #include "tiffio.h" #ifndef O_BINARY # define O_BINARY 0 #endif typedef enum { PIXEL, BAND } InterleavingType; static void swapBytesInScanline(void *, uint32, TIFFDataType); static double correlation(void *, void *, uint32, TIFFDataType); static int processCompressOptions(char*); /* 对TIFF设置压缩方式 其中opt为压缩参数 参数格式为 lzw[:opts] compress output with Lempel-Ziv & Welch encoding", zip[:opts] compress output with deflate encoding", jpeg[:opts] compress output with JPEG encoding", packbits compress output with packbits encoding", none use no compression algorithm on output", JPEG options:, " # set compression quality level (0-100, default 75)", " r output color image as RGB rather than YCbCr", "For example, jpeg:r:50 to get JPEG-encoded RGB data with 50% comp. quality", LZW and deflate options:, " # set predictor value", "For example, lzw:2 to get LZW-encoded data with horizontal differencing", nwpulei 2012-4-18 14:58:38 */ static int processCompressOptions(char* opt,TIFF *out, uint16 & photometric) //压缩参数处理 { uint16 compression = (uint16) -1; int jpegcolormode = JPEGCOLORMODE_RGB; int quality = 75; uint16 predictor = 0; if (strcmp(opt, "none") == 0) { compression = COMPRESSION_NONE; } if (strcmp(opt, "packbits") == 0) { compression = COMPRESSION_PACKBITS; } if (strncmp(opt, "jpeg", 4) == 0) { char* cp = strchr(opt, ':'); compression = COMPRESSION_JPEG; while( cp ) { if (isdigit((int)cp[1])) { quality = atoi(cp+1); } else { if (cp[1] == 'r' ) { jpegcolormode = JPEGCOLORMODE_RAW; } else { return 0; // 格式错误 } } cp = strchr(cp+1,':'); } } if (strncmp(opt, "lzw", 3) == 0) { char* cp = strchr(opt, ':'); if (cp) { predictor = atoi(cp+1); } compression = COMPRESSION_LZW; } if (strncmp(opt, "zip", 3) == 0) { char* cp = strchr(opt, ':'); if (cp) { predictor = atoi(cp+1); } compression = COMPRESSION_DEFLATE; } if (compression == (uint16) -1) // 没有设置参数 { compression = COMPRESSION_PACKBITS; } TIFFSetField(out, TIFFTAG_COMPRESSION, compression); //压缩设置 switch (compression) { case COMPRESSION_JPEG: if (photometric == PHOTOMETRIC_RGB && jpegcolormode == JPEGCOLORMODE_RGB) { photometric = PHOTOMETRIC_YCBCR; } TIFFSetField(out, TIFFTAG_JPEGQUALITY, quality); TIFFSetField(out, TIFFTAG_JPEGCOLORMODE, jpegcolormode); break; case COMPRESSION_LZW: case COMPRESSION_DEFLATE: if (predictor != 0) { TIFFSetField(out, TIFFTAG_PREDICTOR, predictor); } break; } return 1; } /* 创建TIFF文件头 输入参数包括图像的名称outfilename、宽度width、高度length、 通道数nbands、数据类型dtype、数据排列方式fillorder(大端还是小端) 宽度width、高度length、通道数nbands 为整数 dtype可用如下值 TIFF_BYTE; TIFF_SHORT; TIFF_LONG; TIFF_SBYTE; TIFF_SSHORT; TIFF_SLONG; TIFF_FLOAT; TIFF_DOUBLE; fillorder可用如下值 FILLORDER_LSB2MSB; FILLORDER_MSB2LSB 成功 返回一个TIFF* 否则 返回NULL NWPULEI 2012-4-18 14:53:22 */ TIFF *CreateTIFF(const char* outfilename,int width,int length,uint32 nbands,TIFFDataType dtype, uint16 fillorder) { uint32 rowsperstrip = (uint32) -1; uint16 photometric = PHOTOMETRIC_MINISBLACK; /* PHOTOMETRIC_MINISWHITE; PHOTOMETRIC_MINISBLACK; PHOTOMETRIC_RGB; PHOTOMETRIC_SEPARATED; PHOTOMETRIC_YCBCR; PHOTOMETRIC_CIELAB; PHOTOMETRIC_ICCLAB; PHOTOMETRIC_ITULAB; PHOTOMETRIC_MINISBLACK; */ uint16 config = PLANARCONFIG_CONTIG; int16 depth; depth = TIFFDataWidth(dtype); TIFF * out = TIFFOpen(outfilename, "w"); // TIFF 输出文件 if (out == NULL) { fprintf(stderr, "%s: Cannot open file for output.\n",outfilename); return (NULL); } //TIFF 参数设置 TIFFSetField(out, TIFFTAG_IMAGEWIDTH, width); //TIFFGetField(out, TIFFTAG_IMAGEWIDTH, &width); TIFFSetField(out, TIFFTAG_IMAGELENGTH, length); TIFFSetField(out, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT); TIFFSetField(out, TIFFTAG_SAMPLESPERPIXEL, nbands); TIFFSetField(out, TIFFTAG_BITSPERSAMPLE, depth * 8); //数据宽度 TIFFSetField(out, TIFFTAG_FILLORDER, fillorder);// 字节顺序 TIFFSetField(out, TIFFTAG_PLANARCONFIG, config); TIFFSetField(out, TIFFTAG_PHOTOMETRIC, photometric); //数据类型 设置 switch (dtype) { case TIFF_BYTE: case TIFF_SHORT: case TIFF_LONG: TIFFSetField(out, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_UINT); break; case TIFF_SBYTE: case TIFF_SSHORT: case TIFF_SLONG: TIFFSetField(out, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_INT); break; case TIFF_FLOAT: case TIFF_DOUBLE: TIFFSetField(out, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_IEEEFP); break; default: TIFFSetField(out, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_VOID); break; } char opt[]="none"; //压缩设置 processCompressOptions(opt,out, photometric); rowsperstrip = TIFFDefaultStripSize(out, rowsperstrip); if (rowsperstrip > length) { rowsperstrip = length; } TIFFSetField(out, TIFFTAG_ROWSPERSTRIP, rowsperstrip ); return out; }; int main( ) { unsigned char *buf1 = NULL; char outfilename[] = "E:\\数据\\RAW_001\\abb.tif"; //输出文件名 char inputfilename[] = "E:\\数据\\RAW_001\\HW_00002.RAW"; TIFF * out = NULL; uint32 width = 11510; uint32 length = 480; TIFFDataType dtype = TIFF_SHORT; uint32 nbands = 1;//通道数 uint16 fillorder = FILLORDER_LSB2MSB; out = CreateTIFF(outfilename, width, length, nbands, dtype,fillorder); FILE *pf = NULL; pf = fopen(inputfilename,"rb"); // 打开raw文件 if (pf == NULL) { fprintf(stderr, "%s: Cannot open input file.\n", inputfilename); return (-1); } int16 depth = 1; depth = TIFFDataWidth(dtype); uint32 linebytes,bufsize; bufsize = width * nbands * depth; buf1 = (unsigned char *)_TIFFmalloc(bufsize);// 分配存储空间 /* _TIFFmalloc 内部就是仅仅调用了 malloc 没有其他任何多余的操作 因此 这里的空间分配 你可以随意 */ uint32 row, col; for (row = 0; row < length; row++) { if (fread(buf1,bufsize, 1, pf) < 0) { fprintf(stderr,"%s: scanline %lu: Read error.\n",inputfilename, (unsigned long) row); break; } if (TIFFWriteScanline(out, buf1, row, 0) < 0) // 写数据到tiff图像的row行 { fprintf(stderr, " %s: scanline %lu: Write error.\n",outfilename, (unsigned long) row); break; } } if (buf1) { _TIFFfree(buf1); } fclose(pf); TIFFClose(out); return (0); } static void swapBytesInScanline(void *buf, uint32 width, TIFFDataType dtype) { switch (dtype) { case TIFF_SHORT: case TIFF_SSHORT: TIFFSwabArrayOfShort((uint16*)buf,(unsigned long)width); break; case TIFF_LONG: case TIFF_SLONG: TIFFSwabArrayOfLong((uint32*)buf,(unsigned long)width); break; /* case TIFF_FLOAT: */ /* FIXME */ case TIFF_DOUBLE: TIFFSwabArrayOfDouble((double*)buf, (unsigned long)width); break; default: break; } } /* Calculate correlation coefficient between two numeric vectors */ static double correlation(void *buf1, void *buf2, uint32 n_elem, TIFFDataType dtype) { double X, Y, M1 = 0.0, M2 = 0.0, D1 = 0.0, D2 = 0.0, K = 0.0; uint32 i; switch (dtype) { case TIFF_BYTE: default: for (i = 0; i < n_elem; i++) { X = ((unsigned char *)buf1)[i]; Y = ((unsigned char *)buf2)[i]; M1 += X, M2 += Y; D1 += X * X, D2 += Y * Y; K += X * Y; } break; case TIFF_SBYTE: for (i = 0; i < n_elem; i++) { X = ((signed char *)buf1)[i]; Y = ((signed char *)buf2)[i]; M1 += X, M2 += Y; D1 += X * X, D2 += Y * Y; K += X * Y; } break; case TIFF_SHORT: for (i = 0; i < n_elem; i++) { X = ((uint16 *)buf1)[i]; Y = ((uint16 *)buf2)[i]; M1 += X, M2 += Y; D1 += X * X, D2 += Y * Y; K += X * Y; } break; case TIFF_SSHORT: for (i = 0; i < n_elem; i++) { X = ((int16 *)buf1)[i]; Y = ((int16 *)buf2)[i]; M1 += X, M2 += Y; D1 += X * X, D2 += Y * Y; K += X * Y; } break; case TIFF_LONG: for (i = 0; i < n_elem; i++) { X = ((uint32 *)buf1)[i]; Y = ((uint32 *)buf2)[i]; M1 += X, M2 += Y; D1 += X * X, D2 += Y * Y; K += X * Y; } break; case TIFF_SLONG: for (i = 0; i < n_elem; i++) { X = ((int32 *)buf1)[i]; Y = ((int32 *)buf2)[i]; M1 += X, M2 += Y; D1 += X * X, D2 += Y * Y; K += X * Y; } break; case TIFF_FLOAT: for (i = 0; i < n_elem; i++) { X = ((float *)buf1)[i]; Y = ((float *)buf2)[i]; M1 += X, M2 += Y; D1 += X * X, D2 += Y * Y; K += X * Y; } break; case TIFF_DOUBLE: for (i = 0; i < n_elem; i++) { X = ((double *)buf1)[i]; Y = ((double *)buf2)[i]; M1 += X, M2 += Y; D1 += X * X, D2 += Y * Y; K += X * Y; } break; } M1 /= n_elem; M2 /= n_elem; D1 -= M1 * M1 * n_elem; D2 -= M2 * M2 * n_elem; K = (K - M1 * M2 * n_elem) / sqrt(D1 * D2); return K; } static char* stuff[] = { "raw2tiff --- tool for converting raw byte sequences in TIFF images", "usage: raw2tiff [options] input.raw output.tif", "where options are:", " -L input data has LSB2MSB bit order (default)", " -M input data has MSB2LSB bit order", " -r # make each strip have no more than # rows", " -H # size of input image file header in bytes (0 by default)", " -w # width of input image in pixels", " -l # length of input image in lines", " -b # number of bands in input image (1 by default)", "", " -d data_type type of samples in input image", "where data_type may be:", " byte 8-bit unsigned integer (default)", " short 16-bit unsigned integer", " long 32-bit unsigned integer", " sbyte 8-bit signed integer", " sshort 16-bit signed integer", " slong 32-bit signed integer", " float 32-bit IEEE floating point", " double 64-bit IEEE floating point", "", " -p photo photometric interpretation (color space) of the input image", "where photo may be:", " miniswhite white color represented with 0 value", " minisblack black color represented with 0 value (default)", " rgb image has RGB color model", " cmyk image has CMYK (separated) color model", " ycbcr image has YCbCr color model", " cielab image has CIE L*a*b color model", " icclab image has ICC L*a*b color model", " itulab image has ITU L*a*b color model", "", " -s swap bytes fetched from input file", "", " -i config type of samples interleaving in input image", "where config may be:", " pixel pixel interleaved data (default)", " band band interleaved data", "", " -o out.tif write output to out.tif", " -h this help message", NULL };
编译环境为vs2008
上面的代码是在tiff-4.0.1文件夹的tools中的raw2tiff.c基础上修改的
主要是
1.重新封装了CreateTiff()写文件比较方便
2. 重新封装 processCompressOptions
3.简化了测试程序
使用vs2008编译好的库 可以在这里下载