From 697261da53cdb0b4230cb800d71bf333b367bff4 Mon Sep 17 00:00:00 2001 From: tobi <31960611+tsmethurst@users.noreply.github.com> Date: Wed, 31 Jul 2024 20:43:39 +0200 Subject: [PATCH] [chore] Take account of rotation data when calculating full size image dimensions (#3159) * [chore] Take account of rotation data when calculating full size image dimensions * boobies --- internal/media/ffmpeg.go | 103 ++++++++++++++++-------------- internal/media/processingmedia.go | 1 - internal/media/util.go | 29 ++++++--- 3 files changed, 74 insertions(+), 59 deletions(-) diff --git a/internal/media/ffmpeg.go b/internal/media/ffmpeg.go index 0de5797ab..e26ec78d7 100644 --- a/internal/media/ffmpeg.go +++ b/internal/media/ffmpeg.go @@ -437,54 +437,6 @@ func (res *ffprobeResult) Process() (*result, error) { } } - // Preallocate streams to max possible lengths. - r.audio = make([]audioStream, 0, len(res.Streams)) - r.video = make([]videoStream, 0, len(res.Streams)) - - // Convert streams to separate types. - for _, s := range res.Streams { - switch s.CodecType { - case "audio": - // Append audio stream data to result. - r.audio = append(r.audio, audioStream{ - stream: stream{codec: s.CodecName}, - }) - case "video": - var framerate float32 - - // Parse stream framerate, bearing in - // mind that some static container formats - // (e.g. jpeg) still return a framerate, so - // we also check for a non-1 timebase (dts). - if str := s.RFrameRate; str != "" && - s.DurationTS > 1 { - var num, den uint32 - den = 1 - - // Check for inequality (numerator / denominator). - if p := strings.SplitN(str, "/", 2); len(p) == 2 { - n, _ := strconv.ParseUint(p[0], 10, 32) - d, _ := strconv.ParseUint(p[1], 10, 32) - num, den = uint32(n), uint32(d) - } else { - n, _ := strconv.ParseUint(p[0], 10, 32) - num = uint32(n) - } - - // Set final divised framerate. - framerate = float32(num / den) - } - - // Append video stream data to result. - r.video = append(r.video, videoStream{ - stream: stream{codec: s.CodecName}, - width: s.Width, - height: s.Height, - framerate: framerate, - }) - } - } - // Check extra packet / frame information // for provided orientation (not always set). for _, pf := range res.PacketsAndFrames { @@ -521,6 +473,61 @@ func (res *ffprobeResult) Process() (*result, error) { } } + // Preallocate streams to max possible lengths. + r.audio = make([]audioStream, 0, len(res.Streams)) + r.video = make([]videoStream, 0, len(res.Streams)) + + // Convert streams to separate types. + for _, s := range res.Streams { + switch s.CodecType { + case "audio": + // Append audio stream data to result. + r.audio = append(r.audio, audioStream{ + stream: stream{codec: s.CodecName}, + }) + case "video": + // Determine proper display dimensions, + // taking account of rotation data. + width, height := displayDimensions( + s.Width, + s.Height, + r.rotation, + ) + + // Parse stream framerate, bearing in + // mind that some static container formats + // (e.g. jpeg) still return a framerate, so + // we also check for a non-1 timebase (dts). + var framerate float32 + if str := s.RFrameRate; str != "" && + s.DurationTS > 1 { + var num, den uint32 + den = 1 + + // Check for inequality (numerator / denominator). + if p := strings.SplitN(str, "/", 2); len(p) == 2 { + n, _ := strconv.ParseUint(p[0], 10, 32) + d, _ := strconv.ParseUint(p[1], 10, 32) + num, den = uint32(n), uint32(d) + } else { + n, _ := strconv.ParseUint(p[0], 10, 32) + num = uint32(n) + } + + // Set final divised framerate. + framerate = float32(num / den) + } + + // Append video stream data to result. + r.video = append(r.video, videoStream{ + stream: stream{codec: s.CodecName}, + width: width, + height: height, + framerate: framerate, + }) + } + } + return &r, nil } diff --git a/internal/media/processingmedia.go b/internal/media/processingmedia.go index 3da036ac7..5d1d47b97 100644 --- a/internal/media/processingmedia.go +++ b/internal/media/processingmedia.go @@ -223,7 +223,6 @@ func (p *ProcessingMedia) store(ctx context.Context) error { width, height, aspect, - result.rotation, ) p.media.FileMeta.Small.Width = thumbWidth p.media.FileMeta.Small.Height = thumbHeight diff --git a/internal/media/util.go b/internal/media/util.go index dd445844d..7e84b4cdc 100644 --- a/internal/media/util.go +++ b/internal/media/util.go @@ -35,15 +35,13 @@ import ( "github.com/disintegration/imaging" ) -// thumbSize returns the dimensions to use for an input -// image of given width / height, for its outgoing thumbnail. -// This attempts to maintains the original image aspect ratio. -func thumbSize(width, height int, aspect float32, rotation int) (int, int) { - const ( - maxThumbWidth = 512 - maxThumbHeight = 512 - ) - +// displayDimensions takes account of the +// given rotation data to return width and +// height values as the image will be displayed. +func displayDimensions( + width, height int, + rotation int, +) (int, int) { // If image is rotated by // any odd multiples of 90, // flip width / height to @@ -51,9 +49,20 @@ func thumbSize(width, height int, aspect float32, rotation int) (int, int) { switch rotation { case -90, 90, -270, 270: width, height = height, width - aspect = 1 / aspect } + return width, height +} + +// thumbSize returns the dimensions to use for an input +// image of given width / height, for its outgoing thumbnail. +// This attempts to maintains the original image aspect ratio. +func thumbSize(width, height int, aspect float32) (int, int) { + const ( + maxThumbWidth = 512 + maxThumbHeight = 512 + ) + switch { // Simplest case, within bounds! case width < maxThumbWidth &&