Ruby on Rails下的影像處理入門教程_ruby專題

來源:互聯網
上載者:User

映像可以說是任何應用至關重要的一部分。從社交網路到一個簡單的Bug追蹤器,映像都扮演著重要的角色。然而管理映像並不是一件容易的事情,需要提前耗費大量的時間精力去計劃。

本文示範了如何在Rail中實現這一目標。如何處理你的映像以及在後台建立多個版本?如何通過壓縮映像又不損映像品質,以此來提高頁面效能?這些且聽本文一一道來。
入門

本文教程是運行於Rails 4.2,通過MongoDb資料庫和HAML呈現視圖。不過本文所展示的片段應該相容任何Rails版本(儘管有些配置差異)。

布置舞台

ImageMagick是一套功能強大、穩定而且開源的工具集和開發包,你可以通過包管理把它安裝在你的電腦上。

Ubuntu上:

sudo apt-get -y install imagemagicksudo apt-get -y install libmagic-devsudo apt-get -y install libmagickwand-dev

Mac OS X上,建議使用自製程式:

brew install imagemagick

現在我們需要一個串連到本地ImageMagick庫的Ruby適配器。你可以使用MiniMagick,因為它是輕量級的:

# Gemfile gem 'mini_magick'

MiniMagick的特性

在正式開始之前,讓我們先瞭解一下某些MiniMagick的特性,以避免不必要的錯誤。

開啟Rails控制台(Rails c)並運行以下代碼:

# Open an image from a website image = MiniMagick::Image.open("yun_qi_img/85.jpg") # Get the Image's widthimage.width # 4928 # Get the image's heightimage.height #3264

讓我們調整一下以適應我們的iPad:

image.resize "2048x1536" # Now get the image's new width and height p "Width is => #{image.width} and height is => #{image.height}"

更改後的檔案儲存體在哪呢?

image.path # temp path

操縱映像儲存到一個臨時的路徑有消失的危險。所以要把它放到磁碟中,一個簡單的調用編寫方法如下:

image.write "public/uploads/test.jpg"

轉換映像

或許你最常見的工作之一就是將映像轉換成不同的格式。MiniMagick可以簡化這一過程:

image.format "png"image.write "public/uploads/test.png"

你還可以將多個操作放在同一模組中:

image.combine_options do |i| i.resize "2048x1536" i.flip i.rotate "-45" i.blur "0x15"endimage.write "public/uploads/blur.png" ![Some weird result](blur.png)

至此,讓我們來看看如何將以上的這些與我們的Rails應用聯絡到一起。
上傳檔案

Carrierwave簡化了在Ruby中上傳檔案,同時它與MiniMagick互動的也很好。

# Gemfile gem 'carrierwave'gem 'carrierwave-mongoid', :require => 'carrierwave/mongoid'

注意:如果你是在ActiveRecord或DataMapper上,配置會稍微不同。Carrierwave官方文檔介紹了正確的方法,點此進入。

擷取:

bundle install

建立第一個上傳:

#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" endend

這段代碼是自說明,storage :file指示伺服器將映像儲存在本機伺服器上,store_dir指定位置。

自從檔案通過互連網傳送,總會過濾傳入的檔案:

# 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_filenameend

編輯image_uploader.rb來處理上傳的映像:

# app/uploaders/image_uploader.rb #.....process :resize_to_fill => [200, 200]process :convert => 'png'#.....

嘗試從Rails控制台建立一個新的映像:

media = File.open("/Users/test/Desktop/image/jpg")img = Image.new(:media => media)img.save

上傳映像在store_dir下是可用的。然而上傳的映像是立即被處理的,並被200×200的映像覆蓋。我們沒有原始檔案的副本留作以後編輯。所以為避免這種情況,我們需要建立多個版本的檔案。

# 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 #.....

下面顯示的是上段代碼建立兩個版本,檢查版本由Carrierwave建立:

img.media.versions[:thumb] # returns the thumb image instanceimg.media.versions[:cover] # returns the cover image instance

你注意到這些映像是瞬間產生的嗎?這意味著映像轉換髮生在同一線程中,並且執行是被阻塞的,直到完成為止。在生產應用中,在同一線程裡建立一個映像的多個版本是不受歡迎的。相反,我們應該有條件的處理這種情況。

# 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_liveend def is_live=(value) @is_live = valueend#....

這樣,當我們建立一個新的映像時,副本將不會產生。我們可以在需要的時候手動去觸發,運行如下代碼:

img.media.is_live = trueimg.saveimg.media.recreate_versions! :cover

這代碼也是運行於前台,是一個阻塞操作,但至少可以儘可能的延遲到最後一刻。我們可以通過Resque在後台進一步的運行:

# lib/resque/image_queue.rbclass 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 endend

然後,列隊:

Resque.enqueue(ImageQueue, img.id.to_s)

效能提升

映像是厚重的,往往會減慢網站。減少頁面負擔的一種方法是壓縮這些映像。Carrierwave映像最佳化器可以協助我們飛速的壓縮映像。

將下面這段添加到Gemfile:

gem 'carrierwave-imageoptimizer'

然後編輯image_uploader:

# app/uploaders/image_uploader.rd #..... include CarrierWave::ImageOptimizerprocess :optimizeprocess :quality => 100#....

如此壓縮不會有視覺喪失。

影像處理是一個巨大的垂直,我們幾乎只觸及表面。我們可以建立很多很酷的東西。如果您對這篇文章感興趣,請在評論中分享您的想法。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.