Created
July 11, 2012 08:28
-
-
Save jimhj/3089015 to your computer and use it in GitHub Desktop.
Use Mini_Magick to crop animated gif images.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# coding: utf-8 | |
module SimpleUpload | |
class Base | |
class << self | |
def max_size | |
10485760 #(10M) | |
end | |
def extension_white_list | |
%w(jpg jpeg png gif) | |
end | |
def customizable_storage? | |
AppConfig.get(:enable_image_storage_parse) | |
end | |
def location_to_store | |
return nil unless customizable_storage? | |
AppConfig.get(:location_to_store_uploaded_assets) | |
end | |
# Create a dir like '/23/33'. | |
def rand_dir | |
File.join('%02d' % rand(99), '%02d' % rand(99)) | |
end | |
def filename | |
Digest::MD5.hexdigest([Time.now.to_i.to_s, rand.to_s].join('-')) | |
end | |
def white_background_img | |
File.join(Rails.root, 'public', 'white_background.jpg') | |
end | |
# Uncomment this to add watermark | |
# def watermark | |
# end | |
def versions | |
{ | |
:l => '600x900>', | |
:m => '200x300>', | |
:c => '80x80', | |
:s => '50x50' | |
} | |
end | |
end | |
end #Base End | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'simple_upload' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# coding: utf-8 | |
require 'mini_magick' | |
require 'open-uri' | |
# TODO: Crop image. | |
module SimpleUpload | |
class Upload < Base | |
attr_accessor :status, :dfs_path, :errors, :image | |
def initialize(file, product_dir) | |
@status, @dfs_path, @errors = false, nil, [] | |
@image = nil | |
if file.nil? | |
@errors << '请选择一张图片上传' | |
else | |
if file.is_a? ActionDispatch::Http::UploadedFile | |
file_path = file.tempfile.path | |
elsif file.is_a? Tempfile | |
file_path = file.path | |
elsif file.is_a? String | |
# TODO: refine upload a image from a remote url. | |
if File.exist?(file) || file.start_with?('http://') | |
file_path = file | |
end | |
# file_path = file | |
# file_path = 'http://' + file if !file.start_with?('http://') | |
end | |
begin | |
@image = MiniMagick::Image.open(file_path) | |
@errors << '不支持这种格式的图片' if !self.class.extension_white_list.include?(@image[:format].downcase) | |
@errors << '图片超出了最大限制' if @image[:size].to_i > self.class.max_size | |
rescue => e | |
@errors << '不支持的文件' | |
end | |
end | |
end | |
class << self | |
def extension_white_list; super end | |
def versions; super end | |
def max_size; super end | |
## | |
# Uploads the Image and returns an object. | |
# Paramters: | |
# [file (Tempfile or A remote url)] | |
# [product_dir (string)] | |
# | |
# Usage: | |
# upload = SimpleUpload::Upload.process(file_or_url, 'p') | |
# if upload.status | |
# dfs = upload.dfs_path | |
# else | |
# errors = upload.errors | |
# end | |
## | |
def process(file, product_dir = 'p') | |
upload = self.new(file, product_dir) | |
if upload.errors.length == 0 | |
@product_dir, @rand_dir = product_dir, rand_dir | |
filename, extension = self.filename, upload.image[:format].downcase | |
orig_target_dir = File.join(store_dir, "o_#{filename}.#{extension}") | |
begin | |
FileUtils.mkdir_p(store_dir) | |
upload.image.write(orig_target_dir) | |
self.gen_thumbnails(orig_target_dir, "#{filename}.#{extension}") | |
upload.status = true | |
upload.dfs_path = [filename, extension, 0, 0, @product_dir, 0, 0, @rand_dir.split('/')].join('|') | |
rescue => e | |
p e.inspect | |
upload.errors = ['上传中出错了,请重试'] | |
end | |
end | |
return upload | |
end | |
# TODO: Crop image from remote url. | |
# Dfs Path Rule: 481324679f9b4aa85b412a59d1da3127|jpeg|0|0|p|0|0|52|05 | |
def crop(file, crop_position, product_dir = 'a') | |
file_path = get_absolute_dir(file) | |
return nil unless File.exist?(file_path) | |
return nil if !crop_position.is_a?(Array) && crop_position.length == 4 | |
x, y, w, h = crop_position | |
image = MiniMagick::Image.open(file_path) | |
if image.mime_type == 'image/gif' | |
image.crop("#{w}x#{h}+#{x}+#{y}!") | |
image.coalesce(file_path, file_path) | |
else | |
image.crop("#{w}x#{h}+#{x}+#{y}") | |
end | |
image.write(file_path) | |
upload = self.process(file_path, product_dir) | |
end | |
def composite_white_background(dfs_path, product_dir = 'a') | |
file_path = get_absolute_dir(dfs_path) | |
image = MiniMagick::Image.open(file_path) | |
if image.mime_type == 'image/gif' | |
image.run_command("convert #{white_background_img} null: #{file_path} -gravity Center -layers Composite #{file_path}") | |
else | |
composite_img = MiniMagick::Image.open(white_background_img).clone | |
composite_img.composite(image) do |img| | |
img.gravity "Center" | |
end.write(file_path) | |
end | |
self.process(file_path, product_dir) | |
end | |
def resize_to_limit(image, size) | |
size << '>' unless size.end_with?('>') | |
image.resize size | |
end | |
def resize_to_fill(image, size) | |
cols, rows = image[:dimensions] | |
width, height = size.split('x').map{ |length| length.to_i } | |
image.combine_options do |cmd| | |
if width != cols || height != rows | |
scale = [width / cols.to_f, height / rows.to_f].max | |
cols = (scale * (cols + 0.5)).round | |
rows = (scale * (rows + 0.5)).round | |
cmd.resize "#{cols}x#{rows}" | |
end | |
cmd.gravity 'Center' | |
cmd.background "rgba(255,255,255,0.0)" | |
cmd.extent "#{width}x#{height}" if cols != width || rows != height | |
end | |
end | |
# def resize_crop(image, size) | |
# p 111111 | |
# w, h = image[:width], image[:height] | |
# shaved_off = ((w - h) / 2).round | |
# p w, h | |
# x = image.shave "#{shaved_off}x0" | |
# p x | |
# end | |
# Make thumbnails from original image or a remore url. | |
def gen_thumbnails(original_file, fullfilename) | |
orig_img = MiniMagick::Image.open(original_file) | |
self.versions.each do |style, size| | |
case style | |
when :l, :m | |
self.resize_to_limit(orig_img, size) | |
else | |
self.resize_to_fill(orig_img, size) | |
end | |
orig_img.resize(size) | |
orig_img.write File.join(store_dir, "#{style}_#{fullfilename}") | |
end | |
end | |
private | |
def get_absolute_dir(dfs_path, style = 'l') | |
dir_arr = (dfs_path || '').split('|') | |
return nil if dir_arr.length == 0 | |
rand_dir, dir = File.join(dir_arr[-2], dir_arr[-1]), dir_arr[4] | |
root_dir = customizable_storage? ? location_to_store : File.join(Rails.root, 'public') | |
file_path = File.join(root_dir, dir, rand_dir, "#{style}_#{dir_arr[0]}.#{dir_arr[1]}") | |
end | |
def store_dir | |
if customizable_storage? | |
File.join(location_to_store, @product_dir, @rand_dir) | |
else | |
File.join(Rails.root, 'public', @product_dir, @rand_dir) | |
end | |
end | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment