Convert non-web image (e.g. PSD) variants to PNG

This commit is contained in:
George Claghorn 2017-12-18 07:47:42 -05:00
parent daf15f58b9
commit 95117a2ce2
3 changed files with 53 additions and 12 deletions

View File

@ -35,6 +35,8 @@
#
# avatar.variant(resize: "100x100", monochrome: true, flip: "-90")
class ActiveStorage::Variant
WEB_IMAGE_CONTENT_TYPES = %w( image/png image/jpeg image/jpg image/gif )
attr_reader :blob, :variation
delegate :service, to: :blob
@ -62,7 +64,7 @@ class ActiveStorage::Variant
# for a variant that points to the ActiveStorage::VariantsController, which in turn will use this +service_call+ method
# for its redirection.
def service_url(expires_in: service.url_expires_in, disposition: :inline)
service.url key, expires_in: expires_in, disposition: disposition, filename: blob.filename, content_type: blob.content_type
service.url key, expires_in: expires_in, disposition: disposition, filename: filename, content_type: content_type
end
# Returns the receiving variant. Allows ActiveStorage::Variant and ActiveStorage::Preview instances to be used interchangeably.
@ -76,11 +78,40 @@ class ActiveStorage::Variant
end
def process
service.upload key, transform(service.download(blob.key))
service.upload key, transform(blob.download)
end
def filename
if WEB_IMAGE_CONTENT_TYPES.include?(blob.content_type)
blob.filename
else
ActiveStorage::Filename.new("#{blob.filename.base}.png")
end
end
def content_type
blob.content_type.presence_in(WEB_IMAGE_CONTENT_TYPES) || "image/png"
end
def transform(io)
read_image_from(io) do |image|
mogrify image
format image
end
end
def read_image_from(io, &block)
require "mini_magick"
File.open MiniMagick::Image.read(io).tap { |image| variation.transform(image) }.path
File.open MiniMagick::Image.read(io).tap(&block).path
end
def mogrify(image)
variation.transform(image)
end
def format(image)
image.format("PNG") unless WEB_IMAGE_CONTENT_TYPES.include?(blob.content_type)
end
end

Binary file not shown.

View File

@ -4,12 +4,9 @@ require "test_helper"
require "database/setup"
class ActiveStorage::VariantTest < ActiveSupport::TestCase
setup do
@blob = create_file_blob filename: "racecar.jpg"
end
test "resized variation" do
variant = @blob.variant(resize: "100x100").processed
test "resized variation of JPEG blob" do
blob = create_file_blob(filename: "racecar.jpg")
variant = blob.variant(resize: "100x100").processed
assert_match(/racecar\.jpg/, variant.service_url)
image = read_image(variant)
@ -17,8 +14,9 @@ class ActiveStorage::VariantTest < ActiveSupport::TestCase
assert_equal 67, image.height
end
test "resized and monochrome variation" do
variant = @blob.variant(resize: "100x100", monochrome: true).processed
test "resized and monochrome variation of JPEG blob" do
blob = create_file_blob(filename: "racecar.jpg")
variant = blob.variant(resize: "100x100", monochrome: true).processed
assert_match(/racecar\.jpg/, variant.service_url)
image = read_image(variant)
@ -27,6 +25,17 @@ class ActiveStorage::VariantTest < ActiveSupport::TestCase
assert_match(/Gray/, image.colorspace)
end
test "resized variation of PSD blob" do
blob = create_file_blob(filename: "icon.psd", content_type: "image/vnd.adobe.photoshop")
variant = blob.variant(resize: "20x20").processed
assert_match(/icon\.png/, variant.service_url)
image = read_image(variant)
assert_equal "PNG", image.type
assert_equal 20, image.width
assert_equal 20, image.height
end
test "variation of invariable blob" do
assert_raises ActiveStorage::Blob::InvariableError do
create_file_blob(filename: "report.pdf", content_type: "application/pdf").variant(resize: "100x100")
@ -34,7 +43,8 @@ class ActiveStorage::VariantTest < ActiveSupport::TestCase
end
test "service_url doesn't grow in length despite long variant options" do
variant = @blob.variant(font: "a" * 10_000).processed
blob = create_file_blob(filename: "racecar.jpg")
variant = blob.variant(font: "a" * 10_000).processed
assert_operator variant.service_url.length, :<, 500
end
end