- Notifications
You must be signed in to change notification settings - Fork0
High-level image processing wrapper for libvips and ImageMagick/GraphicsMagick
License
mark-young-atg/image_processing
Folders and files
Name | Name | Last commit message | Last commit date | |
---|---|---|---|---|
Repository files navigation
Provides higher-level image processing helpers that are commonly neededwhen handling image uploads.
This gem can process images with eitherImageMagick/GraphicsMagick orlibvips libraries. ImageMagick is a good default choice, especially if youare migrating from another gem or library that uses ImageMagick. Libvips is anewer library that can process imagesvery rapidly(often multiple times faster than ImageMagick).
The goal of this project is to have a single gem that contains all thehelper methods needed to resize and process images.
Currently, existing attachment gems (like Paperclip, CarrierWave, Refile,Dragonfly, ActiveStorage, and others) implement their own custom imagehelper methods. But why? That's not very DRY, is it?
Let's be honest. Image processing is a dark, mysterious art. So we want tocombine every great idea from all of these separate gems into a single awesomelibrary that is constantly updated with best-practice thinking abouthow to resize and process images.
- Install ImageMagick and/or libvips:
In a Mac terminal:
$ brew install imagemagick vips
In a debian/ubuntu terminal:
$ sudo apt install imagemagick libvips
- Add the gem to your Gemfile:
gem"image_processing","~> 1.0"
Processing is performed throughImageProcessing::Vips
orImageProcessing::MiniMagick
modules. Both modules share the samechainable API for defining the processing pipeline:
require"image_processing/mini_magick"processed=ImageProcessing::MiniMagick.source(file).resize_to_limit(400,400).convert("png").callprocessed#=> #<Tempfile:/var/folders/.../image_processing20180316-18446-1j247h6.png>
This allows easy branching when generating multiple derivates:
require"image_processing/vips"pipeline=ImageProcessing::Vips.source(file).convert("png")large=pipeline.resize_to_limit!(800,800)medium=pipeline.resize_to_limit!(500,500)small=pipeline.resize_to_limit!(300,300)
The processing is executed on#call
or when a processing method is calledwith a bang (!
).
processed=ImageProcessing::MiniMagick.convert("png").resize_to_limit(400,400).call(image)# ORprocessed=ImageProcessing::MiniMagick.source(image)# declare source image.convert("png").resize_to_limit(400,400).call# ORprocessed=ImageProcessing::MiniMagick.source(image).convert("png").resize_to_limit!(400,400)# bang method
You can inspect the pipeline options at any point before executing it:
pipeline=ImageProcessing::MiniMagick.source(image).loader(page:1).convert("png").resize_to_limit(400,400).strippipeline.options# => {:source=>#<File:/path/to/source.jpg>,# :loader=>{:page=>1},# :saver=>{},# :format=>"png",# :operations=>[[:resize_to_limit, [400, 400]], [:strip, []]],# :processor_class=>ImageProcessing::MiniMagick::Processor}
The source object needs to responds to#path
, or be a String, a Pathname, oraVips::Image
/MiniMagick::Tool
object. Note that the processed file isalways saved to a new location, in-place processing is not supported.
ImageProcessing::Vips.source(File.open("source.jpg"))ImageProcessing::Vips.source("source.jpg")ImageProcessing::Vips.source(Pathname.new("source.jpg"))ImageProcessing::Vips.source(Vips::Image.new_from_file("source.jpg"))
When#call
is called without options, the result of processing is aTempfile
object. You can save the processing result to a specific location bypassing:destination
to#call
, or passsave: false
to retrieve the rawVips::Image
/MiniMagick::Tool
object.
pipeline=ImageProcessing::Vips.source(image)pipeline.call#=> #<Tempfile ...>pipeline.call(save:false)#=> #<Vips::Image ...>pipeline.call(destination:"/path/to/destination")
You can continue reading the API documentation for specific modules:
See thewiki for additional "How To" guides for common scenarios. The wikiis publicly editable, so you're encouraged to add your own guides.
You can register an#instrumenter
block for a given pipeline, which will wrapthe pipeline execution, allowing you to record performance metrics.
pipeline=ImageProcessing::Vips.instrumenterdo |**options, &processing|options[:source]#=> #<File:...>options[:loader]#=> { fail: true }options[:saver]#=> { quality: 85 }options[:format]#=> "png"options[:operations]#=> [[:resize_to_limit, 500, 500], [:flip, [:horizontal]]]options[:processor]#=> ImageProcessing::Vips::ProcessorActiveSupport::Notifications.instrument("process.image_processing", **options)doprocessing.call# calls the pipelineendendpipeline.source(image).loader(fail:true).saver(quality:85).convert("png").resize_to_limit(500,500).flip(:horizontal).call# calls instrumenter
Our test suite requires bothimagemagick
andlibvips
libraries to be installed.
In a Mac terminal:
$ brew install imagemagick vips
In a debian/ubuntu terminal:
sudo apt install imagemagick libvips
Afterwards you can run tests with
$ bundle exec rake test
We welcome your feedback! What would you like to see added to image_processing?How can we improve this gem? Open an issue and let us know!
TheImageProcessing::MiniMagick
functionality was extracted fromrefile-mini_magick. The chainable interface was heavily inspired byHTTP.rb.