//======================================================================== // // ImageOutputDev.cc // // Copyright 1998-2003 Glyph & Cog, LLC // //======================================================================== //======================================================================== // // Modified under the Poppler project - http://poppler.freedesktop.org // // All changes made under the Poppler project to this file are licensed // under GPL version 2 or later // // Copyright (C) 2005, 2007 Albert Astals Cid // Copyright (C) 2006 Rainer Keller // Copyright (C) 2008 Timothy Lee // Copyright (C) 2008 Vasile Gaburici // Copyright (C) 2009 Carlos Garcia Campos // Copyright (C) 2009 William Bader // Copyright (C) 2010 Jakob Voss // // To see a description of the changes please see the Changelog file that // came with your tarball or type make ChangeLog if you are building from git // //======================================================================== #include "config.h" #include #ifdef USE_GCC_PRAGMAS #pragma implementation #endif #include #include #include #include #include "goo/gmem.h" #include "Error.h" #include "GfxState.h" #include "Object.h" #include "Stream.h" #ifdef ENABLE_LIBJPEG #include "DCTStream.h" #endif #include "ImageOutputDev.h" ImageOutputDev::ImageOutputDev(char *fileRootA, GBool pageNamesA, GBool dumpJPEGA) { fileRoot = copyString(fileRootA); fileName = (char *)gmalloc(strlen(fileRoot) + 45); dumpJPEG = dumpJPEGA; pageNames = pageNamesA; imgNum = 0; pageNum = 0; ok = gTrue; } ImageOutputDev::~ImageOutputDev() { gfree(fileName); gfree(fileRoot); } void ImageOutputDev::setFilename(const char *fileExt) { if (pageNames) { sprintf(fileName, "%s-%03d-%03d.%s", fileRoot, pageNum, imgNum, fileExt); } else { sprintf(fileName, "%s-%03d.%s", fileRoot, imgNum, fileExt); } } void ImageOutputDev::drawImageMask(GfxState *state, Object *ref, Stream *str, int width, int height, GBool invert, GBool interpolate, GBool inlineImg) { FILE *f; int c; int size, i; // dump JPEG file if (dumpJPEG && str->getKind() == strDCT && !inlineImg) { // open the image file setFilename("jpg"); ++imgNum; if (!(f = fopen(fileName, "wb"))) { error(-1, "Couldn't open image file '%s'", fileName); return; } // initialize stream str = ((DCTStream *)str)->getRawStream(); str->reset(); // copy the stream while ((c = str->getChar()) != EOF) fputc(c, f); str->close(); fclose(f); // dump PBM file } else { // open the image file and write the PBM header setFilename("pbm"); ++imgNum; if (!(f = fopen(fileName, "wb"))) { error(-1, "Couldn't open image file '%s'", fileName); return; } fprintf(f, "P4\n"); fprintf(f, "%d %d\n", width, height); // initialize stream str->reset(); // copy the stream size = height * ((width + 7) / 8); for (i = 0; i < size; ++i) { fputc(str->getChar(), f); } str->close(); fclose(f); } } void ImageOutputDev::drawImage(GfxState *state, Object *ref, Stream *str, int width, int height, GfxImageColorMap *colorMap, GBool interpolate, int *maskColors, GBool inlineImg) { FILE *f; ImageStream *imgStr; Guchar *p; Guchar zero = 0; GfxGray gray; GfxRGB rgb; int x, y; int c; int size, i; int pbm_mask = 0xff; // dump JPEG file if (dumpJPEG && str->getKind() == strDCT && (colorMap->getNumPixelComps() == 1 || colorMap->getNumPixelComps() == 3) && !inlineImg) { // open the image file setFilename("jpg"); ++imgNum; if (!(f = fopen(fileName, "wb"))) { error(-1, "Couldn't open image file '%s'", fileName); return; } // initialize stream str = ((DCTStream *)str)->getRawStream(); str->reset(); // copy the stream while ((c = str->getChar()) != EOF) fputc(c, f); str->close(); fclose(f); // dump PBM file } else if (colorMap->getNumPixelComps() == 1 && colorMap->getBits() == 1) { // open the image file and write the PBM header setFilename("pbm"); ++imgNum; if (!(f = fopen(fileName, "wb"))) { error(-1, "Couldn't open image file '%s'", fileName); return; } fprintf(f, "P4\n"); fprintf(f, "%d %d\n", width, height); // initialize stream str->reset(); // if 0 comes out as 0 in the color map, the we _flip_ stream bits // otherwise we pass through stream bits unmolested colorMap->getGray(&zero, &gray); if(colToByte(gray)) pbm_mask = 0; // copy the stream size = height * ((width + 7) / 8); for (i = 0; i < size; ++i) { fputc(str->getChar() ^ pbm_mask, f); } str->close(); fclose(f); // dump PPM file } else { // open the image file and write the PPM header setFilename("ppm"); ++imgNum; if (!(f = fopen(fileName, "wb"))) { error(-1, "Couldn't open image file '%s'", fileName); return; } fprintf(f, "P6\n"); fprintf(f, "%d %d\n", width, height); fprintf(f, "255\n"); // initialize stream imgStr = new ImageStream(str, width, colorMap->getNumPixelComps(), colorMap->getBits()); imgStr->reset(); // for each line... for (y = 0; y < height; ++y) { // write the line p = imgStr->getLine(); for (x = 0; x < width; ++x) { colorMap->getRGB(p, &rgb); fputc(colToByte(rgb.r), f); fputc(colToByte(rgb.g), f); fputc(colToByte(rgb.b), f); p += colorMap->getNumPixelComps(); } } imgStr->close(); delete imgStr; fclose(f); } } void ImageOutputDev::drawMaskedImage( GfxState *state, Object *ref, Stream *str, int width, int height, GfxImageColorMap *colorMap, GBool interpolate, Stream *maskStr, int maskWidth, int maskHeight, GBool maskInvert, GBool maskInterpolate) { drawImage(state, ref, str, width, height, colorMap, interpolate, NULL, gFalse); drawImageMask(state, ref, maskStr, maskWidth, maskHeight, maskInvert, maskInterpolate, gFalse); } void ImageOutputDev::drawSoftMaskedImage( GfxState *state, Object *ref, Stream *str, int width, int height, GfxImageColorMap *colorMap, GBool interpolate, Stream *maskStr, int maskWidth, int maskHeight, GfxImageColorMap *maskColorMap, GBool maskInterpolate) { drawImage(state, ref, str, width, height, colorMap, interpolate, NULL, gFalse); drawImage(state, ref, maskStr, maskWidth, maskHeight, maskColorMap, maskInterpolate, NULL, gFalse); }