📄 tiffcp.c
字号:
{ TIFFTAG_STONITS, 1, TIFF_DOUBLE },};#define NTAGS (sizeof (tags) / sizeof (tags[0]))#define CopyTag(tag, count, type) cpTag(in, out, tag, count, type)typedef int (*copyFunc) (TIFF* in, TIFF* out, uint32 l, uint32 w, uint16 samplesperpixel);static copyFunc pickCopyFunc(TIFF*, TIFF*, uint16, uint16);static inttiffcp(TIFF* in, TIFF* out){ uint16 bitspersample, samplesperpixel; uint16 input_compression; copyFunc cf; uint32 width, length; struct cpTag* p; CopyField(TIFFTAG_IMAGEWIDTH, width); CopyField(TIFFTAG_IMAGELENGTH, length); CopyField(TIFFTAG_BITSPERSAMPLE, bitspersample); CopyField(TIFFTAG_SAMPLESPERPIXEL, samplesperpixel); if (compression != (uint16)-1) TIFFSetField(out, TIFFTAG_COMPRESSION, compression); else CopyField(TIFFTAG_COMPRESSION, compression); if (compression == COMPRESSION_JPEG) { if ( TIFFGetField( in, TIFFTAG_COMPRESSION, &input_compression ) && input_compression == COMPRESSION_JPEG ) { TIFFSetField(in, TIFFTAG_JPEGCOLORMODE, JPEGCOLORMODE_RGB); } if (jpegcolormode == JPEGCOLORMODE_RGB) TIFFSetField(out, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_YCBCR); else TIFFSetField(out, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB); } else if (compression == COMPRESSION_SGILOG || compression == COMPRESSION_SGILOG24) TIFFSetField(out, TIFFTAG_PHOTOMETRIC, samplesperpixel == 1 ? PHOTOMETRIC_LOGL : PHOTOMETRIC_LOGLUV); else CopyTag(TIFFTAG_PHOTOMETRIC, 1, TIFF_SHORT); if (fillorder != 0) TIFFSetField(out, TIFFTAG_FILLORDER, fillorder); else CopyTag(TIFFTAG_FILLORDER, 1, TIFF_SHORT); /* * Will copy `Orientation' tag from input image */ TIFFGetField(in, TIFFTAG_ORIENTATION, &orientation); switch (orientation) { case ORIENTATION_BOTRIGHT: case ORIENTATION_RIGHTBOT: /* XXX */ case ORIENTATION_LEFTBOT: /* XXX */ TIFFWarning(TIFFFileName(in), "using bottom-left orientation"); orientation = ORIENTATION_BOTLEFT; /* fall thru... */ case ORIENTATION_BOTLEFT: break; case ORIENTATION_TOPRIGHT: case ORIENTATION_RIGHTTOP: /* XXX */ case ORIENTATION_LEFTTOP: /* XXX */ default: TIFFWarning(TIFFFileName(in), "using top-left orientation"); orientation = ORIENTATION_TOPLEFT; /* fall thru... */ case ORIENTATION_TOPLEFT: break; } TIFFSetField(out, TIFFTAG_ORIENTATION, orientation); /* * Choose tiles/strip for the output image according to * the command line arguments (-tiles, -strips) and the * structure of the input image. */ if (outtiled == -1) outtiled = TIFFIsTiled(in); if (outtiled) { /* * Setup output file's tile width&height. If either * is not specified, use either the value from the * input image or, if nothing is defined, use the * library default. */ if (tilewidth == (uint32) -1) TIFFGetField(in, TIFFTAG_TILEWIDTH, &tilewidth); if (tilelength == (uint32) -1) TIFFGetField(in, TIFFTAG_TILELENGTH, &tilelength); TIFFDefaultTileSize(out, &tilewidth, &tilelength); TIFFSetField(out, TIFFTAG_TILEWIDTH, tilewidth); TIFFSetField(out, TIFFTAG_TILELENGTH, tilelength); } else { /* * RowsPerStrip is left unspecified: use either the * value from the input image or, if nothing is defined, * use the library default. */ if (rowsperstrip == (uint32) 0) { if (!TIFFGetField(in, TIFFTAG_ROWSPERSTRIP,&rowsperstrip)) rowsperstrip = TIFFDefaultStripSize(out, rowsperstrip); } else if (rowsperstrip == (uint32) -1) rowsperstrip = length; TIFFSetField(out, TIFFTAG_ROWSPERSTRIP, rowsperstrip); } if (config != (uint16) -1) TIFFSetField(out, TIFFTAG_PLANARCONFIG, config); else CopyField(TIFFTAG_PLANARCONFIG, config); if (samplesperpixel <= 4) CopyTag(TIFFTAG_TRANSFERFUNCTION, 4, TIFF_SHORT); CopyTag(TIFFTAG_COLORMAP, 4, TIFF_SHORT);/* SMinSampleValue & SMaxSampleValue */ switch (compression) { case COMPRESSION_JPEG: TIFFSetField(out, TIFFTAG_JPEGQUALITY, quality); TIFFSetField(out, TIFFTAG_JPEGCOLORMODE, jpegcolormode); break; case COMPRESSION_LZW: case COMPRESSION_DEFLATE: if (predictor != (uint16)-1) TIFFSetField(out, TIFFTAG_PREDICTOR, predictor); else CopyField(TIFFTAG_PREDICTOR, predictor); break; case COMPRESSION_CCITTFAX3: case COMPRESSION_CCITTFAX4: if (compression == COMPRESSION_CCITTFAX3) { if (g3opts != (uint32) -1) TIFFSetField(out, TIFFTAG_GROUP3OPTIONS, g3opts); else CopyField(TIFFTAG_GROUP3OPTIONS, g3opts); } else CopyTag(TIFFTAG_GROUP4OPTIONS, 1, TIFF_LONG); CopyTag(TIFFTAG_BADFAXLINES, 1, TIFF_LONG); CopyTag(TIFFTAG_CLEANFAXDATA, 1, TIFF_LONG); CopyTag(TIFFTAG_CONSECUTIVEBADFAXLINES, 1, TIFF_LONG); CopyTag(TIFFTAG_FAXRECVPARAMS, 1, TIFF_LONG); CopyTag(TIFFTAG_FAXRECVTIME, 1, TIFF_LONG); CopyTag(TIFFTAG_FAXSUBADDRESS, 1, TIFF_ASCII); break; } { uint32 len32; void** data; if (TIFFGetField(in, TIFFTAG_ICCPROFILE, &len32, &data)) TIFFSetField(out, TIFFTAG_ICCPROFILE, len32, data); } { unsigned short pg0, pg1; if (TIFFGetField(in, TIFFTAG_PAGENUMBER, &pg0, &pg1)) if (pageNum < 0) // only one input file TIFFSetField(out, TIFFTAG_PAGENUMBER, pg0, pg1); else TIFFSetField(out, TIFFTAG_PAGENUMBER, pageNum++, 0); } for (p = tags; p < &tags[NTAGS]; p++) CopyTag(p->tag, p->count, p->type); cf = pickCopyFunc(in, out, bitspersample, samplesperpixel); return (cf ? (*cf)(in, out, length, width, samplesperpixel) : FALSE);}/* * Copy Functions. */#define DECLAREcpFunc(x) \static int x(TIFF* in, TIFF* out, \ uint32 imagelength, uint32 imagewidth, tsample_t spp)#define DECLAREreadFunc(x) \static void x(TIFF* in, \ uint8* buf, uint32 imagelength, uint32 imagewidth, tsample_t spp)typedef void (*readFunc)(TIFF*, uint8*, uint32, uint32, tsample_t);#define DECLAREwriteFunc(x) \static int x(TIFF* out, \ uint8* buf, uint32 imagelength, uint32 imagewidth, tsample_t spp)typedef int (*writeFunc)(TIFF*, uint8*, uint32, uint32, tsample_t);/* * Contig -> contig by scanline for rows/strip change. */DECLAREcpFunc(cpContig2ContigByRow){ tdata_t buf = _TIFFmalloc(TIFFScanlineSize(in)); uint32 row; (void) imagewidth; (void) spp; for (row = 0; row < imagelength; row++) { if (TIFFReadScanline(in, buf, row, 0) < 0 && !ignore) goto done; if (TIFFWriteScanline(out, buf, row, 0) < 0) goto bad; }done: _TIFFfree(buf); return (TRUE);bad: _TIFFfree(buf); return (FALSE);}typedef void biasFn (void *image, void *bias, uint32 pixels);#define subtract(bits) \static void subtract##bits (void *i, void *b, uint32 pixels)\{\ uint##bits *image = i;\ uint##bits *bias = b;\ while (pixels--) {\ *image = *image > *bias ? *image-*bias : 0;\ image++, bias++; \ } \}subtract(8)subtract(16)subtract(32)static biasFn *lineSubtractFn (unsigned bits){ switch (bits) { case 8: return subtract8; case 16: return subtract16; case 32: return subtract32; } return NULL;}/* * Contig -> contig by scanline while subtracting a bias image. */DECLAREcpFunc(cpBiasedContig2Contig){ if (spp == 1) { tsize_t biasSize = TIFFScanlineSize(bias); tsize_t bufSize = TIFFScanlineSize(in); tdata_t buf, biasBuf; uint32 biasWidth = 0, biasLength = 0; TIFFGetField(bias, TIFFTAG_IMAGEWIDTH, &biasWidth); TIFFGetField(bias, TIFFTAG_IMAGELENGTH, &biasLength); if (biasSize == bufSize && imagelength == biasLength && imagewidth == biasWidth) { uint16 sampleBits = 0; biasFn *subtractLine; TIFFGetField(in, TIFFTAG_BITSPERSAMPLE, &sampleBits); subtractLine = lineSubtractFn (sampleBits); if (subtractLine) { uint32 row; buf = _TIFFmalloc(bufSize); biasBuf = _TIFFmalloc(bufSize); for (row = 0; row < imagelength; row++) { if (TIFFReadScanline(in, buf, row, 0) < 0 && !ignore) break; if (TIFFReadScanline(bias, biasBuf, row, 0) < 0 && !ignore) break; subtractLine (buf, biasBuf, imagewidth); if (TIFFWriteScanline(out, buf, row, 0) < 0) { _TIFFfree(buf); _TIFFfree(biasBuf); return FALSE; } } _TIFFfree(buf); _TIFFfree(biasBuf); TIFFSetDirectory (bias, TIFFCurrentDirectory(bias)); /* rewind */ return TRUE; }else{ fprintf (stderr, "No support for biasing %d bit pixels\n", sampleBits); return FALSE; } } fprintf (stderr,"Bias image %s,%d\nis not the same size as %s,%d\n", TIFFFileName(bias), TIFFCurrentDirectory(bias), TIFFFileName(in), TIFFCurrentDirectory(in)); return FALSE; }else{ fprintf (stderr, "Can't bias %s,%d as it has >1 Sample/Pixel\n", TIFFFileName(in), TIFFCurrentDirectory(in)); return FALSE; }}/* * Strip -> strip for change in encoding. */DECLAREcpFunc(cpDecodedStrips){ tsize_t stripsize = TIFFStripSize(in); tdata_t buf = _TIFFmalloc(stripsize); (void) imagewidth; (void) spp; if (buf) { tstrip_t s, ns = TIFFNumberOfStrips(in); uint32 row = 0; for (s = 0; s < ns; s++) { tsize_t cc = (row + rowsperstrip > imagelength) ? TIFFVStripSize(in, imagelength - row) : stripsize; if (TIFFReadEncodedStrip(in, s, buf, cc) < 0 && !ignore) break; if (TIFFWriteEncodedStrip(out, s, buf, cc) < 0) { _TIFFfree(buf); return (FALSE); } row += rowsperstrip; } _TIFFfree(buf); return (TRUE); } return (FALSE);}/* * Separate -> separate by row for rows/strip change. */DECLAREcpFunc(cpSeparate2SeparateByRow){ tdata_t buf = _TIFFmalloc(TIFFScanlineSize(in)); uint32 row; tsample_t s; (void) imagewidth; for (s = 0; s < spp; s++) { for (row = 0; row < imagelength; row++) { if (TIFFReadScanline(in, buf, row, s) < 0 && !ignore) goto done; if (TIFFWriteScanline(out, buf, row, s) < 0) goto bad; } }done: _TIFFfree(buf); return (TRUE);bad: _TIFFfree(buf); return (FALSE);}/* * Contig -> separate by row. */DECLAREcpFunc(cpContig2SeparateByRow){ tdata_t inbuf = _TIFFmalloc(TIFFScanlineSize(in)); tdata_t outbuf = _TIFFmalloc(TIFFScanlineSize(out)); register uint8 *inp, *outp; register uint32 n; uint32 row; tsample_t s; /* unpack channels */ for (s = 0; s < spp; s++) { for (row = 0; row < imagelength; row++) { if (TIFFReadScanline(in, inbuf, row, 0) < 0 && !ignore) goto done; inp = ((uint8*)inbuf) + s; outp = (uint8*)outbuf; for (n = imagewidth; n-- > 0;) { *outp++ = *inp; inp += spp; } if (TIFFWriteScanline(out, outbuf, row, s) < 0) goto bad; } }done: if (inbuf) _TIFFfree(inbuf); if (outbuf) _TIFFfree(outbuf); return (TRUE);bad: if (inbuf) _TIFFfree(inbuf); if (outbuf) _TIFFfree(outbuf); return (FALSE);}/* * Separate -> contig by row. */DECLAREcpFunc(cpSeparate2ContigByRow){ tdata_t inbuf = _TIFFmalloc(TIFFScanlineSize(in)); tdata_t outbuf = _TIFFmalloc(TIFFScanlineSize(out)); register uint8 *inp, *outp; register uint32 n; uint32 row; tsample_t s; for (row = 0; row < imagelength; row++) { /* merge channels */ for (s = 0; s < spp; s++) { if (TIFFReadScanline(in, inbuf, row, s) < 0 && !ignore) goto done; inp = (uint8*)inbuf; outp = ((uint8*)outbuf) + s; for (n = imagewidth; n-- > 0;) { *outp = *inp++; outp += spp; } } if (TIFFWriteScanline(out, outbuf, row, 0) < 0) goto bad; }done: if (inbuf) _TIFFfree(inbuf); if (outbuf) _TIFFfree(outbuf); return (TRUE);bad: if (inbuf) _TIFFfree(inbuf); if (outbuf) _TIFFfree(outbuf); return (FALSE);}static voidcpStripToTile(uint8* out, uint8* in, uint32 rows, uint32 cols, int outskew, int inskew){ while (rows-- > 0) { uint32 j = cols; while (j-- > 0) *out++ = *in++; out += outskew; in += inskew; }}static voidcpContigBufToSeparateBuf(uint8* out, uint8* in, uint32 rows, uint32 cols, int outskew, int inskew, tsample_t spp, int bytes_per_sample ){ while (rows-- > 0) { uint32 j = cols; while (j-- > 0) { int n = bytes_per_sample; while( n-- ) { *out++ = *in++; } in += (spp-1) * bytes_per_sample; } out += outskew; in += inskew; }}static voidcpSeparateBufToContigBuf(uint8* out, uint8* in, uint32 rows, uint32 cols, int outskew, int inskew, tsample_t spp, int bytes_per_sample){ while (rows-- > 0) { uint32 j = cols; while (j-- > 0) { int n = bytes_per_sample; while( n-- ) { *out++ = *in++; } out += (spp-1)*bytes_per_sample; } out += outskew; in += inskew; }}static intcpImage(TIFF* in, TIFF* out, readFunc fin, writeFunc fout, uint32 imagelength, uint32 imagewidth, tsample_t spp){ int status = FALSE; tdata_t buf = _TIFFmalloc(TIFFRasterScanlineSize(in) * imagelength); if (buf) { (*fin)(in, (uint8*)buf, imagelength, imagewidth, spp); status = (fout)(out, (uint8*)buf, imagelength, imagewidth, spp); _TIFFfree(buf); } return (status);}DECLAREreadFunc(readContigStripsIntoBuffer){ tsize_t scanlinesize = TIFFScanlineSize(in); uint8* bufp = buf; uint32 row; (void) imagewidth; (void) spp; for (row = 0; row < imagelength; row++) { if (TIFFReadScanline(in, (tdata_t) bufp, row, 0) < 0 && !ignore) break; bufp += scanlinesize; }}DECLAREreadFunc(readSeparateStripsIntoBuffer){ tsize_t scanlinesize = TIFFScanlineSize(in); tdata_t scanline = _TIFFmalloc(scanlinesize); (void) imagewidth; if (scanline) { uint8* bufp = (uint8*) buf; uint32 row; tsample_t s; for (row = 0; row < imagelength; row++) { /* merge channels */ for (s = 0; s < spp; s++) { uint8* bp = bufp + s;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -