Ruby on Rails下的圖像處理入門教程
圖像可以說是任何應(yīng)用至關(guān)重要的一部分。從社交網(wǎng)絡(luò)到一個(gè)簡單的Bug追蹤器,圖像都扮演著重要的角色。然而管理圖像并不是一件容易的事情,需要提前耗費(fèi)大量的時(shí)間精力去計(jì)劃。
本文演示了如何在Rail中實(shí)現(xiàn)這一目標(biāo)。如何處理你的圖像以及在后臺(tái)創(chuàng)建多個(gè)版本?如何通過壓縮圖像又不損圖像質(zhì)量,以此來提高頁面性能?這些且聽本文一一道來。
入門
本文教程是運(yùn)行于Rails 4.2,通過MongoDb數(shù)據(jù)庫和HAML呈現(xiàn)視圖。不過本文所展示的片段應(yīng)該兼容任何Rails版本(盡管有些配置差異)。
布置舞臺(tái)
ImageMagick是一套功能強(qiáng)大、穩(wěn)定而且開源的工具集和開發(fā)包,你可以通過包管理把它安裝在你的電腦上。
Ubuntu上:
sudo apt-get -y install imagemagick sudo apt-get -y install libmagic-dev sudo apt-get -y install libmagickwand-dev
Mac OS X上,建議使用自制程序:
brew install imagemagick
現(xiàn)在我們需要一個(gè)連接到本地ImageMagick庫的Ruby適配器。你可以使用MiniMagick,因?yàn)樗禽p量級(jí)的:
# Gemfile gem 'mini_magick'
MiniMagick的特性
在正式開始之前,讓我們先了解一下某些MiniMagick的特性,以避免不必要的錯(cuò)誤。
打開Rails控制臺(tái)(Rails c)并運(yùn)行以下代碼:
# Open an image from a website image = MiniMagick::Image.open("https://s3.amazonaws.com/StartupStockPhotos/20140808_StartupStockPhotos/85.jpg") # Get the Image's width image.width # 4928 # Get the image's height image.height #3264
讓我們調(diào)整一下以適應(yīng)我們的iPad:
image.resize "2048x1536" # Now get the image's new width and height p "Width is => #{image.width} and height is => #{image.height}"
更改后的文件存儲(chǔ)在哪呢?
image.path # temp path
操縱圖像存儲(chǔ)到一個(gè)臨時(shí)的路徑有消失的危險(xiǎn)。所以要把它放到磁盤中,一個(gè)簡單的調(diào)用編寫方法如下:
image.write "public/uploads/test.jpg"
轉(zhuǎn)換圖像
或許你最常見的工作之一就是將圖像轉(zhuǎn)換成不同的格式。MiniMagick可以簡化這一過程:
image.format "png" image.write "public/uploads/test.png"
你還可以將多個(gè)操作放在同一模塊中:
image.combine_options do |i| i.resize "2048x1536" i.flip i.rotate "-45" i.blur "0x15" end image.write "public/uploads/blur.png" 
至此,讓我們來看看如何將以上的這些與我們的Rails應(yīng)用聯(lián)系到一起。
上傳文件
Carrierwave簡化了在Ruby中上傳文件,同時(shí)它與MiniMagick交互的也很好。
# Gemfile gem 'carrierwave' gem 'carrierwave-mongoid', :require => 'carrierwave/mongoid'
注意:如果你是在ActiveRecord或DataMapper上,配置會(huì)稍微不同。Carrierwave官方文檔介紹了正確的方法,點(diǎn)此進(jìn)入。
獲?。?/p>
bundle install
創(chuàng)建第一個(gè)上傳:
#app/uploaders/image_uploader.rb class ImageUploader < CarrierWave::Uploader::Base # Include RMagick or MiniMagick support: include CarrierWave::MiniMagick # Choose what kind of storage to use for this Uploader: storage :file # Override the directory where uploaded files will be stored. # This is a sensible default for uploaders that are meant to be mounted: def store_dir "uploads/images" end end
這段代碼是自說明,storage :file指示服務(wù)器將圖像存儲(chǔ)在本地服務(wù)器上,store_dir指定位置。
自從文件通過互聯(lián)網(wǎng)傳送,總會(huì)過濾傳入的文件:
# app/uploaders/image_uploader.rb ... # Add a white list of extensions which are allowed to be uploaded. # For images you might use something like this: def extension_white_list %w(jpg jpeg png gif) end ...
將這種上傳置入我們的圖像模型:
# app/models/image.rb class Image include Mongoid::Document include Mongoid::Timestamps include Mongoid::Paranoia include Mongoid::Attributes::Dynamic include Rails.application.routes.url_helpers mount_uploader :media, ImageUploader, mount_on: :media_filename end
編輯image_uploader.rb來處理上傳的圖像:
# app/uploaders/image_uploader.rb #..... process :resize_to_fill => [200, 200] process :convert => 'png' #.....
嘗試從Rails控制臺(tái)創(chuàng)建一個(gè)新的圖像:
media = File.open("/Users/test/Desktop/image/jpg") img = Image.new(:media => media) img.save
上傳圖像在store_dir下是可用的。然而上傳的圖像是立即被處理的,并被200×200的圖像覆蓋。我們沒有原始文件的副本留作以后編輯。所以為避免這種情況,我們需要?jiǎng)?chuàng)建多個(gè)版本的文件。
# app/uploaders/image_uploader.rb #..... version :thumb do process :resize_to_fit => [100, 100] process :convert => 'jpg' end version :cover do process :resize_to_fit => [240, 180] process :convert => 'jpg' end #.....
下面顯示的是上段代碼創(chuàng)建兩個(gè)版本,檢查版本由Carrierwave創(chuàng)建:
img.media.versions[:thumb] # returns the thumb image instance img.media.versions[:cover] # returns the cover image instance
你注意到這些圖像是瞬間生成的嗎?這意味著圖像轉(zhuǎn)換發(fā)生在同一線程中,并且執(zhí)行是被阻塞的,直到完成為止。在生產(chǎn)應(yīng)用中,在同一線程里創(chuàng)建一個(gè)圖像的多個(gè)版本是不受歡迎的。相反,我們應(yīng)該有條件的處理這種情況。
# app/uploaders/image_uploader/rb #.... version :cover, :if => :is_live? do process :resize_to_fit => [240, 180] process :convert => 'jpg' end def is_live?(img = nil) @is_live end def is_live=(value) @is_live = value end #....
這樣,當(dāng)我們創(chuàng)建一個(gè)新的圖像時(shí),副本將不會(huì)生成。我們可以在需要的時(shí)候手動(dòng)去觸發(fā),運(yùn)行如下代碼:
img.media.is_live = true img.save img.media.recreate_versions! :cover
這代碼也是運(yùn)行于前臺(tái),是一個(gè)阻塞操作,但至少可以盡可能的推遲到最后一刻。我們可以通過Resque在后臺(tái)進(jìn)一步的運(yùn)行:
# lib/resque/image_queue.rb class ImageQueue @queue = :image_queue def self.perform(image_id) image = Image.find image_id img.media.is_live= true img.save img.media.recreate_versions! :cover end end
然后,列隊(duì):
Resque.enqueue(ImageQueue, img.id.to_s)
性能提升
圖像是厚重的,往往會(huì)減慢網(wǎng)站。減少頁面負(fù)擔(dān)的一種方法是壓縮這些圖像。Carrierwave圖像優(yōu)化器可以幫助我們飛速的壓縮圖像。
將下面這段添加到Gemfile:
gem 'carrierwave-imageoptimizer'
然后編輯image_uploader:
# app/uploaders/image_uploader.rd #..... include CarrierWave::ImageOptimizer process :optimize process :quality => 100 #....
如此壓縮不會(huì)有視覺喪失。
圖像處理是一個(gè)巨大的垂直,我們幾乎只觸及表面。我們可以建立很多很酷的東西。如果您對(duì)這篇文章感興趣,請(qǐng)?jiān)谠u(píng)論中分享您的想法。
- 快速安裝Ruby on Rails的簡明指南
- win7安裝ruby on rails開發(fā)環(huán)境
- 在 Ubuntu 12.04 Server 上安裝部署 Ruby on Rails 應(yīng)用
- Windows下Ruby on Rails開發(fā)環(huán)境安裝配置圖文教程
- Ruby On Rails上手筆記(安裝使用全過程)
- CentOS7下搭建ruby on rails開發(fā)環(huán)境
- 幾個(gè)加速Ruby on Rails的編程技巧
- Ruby on rails安裝后去掉DL is deprecated,please use Fiddle警告信息的方法【測(cè)試可用】
相關(guān)文章
使用Ruby編寫腳本進(jìn)行系統(tǒng)管理的教程
這篇文章主要介紹了使用Ruby編寫腳本進(jìn)行系統(tǒng)管理的教程,本文來自于IBM官方網(wǎng)站技術(shù)文檔,需要的朋友可以參考下2015-04-04Ruby使用REXML庫來解析xml格式數(shù)據(jù)的方法
這篇文章主要介紹了Ruby使用REXML庫來解析xml格式數(shù)據(jù)的方法,文章最后提及了REXML庫的使用相關(guān)安全問題可以注意一下,需要的朋友可以參考下2016-04-04深入剖析Ruby設(shè)計(jì)模式編程中對(duì)命令模式的相關(guān)使用
這篇文章主要介紹了Ruby設(shè)計(jì)模式編程中對(duì)命令模式的相關(guān)使用,文中還講到了關(guān)于觀察者模式和命令模式的一些概念區(qū)別,需要的朋友可以參考下2016-04-04