Skip to content

image: Make image encoding methods consistent across JPG, GIF, and PNG #12572

Description

@jimdoescode

Greetings.

As far as I can tell, Go currently supports encoding an image.Image into 3 image file formats; JPEG, GIF and PNG.

Each format has its own encode method. Both jpeg.Encode and gif.Encode are fairly similar but with different Options structs (jpeg.Options, gif.Options). However png.Encode does not have an Options requirement in its method signature. png.Encode actually uses a separate struct, png.Encoder, which has an Encode method on it, so png.Encode is really just calling png.Encoder.Encode.

Problem
There is no uniform way to encode an image.Image. Also encoding is done in the various sub-packages (image/jpeg, image/gif, image/png) while decoding is done in the image package, so two inverse functions don't exist on the same package levels.

Proposal
I propose that the GIF and JPEG packages be done the same way as PNG, and that an interface be created; image.FormatEncoder, which would wrap all of the _.Encoder.Encode methods. Then an image.Encode(w io.Writer, m Image, enc FormatEncoder) error function be added. See below for my suggested changes to the image packages.

//package "image/jpeg"
type Encoder struct {
    Quality int
}

func (enc *Encoder) Encode(w io.Writer, m Image) error {
    //Do encoding
}
//package "image/gif"
type Encoder struct {
    NumColors int
    Quantizer draw.Quantizer
    Drawer draw.Drawer
}

func (enc *Encoder) Encode(w io.Writer, m Image) error {
    //Do encoding
}
//package "image"
type FormatEncoder interface {
    Encode(io.Writer, Image) error
}

func Encode(w io.Writer, m Image, enc *FormatEncoder) error {
    return enc.Encode(w, m)
}

Notes
If you look at the _.Encoder structs for gif and jpeg, they have the same properties as the old _.Options structs used by the old Encode functions.

Consequences
png.Encode, gif.Encode, gif.Options, jpeg.Encode, and jpep.Options would become deprecated in favor of using image.Encode and passing in the relevant encoder struct.

Any explicit encoding would need to invoke the relevant Encoder struct to call the Encode method on it (it's not a single function call anymore).

Next Steps
I have most of these changes already finished. I need to write a few tests to verify things work as expected, and wanted to get sign off before proceeding further.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions