diff --git a/go.mod b/go.mod index 6ba09628..991ff9fc 100644 --- a/go.mod +++ b/go.mod @@ -5,6 +5,7 @@ go 1.16 require ( github.com/DataDog/zstd v1.4.0 // indirect github.com/Sereal/Sereal v0.0.0-20190430203904-6faf9605eb56 // indirect + github.com/adrium/goheif v0.0.0-20210309200126-b184a7b446fa github.com/asdine/storm v2.1.2+incompatible github.com/caddyserver/caddy v1.0.3 github.com/dgrijalva/jwt-go v3.2.0+incompatible diff --git a/go.sum b/go.sum index e104a73b..43b699d1 100644 --- a/go.sum +++ b/go.sum @@ -6,6 +6,8 @@ github.com/DataDog/zstd v1.4.0/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/Sereal/Sereal v0.0.0-20190430203904-6faf9605eb56 h1:3trCIB5GsAOIY8NxlfMztCYIhVsW9V5sZ+brsecjaiI= github.com/Sereal/Sereal v0.0.0-20190430203904-6faf9605eb56/go.mod h1:D0JMgToj/WdxCgd30Kc1UcA9E+WdZoJqeVOuYW7iTBM= +github.com/adrium/goheif v0.0.0-20210309200126-b184a7b446fa h1:ISwtQHwIaKiwhFFmBOIib1o1jH3UvtKPnsEo45zsVj0= +github.com/adrium/goheif v0.0.0-20210309200126-b184a7b446fa/go.mod h1:aKVJoQ0cc9K5Xb058XSnnAxXLliR97qbSqWBlm5ca1E= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= diff --git a/img/service.go b/img/service.go index ce90401d..444d4437 100644 --- a/img/service.go +++ b/img/service.go @@ -8,7 +8,9 @@ import ( "fmt" "image" "io" + "strings" + "github.com/adrium/goheif" "github.com/disintegration/imaging" "github.com/dsoprea/go-exif/v3" "github.com/marusama/semaphore/v2" @@ -38,6 +40,7 @@ png gif tiff bmp +heic ) */ type Format int @@ -90,22 +93,25 @@ fill type ResizeMode int func (s *Service) FormatFromExtension(ext string) (Format, error) { - format, err := imaging.FormatFromExtension(ext) - if err != nil { - return -1, ErrUnsupportedFormat + if format, err := imaging.FormatFromExtension(ext); err == nil { + switch format { + case imaging.JPEG: + return FormatJpeg, nil + case imaging.PNG: + return FormatPng, nil + case imaging.GIF: + return FormatGif, nil + case imaging.TIFF: + return FormatTiff, nil + case imaging.BMP: + return FormatBmp, nil + } } - switch format { - case imaging.JPEG: - return FormatJpeg, nil - case imaging.PNG: - return FormatPng, nil - case imaging.GIF: - return FormatGif, nil - case imaging.TIFF: - return FormatTiff, nil - case imaging.BMP: - return FormatBmp, nil + + if strings.EqualFold(ext, ".heif") || strings.EqualFold(ext, ".heic") { + return FormatHeic, nil } + return -1, ErrUnsupportedFormat } @@ -166,7 +172,13 @@ func (s *Service) Resize(ctx context.Context, in io.Reader, width, height int, o } } - img, err := imaging.Decode(wrappedReader, imaging.AutoOrientation(true)) + var img image.Image + if format == FormatHeic { + img, err = goheif.Decode(wrappedReader) + } else { + img, err = imaging.Decode(wrappedReader, imaging.AutoOrientation(true)) + } + if err != nil { return err } diff --git a/img/service_enum.go b/img/service_enum.go index 33826438..f96782f2 100644 --- a/img/service_enum.go +++ b/img/service_enum.go @@ -19,9 +19,11 @@ const ( FormatTiff // FormatBmp is a Format of type Bmp FormatBmp + // FormatHeic is a Format of type Heic + FormatHeic ) -const _FormatName = "jpegpnggiftiffbmp" +const _FormatName = "jpegpnggiftiffbmpheic" var _FormatMap = map[Format]string{ 0: _FormatName[0:4], @@ -29,6 +31,7 @@ var _FormatMap = map[Format]string{ 2: _FormatName[7:10], 3: _FormatName[10:14], 4: _FormatName[14:17], + 5: _FormatName[17:21], } // String implements the Stringer interface. @@ -45,6 +48,7 @@ var _FormatValue = map[string]Format{ _FormatName[7:10]: 2, _FormatName[10:14]: 3, _FormatName[14:17]: 4, + _FormatName[17:21]: 5, } // ParseFormat attempts to convert a string to a Format diff --git a/img/service_test.go b/img/service_test.go index f10188f5..e5ec766e 100644 --- a/img/service_test.go +++ b/img/service_test.go @@ -176,6 +176,16 @@ func TestService_Resize(t *testing.T) { }, matcher: sizeMatcher(100, 100), }, + "resize heic": { + options: []Option{WithMode(ResizeModeFill)}, + width: 100, + height: 100, + source: func(t *testing.T) afero.File { + t.Helper() + return openFile(t, "testdata/image3.heic") + }, + matcher: sizeMatcher(100, 100), + }, "resize with high quality": { options: []Option{WithMode(ResizeModeFill), WithQuality(QualityHigh)}, width: 100, @@ -427,6 +437,14 @@ func TestService_FormatFromExtension(t *testing.T) { ext: ".bmp", want: FormatBmp, }, + "heic": { + ext: ".heic", + want: FormatHeic, + }, + "heif": { + ext: ".heif", + want: FormatHeic, + }, "unknown": { ext: ".mov", wantErr: ErrUnsupportedFormat, diff --git a/img/testdata/image3.heic b/img/testdata/image3.heic new file mode 100644 index 00000000..09b62aaf Binary files /dev/null and b/img/testdata/image3.heic differ