Re: Some new Alpha-related capabilities

Cosmin Truta <[email protected]> Tue, 9 Oct 2018 01:56:53 -0400
Newsgroups gmane.comp.graphics.png.devel
Message-ID <CAAoVtZyOMH75=HH6=Gf9-hvcm4z_A1xv0YwY0X8NHPKjrPXmew@mail.gmail.com>
Hi, Phil,

Thank you for your message. I will respond to your points briefly, but
if I haven't address them properly (especially given my unfamiliarity
with Perl), please come back for clarifications.

On point 1:
By using libpng, you can retrieve the uncompressed pixels, and you can
get the raw deflate-compressed IDAT content as well. Doing the former
(which, as I understand, is not what you want) is easy. Doing the
latter is considerably less common (given that fewer use cases require
the compressed data), and requires more programming, but it can be
done. By using the C API, you need to register a read callback, and
extract the content of the desired chunk (in your case, IDAT). I don't
know if you can do that in the Perl wrapper, though.

But before going into details, I would like to know details about the
PDF "FlateDecode" method. For example: is that a raw zlib stream? Does
it have any headers? Does it do delta filtering?

To give you a concrete example: if FlateDecode incorporates a
filtering method that is different from what's done in PNG, then you
cannot just use a PNG IDAT stream. Similarly, if FlateDecode
incorporates no filtering method at all, and the rows are not prefixed
by any filter byte (as in PNG), then, yet again, you can't use the
IDAT. In that case, your only choice is to decompress PNG's
deflate-encoded IDAT and decode the filtering, and then recompress the
PDF deflate stream.

These are just assumptions on my part. In order to respond to you
correctly, I need to know the semantics of FlateDecode streams in the
PDF format. Any description or pointers available?

On point 2:
With the libpng API, you can indeed get all of the RGBA planes in a
single array, and you can strip the alpha channel, but not separate it
AFAIK. Unless you implement that separation yourself in user C code.
(It's fast-running and easy to do.) But if you need to do it in Perl,
and it's not fast, then I guess adding intermediate C code, and
calling that from Perl, could be a workable alternative(?)

If you're asking about extending the libpng API to accommodate that, I
am reluctant. It would complicate the API in order to allow returning
two images instead of one. libpng is primarily a codec, handling
compression and decompression. All the other image processing is done
only to a limited extent.

I wonder if an external tool or library wouldn't be a better fit.
Would you consider manipulating the pixel extraction and channel
separation by the means of libraries like GraphicsMagick or
ImageMagick (which, BTW, have Perl APIs)?

On point 3:
I'm sorry, but I do not know about a reasonably fast and easy way,
other than writing the C code that you need, and calling that from
Perl. Alternatively, if the Perl wrapper allows transformations, then
you can use png_set_expand() or PNG_TRANSFORM_EXPAND, and have your
type-3 image converted to RGBA, then proceed as in my previous answer.
I know it's not ideal for you. It is apparent that libpng wasn't
architected with a straightforward connection to the PDF image use
case in mind.

libpng-based PNG-to-PDF conversions do work, mind you; but for the
kind of transformations that you describe, you probably need to write
custom, native C or C++ code that put the right pixel and channel data
in the right places.

Or use more powerful and flexible pixel processing like
GraphicsMagick/ImageMagick.

Sincerely,
Cosmin