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.
This commit is contained in:
evazion
2022-10-31 03:23:02 -05:00
parent e6ebc54b6c
commit 2f2c73eebb
4 changed files with 15 additions and 0 deletions

View File

@@ -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

View File

@@ -10,6 +10,8 @@ class MediaFile::Image < MediaFile
def dimensions
image.size
rescue Vips::Error
[metadata.width, metadata.height]
rescue
[0, 0]
end

View File

@@ -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

View File

@@ -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)