El Diumenge, 11 de març de 2012, a les 17:44:02, Ihar `Philips` Filipau va escriure: > Hi All!
Hi > I had some spare time and source code at hand and tried to solve > another of my problems with the pdftohtml: vertically flipped images. > (Also a long standing bug: > https://bugs.freedesktop.org/show_bug.cgi?id=32340 ) > > An hour (w)hacking at the code produced that piece of frankenstein > code you might see below. > > Short summary: implement very crude yflip in PNGWriter by buffering > rows and transpose/write them before closing the PNG image; disable > JPEGs and write always PNGs. (The piece of code detecting flip was > lifted from pdf2xml project.) > > > Is there any official ideas on how to implement the image flip in the > pdftohtml? > > Are other flip possible too? rotations? To date I have seen only PDFs > with upside down images. > > Have Fun. Please either use bugzilla or the list to post patches, not both, otherwise following the conversation gets difficult. Albert > > > goo/PNGWriter.cc | 89 > ++++++++++++++++++++++++++++++++++++++++++++++++ goo/PNGWriter.h | > 12 ++++++- > utils/HtmlOutputDev.cc | 47 ++++++++++++++++++++++++- > 3 files changed, 145 insertions(+), 3 deletions(-) > > diff --git a/goo/PNGWriter.cc b/goo/PNGWriter.cc > index fe8b79e..b60a540 100644 > --- a/goo/PNGWriter.cc > +++ b/goo/PNGWriter.cc > @@ -30,6 +30,11 @@ PNGWriter::PNGWriter(Format formatA) : format(formatA) > icc_data_size = 0; > icc_name = NULL; > sRGB_profile = false; > + > + y_flip = false; > + row_buf = NULL; > + row_buf_num = 0; > + row_buf_cap = 0; > } > > PNGWriter::~PNGWriter() > @@ -64,6 +69,9 @@ bool PNGWriter::init(FILE *f, int width, int height, > int hDPI, int vDPI) > png_const_bytep icc_data_ptr = (png_const_bytep)icc_data; > #endif > > + image_width = width; > + image_height = height; > + > /* initialize stuff */ > png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, > NULL); if (!png_ptr) { > @@ -99,18 +107,22 @@ bool PNGWriter::init(FILE *f, int width, int > height, int hDPI, int vDPI) > case RGB: > bit_depth = 8; > color_type = PNG_COLOR_TYPE_RGB; > + bytes_per_row = 3 * image_width; > break; > case RGBA: > bit_depth = 8; > color_type = PNG_COLOR_TYPE_RGB_ALPHA; > + bytes_per_row = 4 * image_width; > break; > case GRAY: > bit_depth = 8; > color_type = PNG_COLOR_TYPE_GRAY; > + bytes_per_row = 1 * image_width; > break; > case MONOCHROME: > bit_depth = 1; > color_type = PNG_COLOR_TYPE_GRAY; > + bytes_per_row = 1 * image_width; > break; > } > png_byte interlace_type = PNG_INTERLACE_NONE; > @@ -139,6 +151,17 @@ bool PNGWriter::init(FILE *f, int width, int > height, int hDPI, int vDPI) > > bool PNGWriter::writePointers(unsigned char **rowPointers, int rowCount) > { > + /* writes the image at once */ > + if (y_flip) { > + if (rowCount == image_height) { > + for (int i = 0; i<rowCount/2; i++) { > + unsigned char *tmp = rowPointers[i]; > + int ri = rowCount-i-1; > + rowPointers[i] = rowPointers[ri]; > + rowPointers[ri] = tmp; > + } > + } > + } > png_write_image(png_ptr, rowPointers); > /* write bytes */ > if (setjmp(png_jmpbuf(png_ptr))) { > @@ -152,6 +175,10 @@ bool PNGWriter::writePointers(unsigned char > **rowPointers, int rowCount) > bool PNGWriter::writeRow(unsigned char **row) > { > // Write the row to the file > + // or just buffer if y_flip > + if (y_flip) { > + return bufRows( row, 1 ); > + } > png_write_rows(png_ptr, row, 1); > if (setjmp(png_jmpbuf(png_ptr))) { > error(errInternal, -1, "error during png row write"); > @@ -163,6 +190,37 @@ bool PNGWriter::writeRow(unsigned char **row) > > bool PNGWriter::close() > { > + /* y_flip is implemented by buffering the rows - flush the rows here. */ > + if (y_flip && row_buf_num) { > + /* transpose the row_buf to accomodate the y_flip */ > + for (int i = 0; i<row_buf_num/2; i++) { > + unsigned char *tmp = row_buf[i]; > + int ri = row_buf_num-i-1; > + row_buf[i] = row_buf[ri]; > + row_buf[ri] = tmp; > + } > + /* write it */ > + if (row_buf_num == image_height) > + { > + png_write_image(png_ptr, row_buf); > + /* write bytes */ > + if (setjmp(png_jmpbuf(png_ptr))) { > + error(errInternal, -1, "Error during writing > bytes"); > + return false; > + } > + } > + else > + { > + for (int i = 0; i<row_buf_num; i++) { > + png_write_rows(png_ptr, &row_buf[i], 1); > + if (setjmp(png_jmpbuf(png_ptr))) { > + error(errInternal, -1, "error during > png row write"); > + return false; > + } > + } > + } > + } > + > /* end write */ > png_write_end(png_ptr, info_ptr); > if (setjmp(png_jmpbuf(png_ptr))) { > @@ -173,4 +231,35 @@ bool PNGWriter::close() > return true; > } > > +void PNGWriter::setFlipY(bool flip) > +{ > + y_flip = flip; > +} > + > +bool PNGWriter::bufRows( unsigned char **rows, int row_count ) > +{ > + if (!row_count) > + return true; > + > + if (row_buf_num + row_count > row_buf_cap) { > + > + if (row_buf_cap == 0) > + row_buf_cap = 32; > + > + while ( row_buf_num + row_count > row_buf_cap ) > + row_buf_cap = (row_buf_cap/4)*5; /* increase > capacity by 25% */ > + > + row_buf = (unsigned char **)grealloc( row_buf, > row_buf_cap*sizeof(unsigned char *) ); > + } > + > + while (row_count > 0) { > + row_buf[ row_buf_num ] = (unsigned char *)gmalloc( > bytes_per_row ); > + memcpy( row_buf[ row_buf_num ], *rows, bytes_per_row ); > + row_buf_num++; > + rows++; > + row_count--; > + } > + return true; > +} > + > #endif > diff --git a/goo/PNGWriter.h b/goo/PNGWriter.h > index f22495d..efc8f58 100644 > --- a/goo/PNGWriter.h > +++ b/goo/PNGWriter.h > @@ -47,7 +47,8 @@ class PNGWriter : public ImgWriter > bool writeRow(unsigned char **row); > > bool close(); > - > + > + void setFlipY(bool = true); > private: > Format format; > png_structp png_ptr; > @@ -56,6 +57,15 @@ class PNGWriter : public ImgWriter > int icc_data_size; > char *icc_name; > bool sRGB_profile; > + > + int image_width, image_height; > + int bytes_per_row; > + > + bool y_flip; > + unsigned char **row_buf; > + int row_buf_num, row_buf_cap; > + > + bool bufRows( unsigned char **rowPointers, int rowCount ); > }; > > #endif > diff --git a/utils/HtmlOutputDev.cc b/utils/HtmlOutputDev.cc > index b38af4d..cd80f6d 100644 > --- a/utils/HtmlOutputDev.cc > +++ b/utils/HtmlOutputDev.cc > @@ -1295,7 +1295,9 @@ void HtmlOutputDev::drawJpegImage(GfxState > *state, Stream *str) > } > > // initialize stream > + fprintf( stderr, "jpeg stream kind before: %d\n", > int(str->getKind()) ); // StreamKind > str = str->getNextStream(); > + fprintf( stderr, "jpeg stream kind after: %d\n", > int(str->getKind()) ); // StreamKind > str->reset(); > > // copy the stream > @@ -1345,6 +1347,47 @@ void HtmlOutputDev::drawPngImage(GfxState > *state, Stream *str, int width, int he > return; > } > > + if (1) { > + double x0, y0; // top left corner of image > + double w0, h0, w1, h1; // size of image > + double xt, yt, wt, ht; > + GBool rotate, xFlip, yFlip; > + > + // get image position and size > + state->transform(0, 0, &xt, &yt); > + state->transformDelta(1, 1, &wt, &ht); > + if (wt > 0) { > + x0 = (xt); > + w0 = (wt); > + } else { > + x0 = (xt + wt); > + w0 = (-wt); > + } > + if (ht > 0) { > + y0 = (yt); > + h0 = (ht); > + } else { > + y0 = (yt + ht); > + h0 = (-ht); > + } > + state->transformDelta(1, 0, &xt, &yt); > + rotate = fabs(xt) < fabs(yt); > + if (rotate) { > + w1 = h0; > + h1 = w0; > + xFlip = ht < 0; > + yFlip = wt > 0; > + } else { > + w1 = w0; > + h1 = h0; > + xFlip = wt < 0; > + yFlip = ht > 0; > + } > + //fprintf( stderr, "image xFlip:%d yFlip:%d\n", int(xFlip), > int(yFlip) ); // StreamKind > + > + if (yFlip) writer->setFlipY(); > + } > + > if (!isMask) { > Guchar *p; > GfxRGB rgb; > @@ -1441,7 +1484,7 @@ void HtmlOutputDev::drawImageMask(GfxState > *state, Object *ref, Stream *str, > } > > // dump JPEG file > - if (dumpJPEG && str->getKind() == strDCT) { > + if (0 && dumpJPEG && str->getKind() == strDCT) { > drawJpegImage(state, str); > } > else { > @@ -1466,7 +1509,7 @@ void HtmlOutputDev::drawImage(GfxState *state, > Object *ref, Stream *str, > /*if( !globalParams->getErrQuiet() ) > printf("image stream of kind %d\n", str->getKind());*/ > // dump JPEG file > - if (dumpJPEG && str->getKind() == strDCT) { > + if (0 && dumpJPEG && str->getKind() == strDCT) { > drawJpegImage(state, str); > } > else { > _______________________________________________ > poppler mailing list > [email protected] > http://lists.freedesktop.org/mailman/listinfo/poppler _______________________________________________ poppler mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/poppler
