Socket
Book a DemoInstallSign in
Socket

dragonfly-lossless_rotate

Package Overview
Dependencies
Maintainers
1
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

dragonfly-lossless_rotate

0.1.2
bundlerRubygems
Version published
Maintainers
1
Created
Source

Dragonfly Lossless Rotate

About 60% more performance with libjpeg-turbo tools

NOTE

Tool jpegtran from MozJPEG may work incorrectly and not rotate same image many times. You should test it before run in production.

Setup

gem "dragonfly-lossless_rotate"
Dragonfly.app.configure
  require "dragonfly/lossless_rotate"
  plugin :lossless_rotate
end

Requirements

By default gem use libjpeg binaries:

cjpeg
djpeg
jpegtran
pnmflip

But you can set MozJPEG binaries in ENV CJPEG_BIN=mozjpeg-cjpeg or in config:

Dragonfly.app.configure
  require "dragonfly/lossless_rotate"
  plugin :lossless_rotate, cjpeg_bin: "mozjpeg-cjpeg",
                           djpeg_bin: "mozjpeg-djpeg",
                           jpegtran_bin: "mozjpeg-jpegtran"

end

Usage

JPEG only:

@image.process(:lossless_rotate) # default 90
@image.process(:lossless_rotate, 180)
@image.process(:lossless_rotate, 270)
@image.process(:lossless_rotate, -90)

With fallback for other formats (rotate via ImageMagick):

@image.process(:safe_lossless_rotate)

Other options:

# Without JPEG optimization (default: true)
@image.process(:lossless_rotate, 90, optimize: false)
# Set default value
plugin :lossless_rotate, libjpeg_optimize: false

# Create progressive JPEG file (default: false)
@image.process(:lossless_rotate, 90, progressive: true)
# Set default value
plugin :lossless_rotate, libjpeg_progressive: true

Benchmark

  • libjpeg-turbo version 1.4.2 (build 20160222)
  • MozJPEG version 3.3.2 (build 20180713)

JPEG 85KB 552x416px

ImageMagick rotate

convert old_path -rotate 90 new_path
puts Benchmark.measure { 500.times { @image.rotate(90).apply } }
  0.360000   1.570000  25.270000 ( 25.168681)

Lossless rotate

libjpeg-turbo

(optimize=true)
jpegtran -rotate 90 -perfect -optimize old_path > new_path
puts Benchmark.measure { 500.times { @image.process(:lossless_rotate).apply } }
  0.280000   1.160000   9.170000 (  9.876645)

puts Benchmark.measure { 500.times { @image.process(:safe_lossless_rotate).apply } }
  0.560000   1.780000  22.710000 ( 23.879913)
(optimize=false)
jpegtran -rotate 90 -perfect old_path > new_path
puts Benchmark.measure { 500.times { @image.process(:lossless_rotate, 90, optimize: false).apply } }
  0.250000   1.090000   8.110000 (  8.601707)

puts Benchmark.measure { 500.times { @image.process(:safe_lossless_rotate, 90, optimize: false).apply } }
  0.360000   1.170000  21.480000 ( 22.744040)

MozJPEG

(optimize=true)
mozjpeg-jpegtran -rotate 90 -perfect -optimize old_path > new_path
puts Benchmark.measure { 500.times { @image.process(:lossless_rotate).apply } }
  0.270000   1.110000  35.230000 ( 36.693039)

puts Benchmark.measure { 500.times { @image.process(:safe_lossless_rotate).apply } }
  0.550000   1.540000  48.880000 ( 50.171667)
(optimize=false)
mozjpeg-jpegtran -rotate 90 -perfect old_path > new_path
puts Benchmark.measure { 500.times { @image.process(:lossless_rotate, 90, optimize: false).apply } }
  0.310000   1.100000  34.960000 ( 35.947432)

puts Benchmark.measure { 500.times { @image.process(:safe_lossless_rotate, 90, optimize: false).apply } }
  0.470000   1.660000  49.050000 ( 50.823576)

Fallback when jpegtran transformation is not perfect

if the image dimensions are not a multiple of the iMCU size (usually 8 or 16 pixels)

Same image but resized to 556x417px

libjpeg-turbo

(optimize=true)
djpeg old_path | pnmflip -r270 | cjpeg -optimize > new_path
puts Benchmark.measure { 500.times { @image.process(:lossless_rotate).apply } }
  0.410000   1.280000  16.310000 ( 13.220535)

puts Benchmark.measure { 500.times { @image.process(:safe_lossless_rotate).apply } }
  0.310000   1.330000  30.300000 ( 28.332533)
(optimize=false)
djpeg old_path | pnmflip -r270 | cjpeg > new_path
puts Benchmark.measure { 500.times { @image.process(:lossless_rotate, 90, optimize: false).apply } }
  0.330000   1.250000  15.190000 ( 11.990070)

puts Benchmark.measure { 500.times { @image.process(:safe_lossless_rotate, 90, optimize: false).apply } }
  0.330000   1.330000  29.010000 ( 26.816061)

MozJPEG

(optimize=true)
mozjpeg-djpeg old_path | pnmflip -r270 | mozjpeg-cjpeg -optimize > new_path
puts Benchmark.measure { 500.times { @image.process(:lossless_rotate).apply } }
  0.400000   1.150000  41.190000 ( 37.970843)

puts Benchmark.measure { 500.times { @image.process(:safe_lossless_rotate).apply } }
  0.420000   1.670000  55.700000 ( 52.835614)
(optimize=false)
mozjpeg-djpeg old_path | pnmflip -r270 | mozjpeg-cjpeg > new_path
puts Benchmark.measure { 500.times { @image.process(:lossless_rotate, 90, optimize: false).apply } }
  0.240000   0.860000  40.550000 ( 38.247647)

puts Benchmark.measure { 500.times { @image.process(:safe_lossless_rotate, 90, optimize: false).apply } }
  0.480000   1.330000  54.550000 ( 52.941735)

FAQs

Package last updated on 16 Jul 2018

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

SocketSocket SOC 2 Logo

Product

About

Packages

Stay in touch

Get open source security insights delivered straight into your inbox.

  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc

U.S. Patent No. 12,346,443 & 12,314,394. Other pending.