diff --git a/download.go b/download.go index 8d572a9d..9d4e9a83 100644 --- a/download.go +++ b/download.go @@ -10,7 +10,7 @@ import ( "net/http" "time" - imagesize "github.com/imgproxy/imgproxy/image_size" + "github.com/imgproxy/imgproxy/imagemeta" ) var ( @@ -102,20 +102,20 @@ func checkDimensions(width, height int) error { } func checkTypeAndDimensions(r io.Reader) (imageType, error) { - meta, err := imagesize.DecodeMeta(r) - if err == imagesize.ErrFormat { + meta, err := imagemeta.DecodeMeta(r) + if err == imagemeta.ErrFormat { return imageTypeUnknown, errSourceImageTypeNotSupported } if err != nil { return imageTypeUnknown, newUnexpectedError(err.Error(), 0) } - imgtype, imgtypeOk := imageTypes[meta.Format] + imgtype, imgtypeOk := imageTypes[meta.Format()] if !imgtypeOk || !imageTypeLoadSupport(imgtype) { return imageTypeUnknown, errSourceImageTypeNotSupported } - if err = checkDimensions(meta.Width, meta.Height); err != nil { + if err = checkDimensions(meta.Width(), meta.Height()); err != nil { return imageTypeUnknown, err } diff --git a/image_size/bmp.go b/imagemeta/bmp.go similarity index 85% rename from image_size/bmp.go rename to imagemeta/bmp.go index 3e7dc07e..c37feb52 100644 --- a/image_size/bmp.go +++ b/imagemeta/bmp.go @@ -1,4 +1,4 @@ -package imagesize +package imagemeta import ( "bytes" @@ -12,7 +12,7 @@ type BmpFormatError string func (e BmpFormatError) Error() string { return "invalid BMP format: " + string(e) } -func DecodeBmpMeta(r io.Reader) (*Meta, error) { +func DecodeBmpMeta(r io.Reader) (Meta, error) { var tmp [26]byte if _, err := io.ReadFull(r, tmp[:]); err != nil { @@ -36,10 +36,10 @@ func DecodeBmpMeta(r io.Reader) (*Meta, error) { height = int(binary.LittleEndian.Uint16(tmp[20:22])) } - return &Meta{ - Format: "bmp", - Width: width, - Height: height, + return &meta{ + format: "bmp", + width: width, + height: height, }, nil } diff --git a/image_size/gif.go b/imagemeta/gif.go similarity index 50% rename from image_size/gif.go rename to imagemeta/gif.go index dce7d759..3026c8c7 100644 --- a/image_size/gif.go +++ b/imagemeta/gif.go @@ -1,10 +1,10 @@ -package imagesize +package imagemeta import ( "io" ) -func DecodeGifMeta(r io.Reader) (*Meta, error) { +func DecodeGifMeta(r io.Reader) (Meta, error) { var tmp [10]byte _, err := io.ReadFull(r, tmp[:]) @@ -12,10 +12,10 @@ func DecodeGifMeta(r io.Reader) (*Meta, error) { return nil, err } - return &Meta{ - Format: "gif", - Width: int(tmp[6]) + int(tmp[7])<<8, - Height: int(tmp[8]) + int(tmp[9])<<8, + return &meta{ + format: "gif", + width: int(tmp[6]) + int(tmp[7])<<8, + height: int(tmp[8]) + int(tmp[9])<<8, }, nil } diff --git a/image_size/heic.go b/imagemeta/heic.go similarity index 96% rename from image_size/heic.go rename to imagemeta/heic.go index 5ee5db49..5e05996a 100644 --- a/image_size/heic.go +++ b/imagemeta/heic.go @@ -1,4 +1,4 @@ -package imagesize +package imagemeta import ( "bytes" @@ -169,17 +169,17 @@ func heicReadBoxes(d *heicDimensionsData, r io.Reader) error { } } -func DecodeHeicMeta(r io.Reader) (*Meta, error) { +func DecodeHeicMeta(r io.Reader) (Meta, error) { d := new(heicDimensionsData) if err := heicReadBoxes(d, r); err != nil && !d.IsFilled() { return nil, err } - return &Meta{ - Format: "heic", - Width: int(d.Width), - Height: int(d.Height), + return &meta{ + format: "heic", + width: int(d.Width), + height: int(d.Height), }, nil } diff --git a/image_size/ico.go b/imagemeta/ico.go similarity index 62% rename from image_size/ico.go rename to imagemeta/ico.go index 3cba6475..686ac4ca 100644 --- a/image_size/ico.go +++ b/imagemeta/ico.go @@ -1,10 +1,24 @@ -package imagesize +package imagemeta import ( "encoding/binary" "io" ) +type IcoMeta struct { + Meta + offset int + size int +} + +func (m *IcoMeta) BestImageOffset() int { + return m.offset +} + +func (m *IcoMeta) BestImageSize() int { + return m.size +} + func icoBestSize(r io.Reader) (width, height byte, offset uint32, size uint32, err error) { var tmp [16]byte @@ -35,8 +49,8 @@ func BestIcoPage(r io.Reader) (int, int, error) { return int(offset), int(size), err } -func DecodeIcoMeta(r io.Reader) (*Meta, error) { - bwidth, bheight, _, _, err := icoBestSize(r) +func DecodeIcoMeta(r io.Reader) (*IcoMeta, error) { + bwidth, bheight, offset, size, err := icoBestSize(r) if err != nil { return nil, err } @@ -52,13 +66,20 @@ func DecodeIcoMeta(r io.Reader) (*Meta, error) { height = 256 } - return &Meta{ - Format: "ico", - Width: width, - Height: height, + return &IcoMeta{ + Meta: &meta{ + format: "ico", + width: width, + height: height, + }, + offset: int(offset), + size: int(size), }, nil } func init() { - RegisterFormat("\x00\x00\x01\x00", DecodeIcoMeta) + RegisterFormat( + "\x00\x00\x01\x00", + func(r io.Reader) (Meta, error) { return DecodeIcoMeta(r) }, + ) } diff --git a/image_size/image_meta.go b/imagemeta/image_meta.go similarity index 67% rename from image_size/image_meta.go rename to imagemeta/image_meta.go index 9b034719..575f45ad 100644 --- a/image_size/image_meta.go +++ b/imagemeta/image_meta.go @@ -1,4 +1,4 @@ -package imagesize +package imagemeta import ( "bufio" @@ -8,14 +8,34 @@ import ( "sync/atomic" ) -type Meta struct { - Format string - Width, Height int +type Meta interface { + Format() string + Width() int + Height() int +} + +type DecodeMetaFunc func(io.Reader) (Meta, error) + +type meta struct { + format string + width, height int +} + +func (m *meta) Format() string { + return m.format +} + +func (m *meta) Width() int { + return m.width +} + +func (m *meta) Height() int { + return m.height } type format struct { magic string - decodeMeta func(io.Reader) (*Meta, error) + decodeMeta DecodeMetaFunc } type reader interface { @@ -49,7 +69,7 @@ func matchMagic(magic string, b []byte) bool { return true } -func RegisterFormat(magic string, decodeMeta func(io.Reader) (*Meta, error)) { +func RegisterFormat(magic string, decodeMeta DecodeMetaFunc) { formatsMu.Lock() defer formatsMu.Unlock() @@ -57,7 +77,7 @@ func RegisterFormat(magic string, decodeMeta func(io.Reader) (*Meta, error)) { atomicFormats.Store(append(formats, format{magic, decodeMeta})) } -func DecodeMeta(r io.Reader) (*Meta, error) { +func DecodeMeta(r io.Reader) (Meta, error) { rr := asReader(r) formats, _ := atomicFormats.Load().([]format) diff --git a/image_size/jpeg.go b/imagemeta/jpeg.go similarity index 92% rename from image_size/jpeg.go rename to imagemeta/jpeg.go index 15136515..4ace1589 100644 --- a/image_size/jpeg.go +++ b/imagemeta/jpeg.go @@ -1,4 +1,4 @@ -package imagesize +package imagemeta import ( "bufio" @@ -32,7 +32,7 @@ type JpegFormatError string func (e JpegFormatError) Error() string { return "invalid JPEG format: " + string(e) } -func DecodeJpegMeta(rr io.Reader) (*Meta, error) { +func DecodeJpegMeta(rr io.Reader) (Meta, error) { var tmp [512]byte r := asJpegReader(rr) @@ -100,10 +100,10 @@ func DecodeJpegMeta(rr io.Reader) (*Meta, error) { return nil, JpegFormatError("unsupported precision") } - return &Meta{ - Format: "jpeg", - Width: int(tmp[3])<<8 + int(tmp[4]), - Height: int(tmp[1])<<8 + int(tmp[2]), + return &meta{ + format: "jpeg", + width: int(tmp[3])<<8 + int(tmp[4]), + height: int(tmp[1])<<8 + int(tmp[2]), }, nil } diff --git a/image_size/png.go b/imagemeta/png.go similarity index 72% rename from image_size/png.go rename to imagemeta/png.go index 8aba1de7..946116c2 100644 --- a/image_size/png.go +++ b/imagemeta/png.go @@ -1,4 +1,4 @@ -package imagesize +package imagemeta import ( "bytes" @@ -12,7 +12,7 @@ type PngFormatError string func (e PngFormatError) Error() string { return "invalid PNG format: " + string(e) } -func DecodePngMeta(r io.Reader) (*Meta, error) { +func DecodePngMeta(r io.Reader) (Meta, error) { var tmp [16]byte if _, err := io.ReadFull(r, tmp[:8]); err != nil { @@ -27,10 +27,10 @@ func DecodePngMeta(r io.Reader) (*Meta, error) { return nil, err } - return &Meta{ - Format: "png", - Width: int(binary.BigEndian.Uint32(tmp[8:12])), - Height: int(binary.BigEndian.Uint32(tmp[12:16])), + return &meta{ + format: "png", + width: int(binary.BigEndian.Uint32(tmp[8:12])), + height: int(binary.BigEndian.Uint32(tmp[12:16])), }, nil } diff --git a/image_size/svg.go b/imagemeta/svg.go similarity index 64% rename from image_size/svg.go rename to imagemeta/svg.go index 6b48631c..8dbae67e 100644 --- a/image_size/svg.go +++ b/imagemeta/svg.go @@ -1,4 +1,4 @@ -package imagesize +package imagemeta import ( "io" @@ -7,8 +7,8 @@ import ( func init() { // Register fake svg decoder. Since we need this only for type detecting, we can // return fake image sizes - decodeMeta := func(io.Reader) (*Meta, error) { - return &Meta{Format: "svg", Width: 1, Height: 1}, nil + decodeMeta := func(io.Reader) (Meta, error) { + return &meta{format: "svg", width: 1, height: 1}, nil } RegisterFormat(" 0 && height > 0 { - return &Meta{ - Format: "tiff", - Width: width, - Height: height, + return &meta{ + format: "tiff", + width: width, + height: height, }, nil } } diff --git a/image_size/webp.go b/imagemeta/webp.go similarity index 84% rename from image_size/webp.go rename to imagemeta/webp.go index 5e1b75f3..90f6123f 100644 --- a/image_size/webp.go +++ b/imagemeta/webp.go @@ -4,7 +4,7 @@ // Original code was cropped and fixed by @DarthSim for imgproxy needs -package imagesize +package imagemeta import ( "errors" @@ -25,7 +25,7 @@ var ( webpFccWEBP = riff.FourCC{'W', 'E', 'B', 'P'} ) -func DecodeWebpMeta(r io.Reader) (*Meta, error) { +func DecodeWebpMeta(r io.Reader) (Meta, error) { formType, riffReader, err := riff.NewReader(r) if err != nil { return nil, err @@ -58,10 +58,10 @@ func DecodeWebpMeta(r io.Reader) (*Meta, error) { fh, err := d.DecodeFrameHeader() - return &Meta{ - Format: "webp", - Width: fh.Width, - Height: fh.Height, + return &meta{ + format: "webp", + width: fh.Width, + height: fh.Height, }, err case webpFccVP8L: @@ -70,10 +70,10 @@ func DecodeWebpMeta(r io.Reader) (*Meta, error) { return nil, err } - return &Meta{ - Format: "webp", - Width: conf.Width, - Height: conf.Height, + return &meta{ + format: "webp", + width: conf.Width, + height: conf.Height, }, nil case webpFccVP8X: @@ -88,10 +88,10 @@ func DecodeWebpMeta(r io.Reader) (*Meta, error) { widthMinusOne := uint32(buf[4]) | uint32(buf[5])<<8 | uint32(buf[6])<<16 heightMinusOne := uint32(buf[7]) | uint32(buf[8])<<8 | uint32(buf[9])<<16 - return &Meta{ - Format: "webp", - Width: int(widthMinusOne) + 1, - Height: int(heightMinusOne) + 1, + return &meta{ + format: "webp", + width: int(widthMinusOne) + 1, + height: int(heightMinusOne) + 1, }, nil default: diff --git a/process.go b/process.go index a2c3b7b7..49a349c7 100644 --- a/process.go +++ b/process.go @@ -7,7 +7,7 @@ import ( "math" "runtime" - imagesize "github.com/imgproxy/imgproxy/image_size" + "github.com/imgproxy/imgproxy/imagemeta" "golang.org/x/sync/errgroup" ) @@ -564,26 +564,29 @@ func transformAnimated(ctx context.Context, img *vipsImage, data []byte, po *pro } func getIcoData(imgdata *imageData) (*imageData, error) { - offset, size, err := imagesize.BestIcoPage(bytes.NewBuffer(imgdata.Data)) + icoMeta, err := imagemeta.DecodeIcoMeta(bytes.NewReader(imgdata.Data)) if err != nil { return nil, err } + offset := icoMeta.BestImageOffset() + size := icoMeta.BestImageSize() + data := imgdata.Data[offset : offset+size] - meta, err := imagesize.DecodeMeta(bytes.NewBuffer(data)) + meta, err := imagemeta.DecodeMeta(bytes.NewReader(data)) if err != nil { return nil, err } - if imgtype, ok := imageTypes[meta.Format]; ok && vipsTypeSupportLoad[imgtype] { + if imgtype, ok := imageTypes[meta.Format()]; ok && vipsTypeSupportLoad[imgtype] { return &imageData{ Data: data, Type: imgtype, }, nil } - return nil, fmt.Errorf("Can't load %s from ICO", meta.Format) + return nil, fmt.Errorf("Can't load %s from ICO", meta.Format()) } func saveImageToFitBytes(po *processingOptions, img *vipsImage) ([]byte, context.CancelFunc, error) { diff --git a/processing_options.go b/processing_options.go index 869765b4..092d9551 100644 --- a/processing_options.go +++ b/processing_options.go @@ -12,7 +12,7 @@ import ( "strings" "sync" - structdiff "github.com/imgproxy/imgproxy/struct-diff" + "github.com/imgproxy/imgproxy/structdiff" ) type urlOption struct { diff --git a/struct-diff/diff.go b/structdiff/diff.go similarity index 100% rename from struct-diff/diff.go rename to structdiff/diff.go