Images can be said to be a critical part of any application. From social networks to a simple bug tracker, images play an important role. Managing images, however, is not an easy task and requires a lot of time and energy to plan ahead.
This article demonstrates how to achieve this goal in rail. How do you handle your images and create multiple versions in the background? How to improve the performance of the page by compressing the image without compromising the image quality? These are the one by one ways to listen to this article.
Entry
This tutorial is run in Rails 4.2, rendering views through the MongoDB database and Haml. However, the fragments shown in this article should be compatible with any rails version (albeit with some configuration differences).
Decorate the stage
ImageMagick is a powerful, stable, and open source Toolset and development Kit that you can install 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, it is recommended that you use a homemade program:
Now we need a Ruby adapter that connects to the local ImageMagick library. You can use Minimagick, because it is lightweight:
# gemfile
Gem ' Mini_magick '
Characteristics of Minimagick
Before we begin, let's take a look at some of the minimagick features 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 ("yun_qi_img/85.jpg")
# Get the image ' s width
ima Ge.width # 4928
# Get the image ' s height
image.height #3264
Let's tweak it to fit our ipad:
Image.resize "2048x1536" # now get the
image ' s new width and height
p ' width is => #{image.width} and ' => #{image.height} "
Where are the changed files stored?
Manipulating images stored to a temporary path has the danger of disappearing. So to put it on the disk, a simple call writing method is as follows:
Image.write "Public/uploads/test.jpg"
Converting images
Perhaps one of your most common jobs is to convert images into 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 let's take a look at how to relate these to our rails application.
Uploading Files
Carrierwave simplifies uploading files in Ruby, and it 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. Carrierwave Official documentation describes the correct approach and points to this entry.
Get:
Create 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:
St Orage:file
# Override The directory where uploaded files would be stored.
# This is a sensible default for uploaders so are meant to be mounted:
def store_dir
"Uploads/images"
end
end
This code is a storage:file that instructs the server to store the image on the local server, store_dir the specified location.
Since files are transmitted over the Internet, the incoming files will always be filtered:
# app/uploaders/image_uploader.rb ...
# ADD A white list of extensions which are allowed to be uploaded.
# for images your might use something like this:
def extension_white_list
%w (jpg jpeg png gif)
end
...
Placing this upload into our image model:
# APP/MODELS/IMAGE.RB
class image
include mongoid::D ocument
include Mongoid::timestamps
include Mongoid::P Aranoia
include mongoid::attributes::D ynamic
include Rails.application.routes.url_helpers
Mount_uploader:media, Imageuploader, mount_on:: Media_filename End
Edit the IMAGE_UPLOADER.RB to process the uploaded image:
# app/uploaders/image_uploader.rb
#
... Process:resize_to_fill => [MB]
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
The upload image is available under Store_dir. However, the uploaded image is immediately processed and overwritten by the 200x200 image. We do not have a copy of the original document left for later 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 => [MB]
process:convert => ' jpg ' End
version: Cover do
process:resize_to_fit => [the 180]
process:convert => ' jpg ' end
# ...
The following shows the previous code created two versions, and the check version is created by Carrierwave:
IMG.MEDIA.VERSIONS[:THUMB] # Returns the thumb image instance
Img.media.versions[:cover] # returns the cover image in Stance
Have you noticed that these images are generated instantaneously? This means that the image transformation occurs on the same thread, and execution is blocked until it is complete. In production applications, it is undesirable to create multiple versions of an image on the same line Chengri. On the contrary, we should deal with this situation conditionally.
# APP/UPLOADERS/IMAGE_UPLOADER/RB
# ....
Version:cover,: If =>: Is_live?
do Process:resize_to_fit => [the 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, the copy will not be generated. We can manually trigger when needed and run the following code:
Img.media.is_live = True
img.save
img.media.recreate_versions!: Cover
This code is also run at the foreground, is a blocking operation, but at least can be postponed to the last minute as far as possible. We can run further through Resque in the background:
# 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, queue:
Resque.enqueue (Imagequeue, img.id.to_s)
Performance improvement
Images are heavy and tend to slow down the site. One way to reduce the burden of a page is to compress the images. Carrierwave Image Optimizer can help us to 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 => ...
.
This compression does not have visual loss.
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.