diff --git a/utils/HtmlOutputDev.cc b/utils/HtmlOutputDev.cc index 17541a2..87d9d93 100644 --- a/utils/HtmlOutputDev.cc +++ b/utils/HtmlOutputDev.cc @@ -1277,16 +1277,9 @@ void HtmlOutputDev::drawJpegImage(GfxState *state, Stream *str) { FILE *f1; int c; - GooString *fName=new GooString(Docname); - fName->append("-"); - GooString *pgNum= GooString::fromInt(pageNum); - GooString *imgnum= GooString::fromInt(pages->getNumImages()+1); // open the image file - fName->append(pgNum)->append("_")->append(imgnum)->append(".jpg"); - delete pgNum; - delete imgnum; - + GooString *fName=createImageFileName("jpg"); if (!(f1 = fopen(fName->getCString(), "wb"))) { error(errIO, -1, "Couldn't open image file '%s'", fName->getCString()); delete fName; @@ -1308,74 +1301,40 @@ void HtmlOutputDev::drawJpegImage(GfxState *state, Stream *str) } } -void HtmlOutputDev::drawImageMask(GfxState *state, Object *ref, Stream *str, - int width, int height, GBool invert, - GBool interpolate, GBool inlineImg) { +void HtmlOutputDev::drawPngImage(GfxState *state, Stream *str, int width, int height, + GfxImageColorMap *colorMap, GBool isMask) +{ +#ifdef ENABLE_LIBPNG + FILE *f1; - if (ignore||(complexMode && !xml)) { - OutputDev::drawImageMask(state, ref, str, width, height, invert, interpolate, inlineImg); + if (!colorMap && !isMask) { + error(errInternal, -1, "Can't have color image without a color map"); return; } - - // dump JPEG file - if (dumpJPEG && str->getKind() == strDCT) { - drawJpegImage(state, str); - } - else { - OutputDev::drawImageMask(state, ref, str, width, height, invert, interpolate, inlineImg); - } -} -void HtmlOutputDev::drawImage(GfxState *state, Object *ref, Stream *str, - int width, int height, GfxImageColorMap *colorMap, - GBool interpolate, int *maskColors, GBool inlineImg) { - - if (ignore||(complexMode && !xml)) { - OutputDev::drawImage(state, ref, str, width, height, colorMap, interpolate, - maskColors, inlineImg); + // open the image file + GooString *fName=createImageFileName("png"); + if (!(f1 = fopen(fName->getCString(), "wb"))) { + error(errIO, -1, "Couldn't open image file '%s'", fName->getCString()); + delete fName; return; } - - /*if( !globalParams->getErrQuiet() ) - printf("image stream of kind %d\n", str->getKind());*/ - // dump JPEG file - if (dumpJPEG && str->getKind() == strDCT) { - drawJpegImage(state, str); + + PNGWriter *writer = new PNGWriter( isMask ? PNGWriter::MONOCHROME : PNGWriter::RGB ); + // TODO can we calculate the resolution of the image? + if (!writer->init(f1, width, height, 72, 72)) { + error(errInternal, -1, "Can't init PNG for image '%s'", fName->getCString()); + delete writer; + fclose(f1); + return; } - else { -#ifdef ENABLE_LIBPNG - // Dump the image as a PNG file. Much of the PNG code - // comes from an example by Guillaume Cottenceau. - FILE *f1; + + if (!isMask) { Guchar *p; GfxRGB rgb; - png_byte *row = (png_byte *) malloc(3 * width); // 3 bytes/pixel: RGB + png_byte *row = (png_byte *) gmalloc(3 * width); // 3 bytes/pixel: RGB png_bytep *row_pointer= &row; - // Create the image filename - GooString *fName=new GooString(Docname); - fName->append("-"); - GooString *pgNum= GooString::fromInt(pageNum); - GooString *imgnum= GooString::fromInt(pages->getNumImages()+1); - fName->append(pgNum)->append("_")->append(imgnum)->append(".png"); - delete pgNum; - delete imgnum; - - // Open the image file - if (!(f1 = fopen(fName->getCString(), "wb"))) { - error(errIO, -1, "Couldn't open image file '{0:t}'", fName); - delete fName; - return; - } - - PNGWriter *writer = new PNGWriter(); - // TODO can we calculate the resolution of the image? - if (!writer->init(f1, width, height, 72, 72)) { - delete writer; - fclose(f1); - return; - } - // Initialize the image stream ImageStream *imgStr = new ImageStream(str, width, colorMap->getNumPixelComps(), colorMap->getBits()); @@ -1388,31 +1347,125 @@ void HtmlOutputDev::drawImage(GfxState *state, Object *ref, Stream *str, p = imgStr->getLine(); for (int x = 0; x < width; x++) { colorMap->getRGB(p, &rgb); - // Write the RGB pixels into the row - row[3*x]= colToByte(rgb.r); - row[3*x+1]= colToByte(rgb.g); - row[3*x+2]= colToByte(rgb.b); - p += colorMap->getNumPixelComps(); + // Write the RGB pixels into the row + row[3*x]= colToByte(rgb.r); + row[3*x+1]= colToByte(rgb.g); + row[3*x+2]= colToByte(rgb.b); + p += colorMap->getNumPixelComps(); } if (!writer->writeRow(row_pointer)) { + error(errIO, -1, "Failed to write into PNG '%s'", fName->getCString()); delete writer; + delete imgStr; fclose(f1); return; } } + gfree(row); + imgStr->close(); + delete imgStr; + } + else { // isMask == true + ImageStream *imgStr = new ImageStream(str, width, 1, 1); + imgStr->reset(); - writer->close(); - delete writer; - fclose(f1); + Guchar *png_row = (Guchar *)gmalloc( width ); + + for (int ri = 0; ri < height; ++ri) + { + // read the row of the mask + Guchar *bit_row = imgStr->getLine(); + + // invert for PNG + for(int i = 0; i < width; i++) + png_row[i] = bit_row[i] ? 0x00 : 0xff ; - free(row); - pages->addImage(fName, state); + if (!writer->writeRow( &png_row )) + { + error(errIO, -1, "Failed to write into PNG '%s'", fName->getCString()); + delete writer; + fclose(f1); + delete imgStr; + gfree(png_row); + return; + } + } imgStr->close(); delete imgStr; + gfree(png_row); + } + + str->close(); + + writer->close(); + delete writer; + fclose(f1); + + pages->addImage(fName, state); #else + return; +#endif +} + +GooString *HtmlOutputDev::createImageFileName(const char *ext) +{ + GooString *fName=new GooString(Docname); + fName->append("-"); + GooString *pgNum= GooString::fromInt(pageNum); + GooString *imgnum= GooString::fromInt(pages->getNumImages()+1); + + fName->append(pgNum)->append("_")->append(imgnum)->append(".")->append(ext); + delete pgNum; + delete imgnum; + + return fName; +} + +void HtmlOutputDev::drawImageMask(GfxState *state, Object *ref, Stream *str, + int width, int height, GBool invert, + GBool interpolate, GBool inlineImg) { + + if (ignore||(complexMode && !xml)) { + OutputDev::drawImageMask(state, ref, str, width, height, invert, interpolate, inlineImg); + return; + } + + // dump JPEG file + if (dumpJPEG && str->getKind() == strDCT) { + drawJpegImage(state, str); + } + else { +#ifdef ENABLE_LIBPNG + drawPngImage(state, str, width, height, NULL, gTrue); +#else + OutputDev::drawImageMask(state, ref, str, width, height, invert, interpolate, inlineImg); +#endif + } +} + +void HtmlOutputDev::drawImage(GfxState *state, Object *ref, Stream *str, + int width, int height, GfxImageColorMap *colorMap, + GBool interpolate, int *maskColors, GBool inlineImg) { + + if (ignore||(complexMode && !xml)) { OutputDev::drawImage(state, ref, str, width, height, colorMap, interpolate, maskColors, inlineImg); + return; + } + + /*if( !globalParams->getErrQuiet() ) + printf("image stream of kind %d\n", str->getKind());*/ + // dump JPEG file + if (dumpJPEG && str->getKind() == strDCT) { + drawJpegImage(state, str); + } + else { +#ifdef ENABLE_LIBPNG + drawPngImage(state, str, width, height, colorMap ); +#else + OutputDev::drawImage(state, ref, str, width, height, colorMap, interpolate, + maskColors, inlineImg); #endif } } diff --git a/utils/HtmlOutputDev.h b/utils/HtmlOutputDev.h index b730ead..2f35759 100644 --- a/utils/HtmlOutputDev.h +++ b/utils/HtmlOutputDev.h @@ -323,6 +323,9 @@ private: int getOutlinePageNum(OutlineItem *item); #endif void drawJpegImage(GfxState *state, Stream *str); + void drawPngImage(GfxState *state, Stream *str, int width, int height, + GfxImageColorMap *colorMap, GBool isMask = gFalse); + GooString *createImageFileName(const char *ext); FILE *fContentsFrame; FILE *page; // html file