mirror of
https://github.com/willnorris/imageproxy.git
synced 2024-12-16 21:56:43 -05:00
add support for specifying output image format
For now, the options are "jpeg" and "png". Gif is a little harder to support because of the way we use the image/gif package to handle animated gifs. I have also have trouble imagining someone wanting to use gif over png. But if the need really exists, we can address it when it comes up. Fixes #89
This commit is contained in:
parent
2937bf84f6
commit
b9cc9df4b6
4 changed files with 37 additions and 8 deletions
21
data.go
21
data.go
|
@ -28,6 +28,8 @@ const (
|
|||
optFit = "fit"
|
||||
optFlipVertical = "fv"
|
||||
optFlipHorizontal = "fh"
|
||||
optFormatJPEG = "jpeg"
|
||||
optFormatPNG = "png"
|
||||
optRotatePrefix = "r"
|
||||
optQualityPrefix = "q"
|
||||
optSignaturePrefix = "s"
|
||||
|
@ -71,6 +73,9 @@ type Options struct {
|
|||
// Allow image to scale beyond its original dimensions. This value
|
||||
// will always be overwritten by the value of Proxy.ScaleUp.
|
||||
ScaleUp bool
|
||||
|
||||
// Desired image format. Valid values are "jpeg", "png".
|
||||
Format string
|
||||
}
|
||||
|
||||
func (o Options) String() string {
|
||||
|
@ -97,14 +102,18 @@ func (o Options) String() string {
|
|||
if o.ScaleUp {
|
||||
fmt.Fprintf(buf, ",%s", optScaleUp)
|
||||
}
|
||||
if o.Format != "" {
|
||||
fmt.Fprintf(buf, ",%s", o.Format)
|
||||
}
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
// transform returns whether o includes transformation options. Some fields
|
||||
// are not transform related at all (like Signature), and others only apply in
|
||||
// the presence of other fields (like Fit and Quality).
|
||||
// the presence of other fields (like Fit and Quality). A non-empty Format
|
||||
// value is assumed to involve a transformation.
|
||||
func (o Options) transform() bool {
|
||||
return o.Width != 0 || o.Height != 0 || o.Rotate != 0 || o.FlipHorizontal || o.FlipVertical
|
||||
return o.Width != 0 || o.Height != 0 || o.Rotate != 0 || o.FlipHorizontal || o.FlipVertical || o.Format != ""
|
||||
}
|
||||
|
||||
// ParseOptions parses str as a list of comma separated transformation options.
|
||||
|
@ -153,6 +162,11 @@ func (o Options) transform() bool {
|
|||
// The "q{qualityPercentage}" option can be used to specify the quality of the
|
||||
// output file (JPEG only). If not specified, the default value of "95" is used.
|
||||
//
|
||||
// Format
|
||||
//
|
||||
// The "jpeg" and "png" options can be used to specify the desired image format
|
||||
// of the proxied image.
|
||||
//
|
||||
// Signature
|
||||
//
|
||||
// The "s{signature}" option specifies an optional base64 encoded HMAC used to
|
||||
|
@ -174,6 +188,7 @@ func (o Options) transform() bool {
|
|||
// 100,r90 - 100 pixels square, rotated 90 degrees
|
||||
// 100,fv,fh - 100 pixels square, flipped horizontal and vertical
|
||||
// 200x,q80 - 200 pixels wide, proportional height, 80% quality
|
||||
// 200x,png - 200 pixels wide, converted to PNG format
|
||||
func ParseOptions(str string) Options {
|
||||
var options Options
|
||||
|
||||
|
@ -189,6 +204,8 @@ func ParseOptions(str string) Options {
|
|||
options.FlipHorizontal = true
|
||||
case opt == optScaleUp: // this option is intentionally not documented above
|
||||
options.ScaleUp = true
|
||||
case opt == optFormatJPEG, opt == optFormatPNG:
|
||||
options.Format = opt
|
||||
case strings.HasPrefix(opt, optRotatePrefix):
|
||||
value := strings.TrimPrefix(opt, optRotatePrefix)
|
||||
options.Rotate, _ = strconv.Atoi(value)
|
||||
|
|
12
data_test.go
12
data_test.go
|
@ -31,12 +31,12 @@ func TestOptions_String(t *testing.T) {
|
|||
"0x0",
|
||||
},
|
||||
{
|
||||
Options{1, 2, true, 90, true, true, 80, "", false},
|
||||
Options{1, 2, true, 90, true, true, 80, "", false, ""},
|
||||
"1x2,fit,r90,fv,fh,q80",
|
||||
},
|
||||
{
|
||||
Options{0.15, 1.3, false, 45, false, false, 95, "c0ffee", false},
|
||||
"0.15x1.3,r45,q95,sc0ffee",
|
||||
Options{0.15, 1.3, false, 45, false, false, 95, "c0ffee", false, "png"},
|
||||
"0.15x1.3,r45,q95,sc0ffee,png",
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -72,6 +72,7 @@ func TestParseOptions(t *testing.T) {
|
|||
{"r90", Options{Rotate: 90}},
|
||||
{"fv", Options{FlipVertical: true}},
|
||||
{"fh", Options{FlipHorizontal: true}},
|
||||
{"jpeg", Options{Format: "jpeg"}},
|
||||
|
||||
// duplicate flags (last one wins)
|
||||
{"1x2,3x4", Options{Width: 3, Height: 4}},
|
||||
|
@ -79,13 +80,14 @@ func TestParseOptions(t *testing.T) {
|
|||
{"1x2,0x3", Options{Width: 0, Height: 3}},
|
||||
{"1x,x2", Options{Width: 1, Height: 2}},
|
||||
{"r90,r270", Options{Rotate: 270}},
|
||||
{"jpeg,png", Options{Format: "png"}},
|
||||
|
||||
// mix of valid and invalid flags
|
||||
{"FOO,1,BAR,r90,BAZ", Options{Width: 1, Height: 1, Rotate: 90}},
|
||||
|
||||
// all flags, in different orders
|
||||
{"q70,1x2,fit,r90,fv,fh,sc0ffee", Options{1, 2, true, 90, true, true, 70, "c0ffee", false}},
|
||||
{"r90,fh,sc0ffee,q90,1x2,fv,fit", Options{1, 2, true, 90, true, true, 90, "c0ffee", false}},
|
||||
{"q70,1x2,fit,r90,fv,fh,sc0ffee,png", Options{1, 2, true, 90, true, true, 70, "c0ffee", false, "png"}},
|
||||
{"r90,fh,sc0ffee,png,q90,1x2,fv,fit", Options{1, 2, true, 90, true, true, 90, "c0ffee", false, "png"}},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
|
|
|
@ -306,7 +306,10 @@ func (t *TransformingTransport) RoundTrip(req *http.Request) (*http.Response, er
|
|||
// replay response with transformed image and updated content length
|
||||
buf := new(bytes.Buffer)
|
||||
fmt.Fprintf(buf, "%s %s\n", resp.Proto, resp.Status)
|
||||
resp.Header.WriteSubset(buf, map[string]bool{"Content-Length": true})
|
||||
resp.Header.WriteSubset(buf, map[string]bool{
|
||||
"Content-Length": true,
|
||||
"Content-Type": opt.Format != "",
|
||||
})
|
||||
fmt.Fprintf(buf, "Content-Length: %d\n\n", len(img))
|
||||
buf.Write(img)
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@ package imageproxy
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"image"
|
||||
_ "image/gif" // register gif format
|
||||
"image/jpeg"
|
||||
|
@ -46,6 +47,10 @@ func Transform(img []byte, opt Options) ([]byte, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
if opt.Format != "" {
|
||||
format = opt.Format
|
||||
}
|
||||
|
||||
// transform and encode image
|
||||
buf := new(bytes.Buffer)
|
||||
switch format {
|
||||
|
@ -74,6 +79,8 @@ func Transform(img []byte, opt Options) ([]byte, error) {
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
default:
|
||||
return nil, fmt.Errorf("unsupported format: %v", format)
|
||||
}
|
||||
|
||||
return buf.Bytes(), nil
|
||||
|
|
Loading…
Reference in a new issue