image-png
image-png copied to clipboard
Re-encode example
Hey! :-) I would like to just add an iTXt text junk to an image, but otherwise leave it as it is, as much as possible.
There is docu for how to add the text junk when writing, and there is docu for decoding and encoding separately. I tried to figure out how to decode and encode again, 1:1, but I could not figure it out. I imagine it is possible, as it is mentioned in https://github.com/image-rs/image-png/issues/253, but it is not shown there. Would it be possible to add an example source file that decodes and encodes and changes a little thing in-between? I'd be happy to provide the example, if I get some hints for how to do this.
I am a it puzzled by the whole interface. there is an Info struct that seems to contain (all)? the settings. It is used by Decoder and Encoder, and it can be fetched from the Decoder, but not set on the Encoder, one has to manually transfer each setting ... does this mimic some C interface, or why is it like that?
The overall interface predates my time as a maintainer and much of it likely even predates Rust 1.0. I wouldn't read too much into how the API is currently designed. At some point it would be nice to clean things up, but it has never been a priority.
I think it would be good to have an example like you describe, though as you're discovering it probably wouldn't end up looking very elegant.
Indeed, the Info struct plays multiple roles, and this is not a good API.
-
Infohas anencode()method, but that method doesn't have access toEncoder(e.g. it can't share compressor instance for ztxt and iccp) -
Info::encode()is public, but it just writes some chunks without file header. It's an internal code in a wrong place, not useful to anyone. -
For encoding some chunks it has separate
source_*fields, for some chunks it doesn't. -
It has to have a lifetime to borrow data for encoding, but doesn't need lifetimes when decoding.
I'd change Info to be purely information about decoded image, not used for encoding at all. Then provide separate options object for encoding, and helper methods for turning Info into encoding options for easy roundtripping.
Encoder also has some unnecessary complications:
-
Encoderis not really an encoder, but a builder for a private encodingOptionstype. It takesW: Writethat it doesn't use. The writer is just passed through in the finalwrite_header(), but theWbound makes it harder for users to pass or store the encoding configuration options. -
Separation of encoding between
Writer,Encoder,Info, andEncodableTextChunkmeans that they don't use the same zlib implementation, and zTXT and iCCP can't respect compression setting. TheWriteris the actual encoder, and it should be doing all the work.
@anforowicz @HeroicKatora Do you have a suggestion for a better interface for configuring animation encoding?
https://github.com/image-rs/image-png/blob/4b10bf8313c7a7db1aebc3cb8f18c0e922429547/src/encoder.rs#L146
@anforowicz @HeroicKatora Do you have a suggestion for a better interface for configuring animation encoding?
https://github.com/image-rs/image-png/blob/4b10bf8313c7a7db1aebc3cb8f18c0e922429547/src/encoder.rs#L146
Not really, sorry. From my perspective, the highest priority requirement is parity with the libpng-based SkPngEncoder API which doesn't support multi-frame images. So my usage of the png crate's encoding API looks more or less like this:
- Encoder:
Encoder::newEncoder::set_colorEncoder::set_depthEncoder::set_compression+Encoder::set_adaptive_filterbased on a single enum that asks for low/medium/high compression levelEncoder::write_header
- Writer:
Writer::write_text_chunk(not sure how I feel about the latin1 handling here... nothing necessarily wrong here, but 1) IIUCfn encode_iso_8859_1_iterintext_metadata.rswill not reject ASCII control characters, 2) I am not sure if havingStrings as inputs is better or worse than&[u8]- Strings require heap-allocation and going latin1 => String => back to latin1)Writer::into_stream_writer
- Stream writer:
<StreamWriter as Write>::writeStreamWriter::finish
This is fixed in master and shipped in v0.18.0-rc, so I'm going to go ahead and close this.