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

Reply via email to