1
0
mirror of https://github.com/imgproxy/imgproxy.git synced 2024-11-24 08:12:38 +02:00

Fix detecting of width and height of HEIF images that include irot boxes

This commit is contained in:
DarthSim 2024-10-29 19:32:17 +03:00
parent ce2495ab05
commit fa28c86d00
2 changed files with 41 additions and 15 deletions

View File

@ -1,5 +1,9 @@
# Changelog # Changelog
## [Unreleased]
### Fixed
- Fix detecting of width and height of HEIF images that include `irot` boxes.
## [3.26.1] - 2024-10-28 ## [3.26.1] - 2024-10-28
### Changed ### Changed
- (pro) Improve `monochrome` and `duotone` processing options. - (pro) Improve `monochrome` and `duotone` processing options.

View File

@ -2,11 +2,13 @@ package imagemeta
import ( import (
"bytes" "bytes"
"cmp"
"encoding/binary" "encoding/binary"
"errors" "errors"
"fmt" "fmt"
"io" "io"
"math" "math"
"slices"
"github.com/imgproxy/imgproxy/v3/imagetype" "github.com/imgproxy/imgproxy/v3/imagetype"
) )
@ -22,13 +24,33 @@ type heifDiscarder interface {
Discard(n int) (discarded int, err error) Discard(n int) (discarded int, err error)
} }
type heifData struct { type heifSize struct {
Format imagetype.Type
Width, Height int64 Width, Height int64
} }
func (d *heifData) IsFilled() bool { type heifData struct {
return d.Format != imagetype.Unknown && d.Width > 0 && d.Height > 0 Format imagetype.Type
Sizes []heifSize
}
func (d *heifData) Meta() (*meta, error) {
if d.Format == imagetype.Unknown {
return nil, errors.New("Invalid HEIF file: format data wasn't found")
}
if len(d.Sizes) == 0 {
return nil, errors.New("Invalid HEIF file: dimensions data wasn't found")
}
bestSize := slices.MaxFunc(d.Sizes, func(a, b heifSize) int {
return cmp.Compare(a.Width*a.Height, b.Width*b.Height)
})
return &meta{
format: d.Format,
width: int(bestSize.Width),
height: int(bestSize.Height),
}, nil
} }
func heifReadN(r io.Reader, n uint64) (b []byte, err error) { func heifReadN(r io.Reader, n uint64) (b []byte, err error) {
@ -200,9 +222,6 @@ func heifReadBoxes(d *heifData, r io.Reader) error {
if err := heifReadMeta(d, r, boxDataSize); err != nil { if err := heifReadMeta(d, r, boxDataSize); err != nil {
return err return err
} }
if !d.IsFilled() {
return errors.New("Dimensions data wasn't found in meta box")
}
return nil return nil
case "hdlr": case "hdlr":
if err := heifReadHldr(r, boxDataSize); err != nil { if err := heifReadHldr(r, boxDataSize); err != nil {
@ -222,8 +241,15 @@ func heifReadBoxes(d *heifData, r io.Reader) error {
if err != nil { if err != nil {
return err return err
} }
if w > d.Width || h > d.Height { d.Sizes = append(d.Sizes, heifSize{Width: w, Height: h})
d.Width, d.Height = w, h case "irot":
data, err := heifReadN(r, boxDataSize)
if err != nil {
return err
}
if len(d.Sizes) > 0 && len(data) > 0 && (data[0] == 1 || data[0] == 3) {
lastSize := d.Sizes[len(d.Sizes)-1]
d.Sizes[len(d.Sizes)-1] = heifSize{Width: lastSize.Height, Height: lastSize.Width}
} }
default: default:
if err := heifDiscardN(r, boxDataSize); err != nil { if err := heifDiscardN(r, boxDataSize); err != nil {
@ -236,15 +262,11 @@ func heifReadBoxes(d *heifData, r io.Reader) error {
func DecodeHeifMeta(r io.Reader) (Meta, error) { func DecodeHeifMeta(r io.Reader) (Meta, error) {
d := new(heifData) d := new(heifData)
if err := heifReadBoxes(d, r); err != nil && !d.IsFilled() { if err := heifReadBoxes(d, r); err != nil {
return nil, err return nil, err
} }
return &meta{ return d.Meta()
format: d.Format,
width: int(d.Width),
height: int(d.Height),
}, nil
} }
func init() { func init() {