}
func (d *WebpCodec) Encode(w io.Writer, img image.Image) error {
+ return d.EncodeOptions(w, img, nil)
+}
+
+func (d *WebpCodec) EncodeOptions(w io.Writer, img image.Image, options map[string]any) error {
b := img.Bounds()
if b.Dx() >= 1<<16 || b.Dy() >= 1<<16 {
return errors.New("webp: image is too large to encode")
// encodeGray
// decode
// config
+
+ opts := map[string]any{
+ "quality": d.quality, // a number between 0 and 100. Set to 0 for lossless.
+ "hint": d.hint, // drawing, icon, photo, picture, or text
+ "useSharpYuv": true, // Use sharp (and slow) RGB->YUV conversion.
+ }
+
+ // Override with per-image options if provided.
+ for _, key := range []string{"quality", "hint"} {
+ if v, ok := options[key]; ok {
+ opts[key] = v
+ }
+ }
+
message := Message[WebpInput]{
Header: Header{
Version: 1,
Data: WebpInput{
Source: bytes.NewReader(imageBytes),
Destination: w,
- Options: map[string]any{
- "quality": d.quality, // a number between 0 and 100. Set to 0 for lossless.
- "hint": d.hint, // drawing, icon, photo, picture, or text
- "useSharpYuv": true, // Use sharp (and slow) RGB->YUV conversion.
- },
+ Options: opts,
Params: map[string]any{
"width": bounds.Max.X,
"height": bounds.Max.Y,
EncodeTo(conf ImageConfig, w io.Writer, src image.Image) error
}
+// EncoderWithOptions defines the encoding of an image format with options.
+// This is currently only used for WebP and the options are passed as a map
+// to match the internal WASM API. The options map may be nil when no options
+// need to be overridden.
+type EncoderWithOptions interface {
+ EncodeOptions(w io.Writer, src image.Image, options map[string]any) error
+}
+
// CodecStdlib defines both decoding and encoding of an image format as defined by the standard library.
type CodecStdlib interface {
Decoder
case BMP:
return bmp.Encode(w, img)
case WEBP:
+ if enc, ok := d.webp.(EncoderWithOptions); ok {
+ var opts map[string]any
+ if conf.qualitySetForImage || conf.hintSetForImage {
+ opts = make(map[string]any)
+ if conf.qualitySetForImage {
+ opts["quality"] = conf.Quality
+ }
+ if conf.hintSetForImage {
+ opts["hint"] = conf.Hint
+ }
+ }
+ return enc.EncodeOptions(w, img, opts)
+ }
return d.webp.Encode(w, img)
default:
return errors.New("format not supported")
c.Filter = filter
} else if _, ok := hints[part]; ok {
c.Hint = part
+ c.hintSetForImage = true
} else if part[0] == '#' {
c.BgColor, err = hexStringToColorGo(part[1:])
if err != nil {
if err != nil {
return c, err
}
- if c.Quality < 1 || c.Quality > 100 {
- return c, errors.New("quality ranges from 1 to 100 inclusive")
+ if c.Quality < 0 || c.Quality > 100 {
+ return c, errors.New("quality ranges from 0 to 100 inclusive")
}
c.qualitySetForImage = true
} else if part[0] == 'r' {
c.TargetFormat = sourceFormat
}
- if c.Quality <= 0 && c.TargetFormat.RequiresDefaultQuality() {
- // We need a quality setting for all JPEGs and WEBPs.
+ if !c.qualitySetForImage && c.Quality <= 0 && c.TargetFormat.RequiresDefaultQuality() {
+ // We need a quality setting for all JPEGs and WEBPs,
+ // unless the user explicitly set quality (e.g., q0 for lossless WebP).
c.Quality = defaults.Config.Imaging.Quality
}
// Hint about what type of picture this is. Used to optimize encoding
// when target is set to webp.
- Hint string
+ Hint string
+ hintSetForImage bool // Whether the above is set for this image.
Width int
Height int
{{ template "process" (dict "spec" "png" "img" $highContrast) }}
{{ template "process" (dict "spec" "resize 300x300" "img" $giphy) }}
{{ template "process" (dict "spec" "resize 300x300 webp" "img" $giphy) }}
+{{ template "process" (dict "spec" "resize 300x300 webp q0" "img" $sunset) }}
+{{ template "process" (dict "spec" "resize 300x300 webp q1" "img" $sunset) }}
+{{ template "process" (dict "spec" "resize 300x300 webp q33" "img" $sunset) }}
+{{ template "process" (dict "spec" "resize 300x300 webp q75" "img" $sunset) }}
+{{ template "process" (dict "spec" "resize 300x300 webp q100" "img" $sunset) }}
+{{ template "process" (dict "spec" "resize 300x300 webp drawing" "img" $sunset) }}
+{{ template "process" (dict "spec" "resize 300x300 webp icon" "img" $sunset) }}
+{{ template "process" (dict "spec" "resize 300x300 webp q50 drawing" "img" $sunset) }}
{{ template "process" (dict "spec" "resize 400x" "img" $highContrast) }}
{{ define "process"}}