From 2f2c73eebb80197c08964426c2beb54f842473d2 Mon Sep 17 00:00:00 2001 From: evazion Date: Mon, 31 Oct 2022 03:23:02 -0500 Subject: [PATCH] media assets: fix dimensions of corrupt GIFs. Fix certain corrupt GIFs returning dimensions of 0x0. This happened when the GIF was too corrupt for libvips to read. Fixed by using ExifTool to read the dimensions instead. Also add validations to ensure that it's not possible to have media assets with a width or height of 0. --- app/logical/exif_tool.rb | 8 ++++++++ app/logical/media_file/image.rb | 2 ++ app/models/media_asset.rb | 3 +++ test/unit/media_file_test.rb | 2 ++ 4 files changed, 15 insertions(+) diff --git a/app/logical/exif_tool.rb b/app/logical/exif_tool.rb index 115aac03d..5933798b4 100644 --- a/app/logical/exif_tool.rb +++ b/app/logical/exif_tool.rb @@ -120,6 +120,14 @@ class ExifTool metadata.has_key?("PNG:Dream") end + def width + metadata.find { |name, value| name.match?(/\A(File|PNG|GIF|RIFF|Flash|Track\d+):ImageWidth\z/) }&.second + end + + def height + metadata.find { |name, value| name.match?(/\A(File|PNG|GIF|RIFF|Flash|Track\d+):ImageHeight\z/) }&.second + end + # @see http://www.vurdalakov.net/misc/gif/netscape-looping-application-extension # @see https://wiki.mozilla.org/APNG_Specification#.60acTL.60:_The_Animation_Control_Chunk # @see https://danbooru.donmai.us/posts?tags=-exif:GIF:AnimationIterations=Infinite+animated_gif diff --git a/app/logical/media_file/image.rb b/app/logical/media_file/image.rb index 175d44deb..0eee1bea5 100644 --- a/app/logical/media_file/image.rb +++ b/app/logical/media_file/image.rb @@ -10,6 +10,8 @@ class MediaFile::Image < MediaFile def dimensions image.size rescue Vips::Error + [metadata.width, metadata.height] + rescue [0, 0] end diff --git a/app/models/media_asset.rb b/app/models/media_asset.rb index 94a3c26eb..58ef91212 100644 --- a/app/models/media_asset.rb +++ b/app/models/media_asset.rb @@ -45,6 +45,9 @@ class MediaAsset < ApplicationRecord validates :md5, uniqueness: { conditions: -> { where(status: [:processing, :active]) } }, if: :md5_changed? validates :file_ext, inclusion: { in: FILE_TYPES, message: "File is not an image or video" } validates :file_key, length: { is: FILE_KEY_LENGTH }, uniqueness: true, if: :file_key_changed? + validates :file_size, comparison: { greater_than: 0 }, if: :file_size_changed? + validates :image_width, comparison: { greater_than: 0 }, if: :image_width_changed? + validates :image_height, comparison: { greater_than: 0 }, if: :image_height_changed? before_create :initialize_file_key diff --git a/test/unit/media_file_test.rb b/test/unit/media_file_test.rb index fd0f9e324..105100d0a 100644 --- a/test/unit/media_file_test.rb +++ b/test/unit/media_file_test.rb @@ -467,6 +467,7 @@ class MediaFileTest < ActiveSupport::TestCase @metadata = @file.metadata assert_equal(true, @file.is_corrupt?) + assert_equal([475, 600], @file.dimensions) assert_equal("File format error", @metadata["ExifTool:Error"]) assert_equal("89a", @metadata["GIF:GIFVersion"]) assert_equal(9, @metadata.count) @@ -478,6 +479,7 @@ class MediaFileTest < ActiveSupport::TestCase assert_equal(true, @file.is_corrupt?) assert_equal(nil, @file.frame_count) + assert_equal([575, 800], @file.dimensions) assert_equal("File format error", @metadata["ExifTool:Error"]) assert_equal("89a", @metadata["GIF:GIFVersion"]) assert_equal(9, @metadata.count)