📄 tiff2ps.c
字号:
/* $Header: /cvsroot/osrs/libtiff/tools/tiff2ps.c,v 1.21 2003/12/19 15:30:27 dron Exp $ *//* * Copyright (c) 1988-1997 Sam Leffler * Copyright (c) 1991-1997 Silicon Graphics, Inc. * * Permission to use, copy, modify, distribute, and sell this software and * its documentation for any purpose is hereby granted without fee, provided * that (i) the above copyright notices and this permission notice appear in * all copies of the software and related documentation, and (ii) the names of * Sam Leffler and Silicon Graphics may not be used in any advertising or * publicity relating to the software without the specific, prior written * permission of Sam Leffler and Silicon Graphics. * * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. * * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE * OF THIS SOFTWARE. */#include <stdio.h>#include <stdlib.h> /* for atof */#include <math.h>#include <time.h>#include <string.h>#include "tiffio.h"/* * Revision history * * 2001-Mar-21 * I (Bruce A. Mallett) added this revision history comment ;) * * Fixed PS_Lvl2page() code which outputs non-ASCII85 raw * data. Moved test for when to output a line break to * *after* the output of a character. This just serves * to fix an eye-nuisance where the first line of raw * data was one character shorter than subsequent lines. * * Added an experimental ASCII85 encoder which can be used * only when there is a single buffer of bytes to be encoded. * This version is much faster at encoding a straight-line * buffer of data because it can avoid alot of the loop * overhead of the byte-by-bye version. To use this version * you need to define EXP_ASCII85ENCODER (experimental ...). * * Added bug fix given by Michael Schmidt to PS_Lvl2page() * in which an end-of-data marker ('>') was not being output * when producing non-ASCII85 encoded PostScript Level 2 * data. * * Fixed PS_Lvl2colorspace() so that it no longer assumes that * a TIFF having more than 2 planes is a CMYK. This routine * no longer looks at the samples per pixel but instead looks * at the "photometric" value. This change allows support of * CMYK TIFFs. * * Modified the PostScript L2 imaging loop so as to test if * the input stream is still open before attempting to do a * flushfile on it. This was done because some RIPs close * the stream after doing the image operation. * * Got rid of the realloc() being done inside a loop in the * PSRawDataBW() routine. The code now walks through the * byte-size array outside the loop to determine the largest * size memory block that will be needed. * * Added "-m" switch to ask tiff2ps to, where possible, use the * "imagemask" operator instead of the "image" operator. * * Added the "-i #" switch to allow interpolation to be disabled. * * Unrolled a loop or two to improve performance. *//* * Define EXP_ASCII85ENCODER if you want to use an experimental * version of the ASCII85 encoding routine. The advantage of * using this routine is that tiff2ps will convert to ASCII85 * encoding at between 3 and 4 times the speed as compared to * using the old (non-experimental) encoder. The disadvantage * is that you will be using a new (and unproven) encoding * routine. So user beware, you have been warned! */#define EXP_ASCII85ENCODER/* * NB: this code assumes uint32 works with printf's %l[ud]. */#ifndef TRUE#define TRUE 1#define FALSE 0#endifint ascii85 = FALSE; /* use ASCII85 encoding */int interpolate = TRUE; /* interpolate level2 image */int level2 = FALSE; /* generate PostScript level 2 */int level3 = FALSE; /* generate PostScript level 3 */int printAll = FALSE; /* print all images in file */int generateEPSF = TRUE; /* generate Encapsulated PostScript */int PSduplex = FALSE; /* enable duplex printing */int PStumble = FALSE; /* enable top edge binding */int PSavoiddeadzone = TRUE; /* enable avoiding printer deadzone */float maxPageHeight = 0; /* maximum size to fit on page */float splitOverlap = 0; /* amount for split pages to overlag */int rotate = FALSE; /* rotate image by 180 degrees */char *filename; /* input filename */int useImagemask = FALSE; /* Use imagemask instead of image operator */uint16 res_unit = 0; /* Resolution units: 1 - inches, 2 - cm*//* * ASCII85 Encoding Support. */unsigned char ascii85buf[10];int ascii85count;int ascii85breaklen;int TIFF2PS(FILE*, TIFF*, float, float, double, double, int);void PSpage(FILE*, TIFF*, uint32, uint32);void PSColorContigPreamble(FILE*, uint32, uint32, int);void PSColorSeparatePreamble(FILE*, uint32, uint32, int);void PSDataColorContig(FILE*, TIFF*, uint32, uint32, int);void PSDataColorSeparate(FILE*, TIFF*, uint32, uint32, int);void PSDataPalette(FILE*, TIFF*, uint32, uint32);void PSDataBW(FILE*, TIFF*, uint32, uint32);void PSRawDataBW(FILE*, TIFF*, uint32, uint32);void Ascii85Init(void);void Ascii85Put(unsigned char code, FILE* fd);void Ascii85Flush(FILE* fd);void PSHead(FILE*, TIFF*, uint32, uint32, float, float, float, float);void PSTail(FILE*, int);#if defined( EXP_ASCII85ENCODER)int Ascii85EncodeBlock( uint8 * ascii85_p, unsigned f_eod, const uint8 * raw_p, int raw_l );#endifstatic void usage(int);intmain(int argc, char* argv[]){ int dirnum = -1, c, np = 0; int centered = 0; float bottommargin = 0; float leftmargin = 0; float pageWidth = 0; float pageHeight = 0; uint32 diroff = 0; extern char *optarg; extern int optind; FILE* output = stdout; while ((c = getopt(argc, argv, "b:d:h:H:L:i:w:l:o:O:acelmrxyzps1238DT")) != -1) switch (c) { case 'b': bottommargin = atof(optarg); break; case 'c': centered = 1; break; case 'd': dirnum = atoi(optarg); break; case 'D': PSduplex = TRUE; break; case 'i': interpolate = atoi(optarg) ? TRUE:FALSE; break; case 'T': PStumble = TRUE; break; case 'e': PSavoiddeadzone = FALSE; generateEPSF = TRUE; break; case 'h': pageHeight = atof(optarg); break; case 'H': maxPageHeight = atof(optarg); if (pageHeight==0) pageHeight = maxPageHeight; break; case 'L': splitOverlap = atof(optarg); break; case 'm': useImagemask = TRUE; break; case 'o': diroff = (uint32) strtoul(optarg, NULL, 0); break; case 'O': /* XXX too bad -o is already taken */ output = fopen(optarg, "w"); if (output == NULL) { fprintf(stderr, "%s: %s: Cannot open output file.\n", argv[0], optarg); exit(-2); } break; case 'l': leftmargin = atof(optarg); break; case 'a': printAll = TRUE; /* fall thru... */ case 'p': generateEPSF = FALSE; break; case 'r': rotate = TRUE; break; case 's': printAll = FALSE; break; case 'w': pageWidth = atof(optarg); break; case 'z': PSavoiddeadzone = FALSE; break; case '1': level2 = FALSE; level3 = FALSE; ascii85 = FALSE; break; case '2': level2 = TRUE; ascii85 = TRUE; /* default to yes */ break; case '3': level3 = TRUE; ascii85 = TRUE; /* default to yes */ break; case '8': ascii85 = FALSE; break; case 'x': res_unit = RESUNIT_CENTIMETER; break; case 'y': res_unit = RESUNIT_INCH; break; case '?': usage(-1); } for (; argc - optind > 0; optind++) { TIFF* tif = TIFFOpen(filename = argv[optind], "r"); if (tif != NULL) { if (dirnum != -1 && !TIFFSetDirectory(tif, dirnum)) return (-1); else if (diroff != 0 && !TIFFSetSubDirectory(tif, diroff)) return (-1); np = TIFF2PS(output, tif, pageWidth, pageHeight, leftmargin, bottommargin, centered); TIFFClose(tif); } } if (np) PSTail(output, np); else usage(-1); if (output != stdout) fclose(output); return (0);}static uint16 samplesperpixel;static uint16 bitspersample;static uint16 planarconfiguration;static uint16 photometric;static uint16 compression;static uint16 extrasamples;static int alpha;static intcheckImage(TIFF* tif){ switch (photometric) { case PHOTOMETRIC_YCBCR: if ((compression == COMPRESSION_JPEG || compression == COMPRESSION_OJPEG) && planarconfiguration == PLANARCONFIG_CONTIG) { /* can rely on libjpeg to convert to RGB */ TIFFSetField(tif, TIFFTAG_JPEGCOLORMODE, JPEGCOLORMODE_RGB); photometric = PHOTOMETRIC_RGB; } else { if (level2 || level3) break; TIFFError(filename, "Can not handle image with %s", "PhotometricInterpretation=YCbCr"); return (0); } /* fall thru... */ case PHOTOMETRIC_RGB: if (alpha && bitspersample != 8) { TIFFError(filename, "Can not handle %d-bit/sample RGB image with alpha", bitspersample); return (0); } /* fall thru... */ case PHOTOMETRIC_SEPARATED: case PHOTOMETRIC_PALETTE: case PHOTOMETRIC_MINISBLACK: case PHOTOMETRIC_MINISWHITE: break; case PHOTOMETRIC_LOGL: case PHOTOMETRIC_LOGLUV: if (compression != COMPRESSION_SGILOG && compression != COMPRESSION_SGILOG24) { TIFFError(filename, "Can not handle %s data with compression other than SGILog", (photometric == PHOTOMETRIC_LOGL) ? "LogL" : "LogLuv" ); return (0); } /* rely on library to convert to RGB/greyscale */ TIFFSetField(tif, TIFFTAG_SGILOGDATAFMT, SGILOGDATAFMT_8BIT); photometric = (photometric == PHOTOMETRIC_LOGL) ? PHOTOMETRIC_MINISBLACK : PHOTOMETRIC_RGB; bitspersample = 8; break; case PHOTOMETRIC_CIELAB: /* fall thru... */ default: TIFFError(filename, "Can not handle image with PhotometricInterpretation=%d", photometric); return (0); } switch (bitspersample) { case 1: case 2: case 4: case 8: break; default: TIFFError(filename, "Can not handle %d-bit/sample image", bitspersample); return (0); } if (planarconfiguration == PLANARCONFIG_SEPARATE && extrasamples > 0) TIFFWarning(filename, "Ignoring extra samples"); return (1);}#define PS_UNIT_SIZE 72.0#define PSUNITS(npix,res) ((npix) * (PS_UNIT_SIZE / (res)))static char RGBcolorimage[] = "\/bwproc {\n\ rgbproc\n\ dup length 3 idiv string 0 3 0\n\ 5 -1 roll {\n\ add 2 1 roll 1 sub dup 0 eq {\n\ pop 3 idiv\n\ 3 -1 roll\n\ dup 4 -1 roll\n\ dup 3 1 roll\n\ 5 -1 roll put\n\ 1 add 3 0\n\ } { 2 1 roll } ifelse\n\ } forall\n\ pop pop pop\n\} def\n\/colorimage where {pop} {\n\ /colorimage {pop pop /rgbproc exch def {bwproc} image} bind def\n\} ifelse\n\";/* * Adobe Photoshop requires a comment line of the form: * * %ImageData: <cols> <rows> <depth> <main channels> <pad channels> * <block size> <1 for binary|2 for hex> "data start" * * It is claimed to be part of some future revision of the EPS spec. */static voidPhotoshopBanner(FILE* fd, uint32 w, uint32 h, int bs, int nc, char* startline){ fprintf(fd, "%%ImageData: %ld %ld %d %d 0 %d 2 \"", (long) w, (long) h, bitspersample, nc, bs); fprintf(fd, startline, nc); fprintf(fd, "\"\n");}/* * pw : image width in pixels * ph : image height in pixels * pprw : image width in PS units (72 dpi) * pprh : image height in PS units (72 dpi) */static voidsetupPageState(TIFF* tif, uint32* pw, uint32* ph, float* pprw, float* pprh){ float xres, yres; TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, pw); TIFFGetField(tif, TIFFTAG_IMAGELENGTH, ph); if (res_unit == 0) TIFFGetFieldDefaulted(tif, TIFFTAG_RESOLUTIONUNIT, &res_unit); /* * Calculate printable area. */ if (!TIFFGetField(tif, TIFFTAG_XRESOLUTION, &xres) || !xres) xres = PS_UNIT_SIZE; if (!TIFFGetField(tif, TIFFTAG_YRESOLUTION, &yres) || !yres) yres = PS_UNIT_SIZE; switch (res_unit) { case RESUNIT_CENTIMETER: xres *= 2.54, yres *= 2.54; break; case RESUNIT_INCH: break; case RESUNIT_NONE: default: xres *= PS_UNIT_SIZE, yres *= PS_UNIT_SIZE; break; } *pprh = PSUNITS(*ph, yres); *pprw = PSUNITS(*pw, xres);}static intisCCITTCompression(TIFF* tif){ uint16 compress; TIFFGetField(tif, TIFFTAG_COMPRESSION, &compress); return (compress == COMPRESSION_CCITTFAX3 || compress == COMPRESSION_CCITTFAX4 || compress == COMPRESSION_CCITTRLE || compress == COMPRESSION_CCITTRLEW);}static tsize_t tf_bytesperrow;static tsize_t ps_bytesperrow;static tsize_t tf_rowsperstrip;static tsize_t tf_numberstrips;static char *hex = "0123456789abcdef";/* * imagewidth & imageheight are 1/72 inches * pagewidth & pageheight are inches */intPlaceImage(FILE *fp, float pagewidth, float pageheight, float imagewidth, float imageheight, int splitpage, double lm, double bm, int cnt){ float xtran = 0; float ytran = 0; float xscale = 1; float yscale = 1; float left_offset = lm * PS_UNIT_SIZE; float bottom_offset = bm * PS_UNIT_SIZE; float subimageheight; float splitheight; float overlap; pagewidth *= PS_UNIT_SIZE; pageheight *= PS_UNIT_SIZE; if (maxPageHeight==0) splitheight = 0; else splitheight = maxPageHeight * PS_UNIT_SIZE; overlap = splitOverlap * PS_UNIT_SIZE; /* * WIDTH: * if too wide, scrunch to fit * else leave it alone */ if (imagewidth <= pagewidth) { xscale = imagewidth; } else { xscale = pagewidth; } /* HEIGHT: * if too long, scrunch to fit * if too short, move to top of page */ if (imageheight <= pageheight) { yscale = imageheight; ytran = pageheight - imageheight; } else if (imageheight > pageheight && (splitheight == 0 || imageheight <= splitheight)) { yscale = pageheight; } else /* imageheight > splitheight */ { subimageheight = imageheight - (pageheight-overlap)*splitpage; if (subimageheight <= pageheight) { yscale = imageheight; ytran = pageheight - subimageheight; splitpage = 0; } else if ( subimageheight > pageheight && subimageheight <= splitheight) { yscale = imageheight * pageheight / subimageheight; ytran = 0; splitpage = 0; } else /* sumimageheight > splitheight */ { yscale = imageheight; ytran = pageheight - subimageheight; splitpage++; } } bottom_offset += ytran / (cnt?2:1);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -