diff --git a/Gemfile b/Gemfile index bbe9fcad7..73c42ad39 100644 --- a/Gemfile +++ b/Gemfile @@ -48,9 +48,6 @@ gem 'activerecord-hierarchical_query' gem 'pundit' gem 'mail' -# needed for looser jpeg header compat -gem 'ruby-imagespec', :require => "image_spec", :git => "https://github.com/r888888888/ruby-imagespec.git", :branch => "exif-fixes" - group :production, :staging do gem 'unicorn', :platforms => :ruby gem 'capistrano3-unicorn' diff --git a/Gemfile.lock b/Gemfile.lock index 9b68a84de..f69c96262 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -5,13 +5,6 @@ GIT dtext_rb (1.10.5) nokogiri (~> 1.8) -GIT - remote: https://github.com/r888888888/ruby-imagespec.git - revision: 2dab9811f4abb4fbaeea66feb42e388ba545b2d8 - branch: exif-fixes - specs: - ruby-imagespec (0.3.1) - GEM remote: https://rubygems.org/ specs: @@ -456,7 +449,6 @@ DEPENDENCIES request_store responders retriable - ruby-imagespec! ruby-vips rubyzip sanitize diff --git a/app/logical/media_file/flash.rb b/app/logical/media_file/flash.rb index d7f8dc024..696d68dbe 100644 --- a/app/logical/media_file/flash.rb +++ b/app/logical/media_file/flash.rb @@ -1,6 +1,57 @@ +# Adapted from https://github.com/dim/ruby-imagespec/blob/f2f3ce8bb5b1b411f8658e66a891a095261d94c0/lib/image_spec/parser/swf.rb +# License: https://github.com/dim/ruby-imagespec/blob/master/LICENSE + class MediaFile::Flash < MediaFile::Image def dimensions - image_size = ImageSpec.new(file.path) - [image_size.width, image_size.height] + # Read the entire stream into memory because the + # dimensions aren't stored in a standard location + contents = file.read.force_encoding("ASCII-8BIT") + + # Our 'signature' is the first 3 bytes + # Either FWS or CWS. CWS indicates compression + signature = contents[0..2] + + # SWF version + version = contents[3].unpack('C').join.to_i + + # Determine the length of the uncompressed stream + length = contents[4..7].unpack('V').join.to_i + + # If we do, in fact, have compression + if signature == 'CWS' + # Decompress the body of the SWF + body = Zlib::Inflate.inflate( contents[8..length] ) + + # And reconstruct the stream contents to the first 8 bytes (header) + # Plus our decompressed body + contents = contents[0..7] + body + end + + # Determine the nbits of our dimensions rectangle + nbits = contents.unpack('C'*contents.length)[8] >> 3 + + # Determine how many bits long this entire RECT structure is + rectbits = 5 + nbits * 4 # 5 bits for nbits, as well as nbits * number of fields (4) + + # Determine how many bytes rectbits composes (ceil(rectbits/8)) + rectbytes = (rectbits.to_f / 8).ceil + + # Unpack the RECT structure from the stream in little-endian bit order, then join it into a string + rect = contents[8..(8 + rectbytes)].unpack("#{'B8' * rectbytes}").join + + # Read in nbits incremenets starting from 5 + dimensions = Array.new + 4.times do |n| + s = 5 + (n * nbits) # Calculate our start index + e = s + (nbits - 1) # Calculate our end index + dimensions[n] = rect[s..e].to_i(2) # Read that range (binary) and convert it to an integer + end + + # The values we have here are in "twips" + # 20 twips to a pixel (that's why SWFs are fuzzy sometimes!) + width = (dimensions[1] - dimensions[0]) / 20 + height = (dimensions[3] - dimensions[2]) / 20 + + [width, height] end end diff --git a/app/logical/media_file/image.rb b/app/logical/media_file/image.rb index e266f2577..b18608d91 100644 --- a/app/logical/media_file/image.rb +++ b/app/logical/media_file/image.rb @@ -1,6 +1,9 @@ class MediaFile::Image < MediaFile def dimensions - image_size = ImageSpec.new(file.path) - [image_size.width, image_size.height] + image.size + end + + def image + @image ||= Vips::Image.new_from_file(file.path) end end