diff --git a/app/javascript/mastodon/features/compose/components/upload_button.js b/app/javascript/mastodon/features/compose/components/upload_button.js index d550019f41841ba3039fab9bd16fbcd76d2f5487..08da1306d92f26b04db8d1aa01e89c2b608b2661 100644 --- a/app/javascript/mastodon/features/compose/components/upload_button.js +++ b/app/javascript/mastodon/features/compose/components/upload_button.js @@ -10,7 +10,7 @@ const messages = defineMessages({ upload: { id: 'upload_button.label', defaultMessage: 'Add media ({formats})' }, }); -const SUPPORTED_FORMATS = 'JPEG, PNG, GIF, WebM, MP4, MOV, OGG, WAV, MP3, FLAC'; +const SUPPORTED_FORMATS = 'JPEG, PNG, GIF, WEBP, HEIF, HEIC, WebM, MP4, MOV, OGG, WAV, MP3, FLAC'; const makeMapStateToProps = () => { const mapStateToProps = state => ({ diff --git a/app/javascript/mastodon/utils/resize_image.js b/app/javascript/mastodon/utils/resize_image.js index 7196dc96b1e9b26ab3db09072188f294529e4249..b0f2fd565971d2e33949fe12fa63775e5d87e2a0 100644 --- a/app/javascript/mastodon/utils/resize_image.js +++ b/app/javascript/mastodon/utils/resize_image.js @@ -95,8 +95,10 @@ const resizeImage = (img, type = 'image/png') => new Promise((resolve, reject) = .catch(reject); }); +const WITHOUT_RESIZING_FORMATS = ['image/gif', 'image/heic', 'image/heif']; + export default inputFile => new Promise((resolve, reject) => { - if (!inputFile.type.match(/image.*/) || inputFile.type === 'image/gif') { + if (!inputFile.type.match(/image.*/) || WITHOUT_RESIZING_FORMATS.indexOf(inputFile.type) >= 0) { resolve(inputFile); return; } diff --git a/app/models/media_attachment.rb b/app/models/media_attachment.rb index 1fd0adfd02ba74976da02b9ddff224f8ac3aace8..6468d104d253c2837d8fe02c0dad140c53058f57 100644 --- a/app/models/media_attachment.rb +++ b/app/models/media_attachment.rb @@ -28,11 +28,12 @@ class MediaAttachment < ApplicationRecord MAX_DESCRIPTION_LENGTH = 1_500 - IMAGE_FILE_EXTENSIONS = %w(.jpg .jpeg .png .gif).freeze + IMAGE_FILE_EXTENSIONS = %w(.jpg .jpeg .png .gif .webp .heif .heic).freeze VIDEO_FILE_EXTENSIONS = %w(.webm .mp4 .m4v .mov).freeze AUDIO_FILE_EXTENSIONS = %w(.ogg .oga .mp3 .wav .flac .opus .aac .m4a .3gp .wma).freeze - IMAGE_MIME_TYPES = %w(image/jpeg image/png image/gif).freeze + IMAGE_MIME_TYPES = %w(image/jpeg image/png image/gif image/webp image/heif image/heic).freeze + IMAGE_CONVERTIBLE_MIME_TYPES = %w(image/webp image/heif image/heic).freeze VIDEO_MIME_TYPES = %w(video/webm video/mp4 video/quicktime video/ogg).freeze VIDEO_CONVERTIBLE_MIME_TYPES = %w(video/webm video/quicktime).freeze AUDIO_MIME_TYPES = %w(audio/wave audio/wav audio/x-wav audio/x-pn-wave audio/ogg audio/mpeg audio/mp3 audio/webm audio/flac audio/aac audio/m4a audio/x-m4a audio/mp4 audio/3gpp video/x-ms-asf).freeze @@ -240,6 +241,8 @@ class MediaAttachment < ApplicationRecord [:video_transcoder, :blurhash_transcoder, :type_corrector] elsif AUDIO_MIME_TYPES.include?(f.file_content_type) [:transcoder, :type_corrector] + elsif IMAGE_CONVERTIBLE_MIME_TYPES.include?(f.file_content_type) + [:img_converter, :lazy_thumbnail, :blurhash_transcoder, :type_corrector] else [:lazy_thumbnail, :blurhash_transcoder, :type_corrector] end diff --git a/lib/paperclip/img_converter.rb b/lib/paperclip/img_converter.rb new file mode 100644 index 0000000000000000000000000000000000000000..3f4e949359dd7b2565551713dfd1641527c699b1 --- /dev/null +++ b/lib/paperclip/img_converter.rb @@ -0,0 +1,34 @@ +# frozen_string_literal: true + +module Paperclip + class ImgConverter < Paperclip::Processor + def initialize(file, options = {}, attachment = nil) + super + + @current_format = File.extname(@file.path) + @basename = File.basename(@file.path, @current_format) + end + + def make + dst_format, dst_content_type = opaque? ? ['jpg', 'image/jpeg'] : ['png', 'image/png'] + dst_name = "#{@basename}.#{dst_format}" + + attachment.instance.file_file_name = dst_name + attachment.instance.file_content_type = dst_content_type + + options[:format] = dst_format + options[:content_type] = dst_content_type + + dst = Paperclip::TempfileFactory.new.generate(dst_name) + convert(':src :dst', src: File.expand_path(@file.path), dst: File.expand_path(dst.path)) + + dst + end + + private + + def opaque? + identify('-format "%[opaque]" :src', src: File.expand_path(@file.path)).strip.downcase == 'true' + end + end +end