我想转换用户在webp
上传图片以获取网站效果。我知道webp
现在只支持两种浏览器,Google Chrome
和Opera
。
我正在使用carrierwave
将图片上传到s3
。
找不到任何支持将图片转换为webp
中的carrierwave
。
image-magick
有图书馆libwebp
,可以将图片转换为webp
。
铁轨中是否有任何宝石?
如何将图片转换为carrierwave
并保存。
<{1}}以外的解决方案也有效。
答案 0 :(得分:0)
我有类似的任务,但是没有上传到S3。 我用webp-ffi gem编写自定义转换器。
这是对我有帮助的解决方案。
首先,您需要安装requirements gem的README文件中指定的webp-ffi。
之后,将webp-ffi宝石添加到您的项目中:
gem 'webp-ffi'
如果不需要存储原始图像,则只需将自定义方法添加到您的上传器中,然后使用CarrierWave的处理方法进行调用。这是我将图片转换为webp格式的技巧:
class MyImageUploader < CarrierWave::Uploader::Base
storage :file
process convert_to_webp: [{ quality: 80, method: 5 }]
def store_dir
"uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
end
private
def convert_to_webp(options = {})
# Build path for new file
webp_path = "#{path}.webp"
# Encode (convert) image to webp format with passed options
WebP.encode(path, webp_path, options)
# HACK: Changing of this two instance variables is the only way
# I found to make CarrierWave save new file that was created
# by encoding original image.
@filename = webp_path.split('/').pop
@file = CarrierWave::SanitizedFile.new(
tempfile: webp_path,
filename: webp_path,
content_type: 'image/webp'
)
end
end
您可以将此方法移至项目中的某个模块(确保正确autoload)。例如,我将这段代码放在app/services/web_p_converter.rb
中:
module WebPConverter
def convert_to_webp(options = {})
webp_path = "#{path}.webp"
WebP.encode(path, webp_path, options)
@filename = webp_path.split('/').pop
@file = CarrierWave::SanitizedFile.new(
tempfile: webp_path,
filename: webp_path,
content_type: 'image/webp'
)
end
end
现在,我可以在需要进行webp转换的每个上传器中包含此模块:
class MyImageUploader < CarrierWave::Uploader::Base
include WebPConverter
storage :file
process convert_to_webp: [{ quality: 80, method: 5 }]
def store_dir
"uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
end
end
但是,如果您需要存储文件的原始版本并在上载器中创建版本,则需要使用此技巧:
class MyImageUploader < CarrierWave::Uploader::Base
include WebPConverter
storage :file
version :webp do
process convert_to_webp: [{ quality: 80, method: 5 }]
def full_filename(file)
return "#{version_name}_#{filename}" if filename.split('.').last == 'webp'
"#{version_name}_#{file}.webp"
end
end
def store_dir
"uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
end
end
之所以必须这样做,是因为CarrierWave使用原始图像名称来构建其他版本的路径。
您还可以将逻辑从#full_filename移到方法中。例如,我将构建完整文件名的逻辑移到了WebPConverter模块中,因此看起来像这样:
module WebPConverter
# ...
def build_webp_full_filename(filename, version_name)
return "#{version_name}_#{filename}" if filename.split('.').last == 'webp'
"#{version_name}_#{filename}.webp"
end
end
从现在开始,我可以将其用于需要转换为webp的版本:
class MyImageUploader < CarrierWave::Uploader::Base
include WebPConverter
storage :file
version :webp do
process convert_to_webp: [{ quality: 80, method: 5 }]
def full_filename(file)
build_webp_full_filename(file, version_name)
end
end
def store_dir
"uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
end
end
我以示例使用Checkout carrierwave-webp宝石来创建此问题的解决方案(出于某种原因,该宝石对我不起作用)。
还要结帐我为演示有效解决方案而制作的simple app。
答案 1 :(得分:0)
module WebPConverter
private
def build_webp_full_filename(filename, version_name)
return "#{version_name}_#{filename}" if filename.split('.').last == 'webp'
"#{version_name}_#{filename}.webp"
end
end
并在ImageUploader中
class ImageUploader < CarrierWave::Uploader::Base
include CarrierWave::MiniMagick
include CarrierWave::WebP::Converter
include WebPConverter
storage :file
def store_dir
"uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
end
version :thumb do
process resize_to_fit: [50, 50]
end
version :img_quality do
process resize_to_fit: [600, 600]
process quality: 60
end
version :webp do
process convert_to_webp: [{ quality: 60, method: 5 }]
process resize_to_fit: [600, 600]
def full_filename(file)
build_webp_full_filename(file, version_name)
end
end
def extension_whitelist
%w[jpg jpeg gif png]
end
end
,并根据浏览器提供不同的格式 宝石“浏览器”
观看次数:
<%= image_tag set_browser(deals_first(@category).brand.logo) %>
助手
def set_browser(object)
browser.chrome? || browser.opera? || browser.platform.android? ?
object.webp.url : object.quality.url
end