Skip to content

Improve API design for Codecs #26

Description

@JimBobSquarePants

At present we have to pass many options to the codecs as parameters. There is also ambiguity over what exactly "Quality" means - Sometimes it's color count, sometimes compression.

We need to:

  • Create Options classes to pass to the encoders and decoders to reduce parameter count.
  • Remove Quality property from Image<TColor, TPacked>
  • Create overload for Image<TColor, TPacked> that allows passing a specific decoder or decoders with options.

Activity

  1. added this to the milestone on Nov 29, 2016
  2. olivif commented on Dec 22, 2016

    @olivif
    Contributor

    I did a little bit of digging through the code on this, and had some thoughts and questions.

    So, if I understand correctly, we want to have an options class - for encoders let's say for now - so EncoderOptions.

    These options would be used in all IImageEncoders in Encode, possibly like this

    public void Encode<TColor, TPacked>(Image<TColor, TPacked> image, Stream stream, IEncoderOptions encoderOptions)

    There seems to be some overlap in the options between encoders but encoders also have options that are specific to them, and therefore doesn't make sense to have in the generic EncoderOptions - for example the BmpEncoderCore uses BmpBitsPerPixel.

    One idea to solve this is to have a generic IEncoderOptions which has all the common options - if any, and then have derived options for any other format specific ones.

    I tried this out in a branch for BmpEncoder - it works, but I think it sucks a little bit because of the casting to the concrete type in BmpEncoder. Also, it would be good if the core encoders could actually be IImageEncoders and share an interface - which using this they could do if the IEncoderOptions is added to the Encode interface, but then the cast would have to move inside the Core object. Which maybe is OK.

    Thoughts?

  3. dlemstra commented on Dec 22, 2016

    @dlemstra
    Member

    @olivif I am working on some changes to the encoders. I used different naming but I will use yours to explain what I did. I added anIEncoderOptions argument to the Encode method and added and IBmpEncoderOptions argument in the SaveAsBmp method but your idea got me thinking. The encoder method has two overloads. One with IEncoderOptions and one with IBmpEncoderOptions. I could try to cast the object that is passed in to the IEncoderOptions overload and call the IBmpEncoderOptions overload if that works. Then someone could creat a single object that implements the various encoder options. The only issue with that is that you have some kind of hidden functionality. I would rather make it so people can see it in the API.

  4. olivif commented on Dec 22, 2016

    @olivif
    Contributor

    The encoder method has two overloads. One with IEncoderOptions and one with IBmpEncoderOptions.

    Will the IBmpEncoderOptions overload be in the IEncoder interface? If it is, then it would be a bit odd to have format specific stuff in there. If it's not, it would also be kind of odd since you wouldn't be enforcing the specific encoding method on let's say a new type of encoder.

    Then someone could create a single object that implements the various encoder options.

    Hmm this got me thinking as well. We are trying to solve this using an approach that involves passing in the options at "encoding time", so when calling encode. Here's another idea, what if we push the options initialization into the constructor? Right now even with this Encode approach it's half in ctor half in the method, since you have some defaults anyway. So, we push the responsibility of initializing the encoder with the correct configuration in the ctor. Whoever knows the concrete type will know they need to pass in a Bmp specific options and that seems a little less weird. The only challenge with this is that you need to create an encoder per encode operation, if you want different options. Not sure if that works with the other parts of the stack, haven't dug much into the upper layers.

  5. dlemstra commented on Dec 22, 2016

    @dlemstra
    Member

    The IBmpEncoderOptions will only be available in the BmpEncoder. Moving it from a property to the constructor is prob a good idea and I will try and make that work. But that won't really change much for the rest of the API. The Save method: public Image<TColor> Save(Stream stream, IEncoderOptions options) will have the same signature.

  6. olivif commented on Dec 22, 2016

    @olivif
    Contributor

    Yep, that sounds great to me! Clean interface and specific implementation options hidden in the implementation. Perfection ❤️

  7. added a commit that references this issue on Jan 18, 2020
  8. added 2 commits that reference this issue on Feb 17, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions