Getting started with image processing in Ruby on Rails, rubyrails

Source: Internet
Author: User
Tags imagemagick image optimizer

Getting started with image processing in Ruby on Rails, rubyrails

Images can be said to be a vital part of any application. From social networks to a simple Bug tracker, images play an important role. However, managing images is not an easy task. It takes a lot of time and effort to plan images in advance.

This article demonstrates how to achieve this in Rail. How to process your images and create multiple versions in the background? How to Improve page performance by compressing images without compromising image quality? Let's hear this article.
Getting started

This tutorial is run on Rails 4.2 and presents the view through the MongoDb database and HAML. However, the snippets shown in this article should be compatible with any Rails version (despite some configuration differences ).

Stage Arrangement

ImageMagick is a powerful, stable, and open-source toolkit. you can install it on your computer through package management.

On Ubuntu:

sudo apt-get -y install imagemagick
sudo apt-get -y install libmagic-dev
sudo apt-get -y install libmagickwand-dev

On Mac OS X, homemade programs are recommended:

brew install imagemagick

Now we need a Ruby adapter connected to the local ImageMagick library. You can use MiniMagick because it is lightweight:

# Gemfile
 
gem 'mini_magick'

MiniMagick Features

Before the official start, let us first understand some of the features of MiniMagick to avoid unnecessary errors.

Open the Rails console (Rails c) and run the following code:

# 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

Let's adjust it to fit our iPad:

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

Where are the changed files stored?

image.path # temp path

There is a danger that manipulating images stored to a temporary path will disappear. So to put it on the disk, a simple call writing method is as follows:

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

Convert image

Perhaps one of your most common tasks is to convert images to different formats. MiniMagick can simplify this process:

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

You can also put multiple operations in the same module:

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

So far, let's take a look at how to link the above with our Rails application.
upload files

Carrierwave simplifies uploading files in Ruby, and it also interacts well with MiniMagick.

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

Note: If you are on ActiveRecord or DataMapper, the configuration will be slightly different. The official Carrierwave documentation describes the correct method, click here to enter.

Obtain:

bundle install

Create the first upload:

# 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

This code is self-explanatory, storage: file instructs the server to store the image on the local server, and store_dir specifies the location.

Since files are transmitted over the Internet, incoming files are always filtered:

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

Put this upload into our image model:

# 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

Edit image_uploader.rb to process the uploaded image:

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

Try to create a new image from the Rails console:

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

Uploaded images are available under store_dir. However, the uploaded image is processed immediately and is overwritten by the 200 × 200 image. We do not have a copy of the original document for future editing. So to avoid this, we need to create multiple versions of the file.

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

Shown below are two versions of the previous code, check the version created by Carrierwave:

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

Did you notice that these images were generated instantly? This means that the image conversion happens in the same thread, and execution is blocked until it completes. In production applications, creating multiple versions of an image in the same thread is undesirable. Instead, we should deal with this situation conditionally.

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

This way, when we create a new image, a copy will not be generated. We can manually trigger when needed, run the following code:

img.media.is_live = true
img.save
img.media.recreate_versions!: cover

This code also runs in the foreground and is a blocking operation, but at least it can be postponed to the last minute. We can run further in the background through Resque:

# 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

Then line up:

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

Performance improvement

The images are heavy and tend to slow down the website. One way to reduce page load is to compress these images. Carrierwave image optimizer can help us compress images quickly.

Add the following paragraph to the Gemfile:

gem 'carrierwave-imageoptimizer'

Then edit image_uploader:

# app / uploaders / image_uploader.rd
 
# .....
 
include CarrierWave :: ImageOptimizer
process: optimize
process: quality => 100
# ....

Such compression will not cause visual loss.

The image processing is a huge vertical, and we almost only touch the surface. We can build a lot of cool things. If you are interested in this article, please share your thoughts in the comments.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

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.