Skip to content

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

@jimdoescode

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.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions