opencv对tiff的保存只做了简单的封装。
使得在raw转为tiff时 有些功能没法实现。
比如设置数据压缩方式
本文使用tiff库来实现raw到tiff的转化
流程如下
下载tiflib源码包tiff-4.0.1.zip 解压到d:盘 tiff-4.0.1下
#include
#include
#include
#include //strcmp
#include // sqrt
#include //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编译好的库 可以在这里下载