/* * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * @brief Convert PWG Raster to a PostScript file * @file rastertops.c * @author Pranjal Bhor (C) 2016 * @author Neil 'Superna' Armstrong (C) 2010 * @author Tobias Hoffmann (c) 2012 * @author Till Kamppeter (c) 2014 */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* * 'write_prolog()' - Writing the PostScript prolog for the file */ void writeProlog(int width, /* I - width of the image in points */ int height) /* I - height of the image in points */ { /* Document header... */ printf("%%!PS-Adobe-3.0\n"); printf("%%%%BoundingBox: %d %d %d %d\n", 0, 0, width, height); printf("%%%%Creator: cups-filters\n"); printf("%%%%LanguageLevel: 2\n"); printf("%%%%DocumentData: Clean7Bit\n"); printf("%%%%Pages: (atend)\n"); printf("%%%%EndComments\n"); printf("%%%%BeginProlog\n"); printf("%%%%EndProlog\n"); } /* * 'writeStartPage()' - Write the basic page setup */ void writeStartPage(int page, /* I - Page to write */ int width, /* I - Page width in points */ int length) /* I - Page length in points */ { printf("%%%%Page: %d %d\n", page, page); printf("%%%%BeginPageSetup\n"); printf("<< /PageSize[%d %d] >> setpagedevice\n", width, length); printf("%%%%EndPageSetup\n"); } /* * 'find_bits()' - Finding the number of bits per color */ int /* O - Exit status */ find_bits(cups_cspace_t mode, /* I - Color space of data */ int bpc) /* I - Original bits per color of data */ { if (bpc == 1 && (mode == CUPS_CSPACE_RGB || mode == CUPS_CSPACE_ADOBERGB || mode == CUPS_CSPACE_SRGB || mode == CUPS_CSPACE_CMY)) return 8; if (bpc == 16) return 8; return bpc; } /* * 'writeImage()' - Write the information regarding the image */ void /* O - Exit status */ writeImage(int pagewidth, /* I - width of page in points */ int pageheight, /* I - height of page in points */ int bpc, /* I - bits per color */ int pixwidth, /* I - width of image in pixels */ int pixheight, /* I - height of image in pixels */ cups_cspace_t mode) /* I - color model of image */ { printf("gsave\n"); switch (mode) { case CUPS_CSPACE_RGB: case CUPS_CSPACE_CMY: case CUPS_CSPACE_SRGB: case CUPS_CSPACE_ADOBERGB: printf("/DeviceRGB setcolorspace\n"); break; case CUPS_CSPACE_CMYK: printf("/DeviceCMYK setcolorspace\n"); break; default: case CUPS_CSPACE_K: case CUPS_CSPACE_W: case CUPS_CSPACE_SW: printf("/DeviceGray setcolorspace\n"); break; } if (bpc == 16) printf("/Input currentfile /FlateDecode filter def\n"); printf("%d %d scale\n", pagewidth, pageheight); printf("<< \n" "/ImageType 1\n" "/Width %d\n" "/Height %d\n" "/BitsPerComponent %d\n", pixwidth, pixheight, find_bits(mode, bpc)); switch (mode) { case CUPS_CSPACE_RGB: case CUPS_CSPACE_CMY: case CUPS_CSPACE_SRGB: case CUPS_CSPACE_ADOBERGB: printf("/Decode [0 1 0 1 0 1]\n"); break; case CUPS_CSPACE_CMYK: printf("/Decode [0 1 0 1 0 1 0 1]\n"); break; case CUPS_CSPACE_SW: printf("/Decode [0 1]\n"); break; default: case CUPS_CSPACE_K: case CUPS_CSPACE_W: printf("/Decode [1 0]\n"); break; } if(bpc==16) printf("/DataSource {3 string 0 1 2 {1 index exch Input read {pop}" "if Input read pop put } for} bind\n"); else printf("/DataSource currentfile /FlateDecode filter\n"); printf("/ImageMatrix [%d 0 0 %d 0 %d]\n", pixwidth, -1*pixheight, pixheight); printf(">> image\n"); } /* * 'convert_pixels()'- Convert 1 bpc to 8 bpc */ void convert_pixels(unsigned char *pixdata, /* I - Original pixel data */ unsigned char *convertedpix, /* I - Buffer for converted data */ int width) /* I - Width of data */ { int j, k = 0; /* Variables for iteration */ unsigned int mask; /* Variable for per byte iteration */ unsigned char temp; /* temporary character */ for(j = 0; j < width; ++j) { temp = *(pixdata + j); for (mask = 0x80; mask != 0; mask >>= 1) { if (mask!=0x80 && mask != 0x08) { if (temp & mask) convertedpix[k] = 0xFF; else convertedpix[k] = 0; ++k; } } } } /* * 'write_flate()' - Write the image data in flate encoded format */ int /* O - Error value */ write_flate(cups_raster_t *ras, /* I - Image data */ cups_page_header2_t header) /* I - Bytes Per Line */ { int ret, /* Return value of this function */ flush, /* Check the end of image data */ curr_line=1, /* Maitining the working line of pixels */ alloc, flag = 0; unsigned have; /* Bytes available in output buffer */ z_stream strm; /* Structure required by deflate */ unsigned char *pixdata, *convertedpix; unsigned char in[header.cupsBytesPerLine * 6], /* Input data buffer */ out[header.cupsBytesPerLine * 6]; /* Output data buffer */ /* allocate deflate state */ strm.zalloc = Z_NULL; strm.zfree = Z_NULL; strm.opaque = Z_NULL; ret = deflateInit(&strm, -1); if (ret != Z_OK) return ret; if(header.cupsBitsPerColor == 1 && (header.cupsColorSpace == CUPS_CSPACE_RGB || header.cupsColorSpace == CUPS_CSPACE_ADOBERGB || header.cupsColorSpace == CUPS_CSPACE_SRGB)) flag = 1; /* compress until end of file */ do { pixdata = malloc(header.cupsBytesPerLine); cupsRasterReadPixels(ras, pixdata, header.cupsBytesPerLine); if (flag) { convertedpix = malloc(header.cupsBytesPerLine * 6); convert_pixels(pixdata,convertedpix, header.cupsBytesPerLine); alloc = header.cupsBytesPerLine * 6; } else { convertedpix = malloc(header.cupsBytesPerLine); memcpy(convertedpix, pixdata, header.cupsBytesPerLine); alloc = header.cupsBytesPerLine; } if(curr_line == header.cupsHeight) flush = Z_FINISH; else flush = Z_NO_FLUSH; curr_line++; memcpy(in, convertedpix, alloc); strm.avail_in = alloc; strm.next_in = in; /* run deflate() on input until output buffer not full, finish * compression if all of source has been read in */ do { strm.avail_out = alloc; strm.next_out = out; /* Run the deflate algorithm on the data */ ret = deflate(&strm, flush); /* check whether state is not clobbered */ assert(ret != Z_STREAM_ERROR); have = alloc - strm.avail_out; if (fwrite(out, 1, have, stdout) != have) { (void)deflateEnd(&strm); if (convertedpix != NULL) free(convertedpix); return Z_ERRNO; } } while (strm.avail_out == 0); /* all input will be used */ assert(strm.avail_in == 0); /* done when last data in file processed */ free(pixdata); free(convertedpix); } while (flush != Z_FINISH); /* stream will be complete */ assert(ret == Z_STREAM_END); /* clean up and return */ (void)deflateEnd(&strm); return Z_OK; } /* * Report a zlib or i/o error */ void zerr(int ret) /* I - Return status of deflate */ { fputs("zpipe: ", stderr); switch (ret) { case Z_ERRNO: fputs("error in source data or output file\n", stderr); break; case Z_STREAM_ERROR: fputs("invalid compression level\n", stderr); break; case Z_DATA_ERROR: fputs("invalid or incomplete deflate data\n", stderr); break; case Z_MEM_ERROR: fputs("out of memory\n", stderr); break; case Z_VERSION_ERROR: fputs("zlib version mismatch!\n", stderr); } } /* * 'writeEndPage()' - Show the current page. */ void writeEndPage() { printf("\ngrestore\n"); printf("showpage\n"); printf("%%%%PageTrailer\n"); } /* * 'writeTrailer()' - Write the PostScript trailer. */ void writeTrailer(int pages) /* I - Number of pages */ { printf("%%%%Trailer\n"); printf("%%%%Pages: %d\n", pages); printf("%%%%EOF\n"); } /* * 'main()' - Main entry and processing of driver. */ int /* O - Exit status */ main(int argc, /* I - Number of command-line arguments */ char *argv[]) /* I - Command-line arguments */ { FILE *input = NULL; /* File pointer to raster document */ int fd, /* File descriptor for raster document */ num_options, /* Number of options */ Canceled = 0, /* variable for job cancellation */ empty, /* Is the input empty? */ Page = 0, /* variable for counting the pages */ ret; /* Return value of deflate compression */ ppd_file_t *ppd; /* PPD file */ cups_raster_t *ras; /* Raster stream for printing */ cups_page_header2_t header; /* Page header from file */ cups_option_t *options; /* Options */ /* * Make sure status messages are not buffered... */ setbuf(stderr, NULL); /* * Check command-line... */ if (argc < 6 || argc > 7) { fprintf(stderr, "Usage: %s job-id user title copies options [file]\n", "rastertops"); return (1); } num_options = cupsParseOptions(argv[5], 0, &options); /* * Open the PPD file... */ ppd = ppdOpenFile(getenv("PPD")); if (ppd) { ppdMarkDefaults(ppd); cupsMarkOptions(ppd, num_options, options); } else { ppd_status_t status; /* PPD error */ int linenum; /* Line number */ fprintf(stderr, "DEBUG: The PPD file could not be opened.\n"); status = ppdLastError(&linenum); fprintf(stderr, "DEBUG: %s on line %d.\n", ppdErrorString(status), linenum); } /* * Open the page stream... */ if (argc == 7) { input = fopen(argv[6], "rb"); if (input == NULL) { fprintf(stderr, "Unable to open PWG Raster file\n"); exit(1); } } else input = stdin; /* * Get fd from file */ fd = fileno(input); /* * Transform */ ras = cupsRasterOpen(fd, CUPS_RASTER_READ); /* * Register a signal handler to eject the current page if the * job is cancelled. */ Canceled = 0; /* * Process pages as needed... */ Page = 0; empty = 1; while (cupsRasterReadHeader2(ras, &header)) { /* * Write the prolog for PS only once */ if (empty) { empty = 0; writeProlog(header.PageSize[0], header.PageSize[1]); } /* * Write a status message with the page number and number of copies. */ if (Canceled) break; Page ++; fprintf(stderr, "INFO: Starting page %d.\n", Page); /* * Write the starting of the page */ writeStartPage(Page, header.PageSize[0], header.PageSize[1]); /* * write the information regarding the image */ writeImage(header.PageSize[0], header.PageSize[1], header.cupsBitsPerColor, header.cupsWidth, header.cupsHeight, header.cupsColorSpace); /* Write the compressed image data*/ ret = write_flate(ras, header); if (ret != Z_OK) zerr(ret); writeEndPage(); } if (empty) { fprintf(stderr, "DEBUG: Input is empty, outputting empty file.\n"); cupsRasterClose(ras); return 0; } writeTrailer(Page); cupsRasterClose(ras); return 0; }