diff --git a/lib/upload_creator.rb b/lib/upload_creator.rb index d2708108530..55f690c635e 100644 --- a/lib/upload_creator.rb +++ b/lib/upload_creator.rb @@ -72,8 +72,10 @@ class UploadCreator extract_image_info! return @upload if @upload.errors.present? - if @image_info.type.to_s == "svg" + if @image_info.type == :svg clean_svg! + elsif @image_info.type == :ico + convert_favicon_to_png! elsif !Rails.env.test? || @opts[:force_optimize] convert_to_jpeg! if convert_png_to_jpeg? || should_alter_quality? fix_orientation! if should_fix_orientation? @@ -261,6 +263,33 @@ class UploadCreator MIN_CONVERT_TO_JPEG_BYTES_SAVED = 75_000 MIN_CONVERT_TO_JPEG_SAVING_RATIO = 0.70 + def convert_favicon_to_png! + png_tempfile = Tempfile.new(["image", ".png"]) + + from = @file.path + to = png_tempfile.path + + OptimizedImage.ensure_safe_paths!(from, to) + + from = OptimizedImage.prepend_decoder!(from, nil, filename: "image.#{@image_info.type}") + to = OptimizedImage.prepend_decoder!(to) + + from = "#{from}[-1]" # We only want the last(largest) image of the .ico file + + opts = { flatten: false } # Preserve transparency + + begin + execute_convert(from, to, opts) + rescue + # retry with debugging enabled + execute_convert(from, to, opts.merge(debug: true)) + end + + @file.respond_to?(:close!) ? @file.close! : @file.close + @file = png_tempfile + extract_image_info! + end + def convert_to_jpeg! return if @opts[:for_site_setting] return if filesize < MIN_CONVERT_TO_JPEG_BYTES_SAVED @@ -331,8 +360,8 @@ class UploadCreator "-auto-orient", "-background", "white", "-interlace", "none", - "-flatten" ] + command << "-flatten" unless opts[:flatten] == false command << "-debug" << "all" if opts[:debug] command << "-quality" << opts[:quality].to_s if opts[:quality] command << to diff --git a/spec/lib/upload_creator_spec.rb b/spec/lib/upload_creator_spec.rb index 2be20fe13ae..bf7899d75ef 100644 --- a/spec/lib/upload_creator_spec.rb +++ b/spec/lib/upload_creator_spec.rb @@ -547,6 +547,23 @@ RSpec.describe UploadCreator do end end + describe '#convert_favicon_to_png!' do + let(:filename) { "smallest.ico" } + let(:file) { file_from_fixtures(filename, "images") } + + before do + SiteSetting.authorized_extensions = 'png|jpg|ico' + end + + it 'converts to png' do + upload = UploadCreator.new(file, filename).create_for(user.id) + + expect(upload.persisted?).to eq(true) + expect(upload.extension).to eq('png') + end + + end + describe '#clean_svg!' do let(:b64) do Base64.encode64('')