jr-paperclip 8.0.0 → 8.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3a0a10e43e470a988afe5f30de3f2144f18bca45154654abdbf09b57817bee4b
4
- data.tar.gz: 59df71bd9e4c0577f252165bf5b1d55202ffe8d363f0eae235d30db9c90b14fb
3
+ metadata.gz: 832b95743f1be2588ee95b5739e548c630a0c522f579da2234d083b58d82d708
4
+ data.tar.gz: 0034d60bdc931cb92fcd9a338bb2126419a183a9017344e2b036eb553e01ad8a
5
5
  SHA512:
6
- metadata.gz: 4ac11878b1797097dd0c6a369f39f03bc52153f2c9db2c2991d533b171a9f36fbec873b5859b55b378dbcb541d2d477f40de92d99456c7c3f5fb86c1d53eae5b
7
- data.tar.gz: 8ec53d673eee2ddbfab2008ab3a3977d659dda2df53f9e7c34d9cef307b1889d53ead7ae3a3c4d4cebdc33452c9ec3e9a5c7abfefb36f46ca5e5f68ecf0bc644
6
+ metadata.gz: e2828741e3347c89141a90baef60b1a9dd96482a29687a2ca146f663477d7e15f8dade773ff4b5f7e5d092c54ebf4fb7ed301baaa9c823286b5dceb6bfd08781
7
+ data.tar.gz: fd6704473b2934cbc999a82d986e144ce10e266b070d67b38802fe73daa07d650dbd5b1e47aeb112caa3bd0f889fd841315b5f740d3158c7341d1a9cafcdbbd0
data/NEWS CHANGED
@@ -1,3 +1,15 @@
1
+ 8.0.2 (2026-01-19)
2
+
3
+ * Performance: Optimized image thumbnail processing pipeline to handle EXIF orientation more efficiently when using vips backend.
4
+ * Bugix: Vips backend now uses copy_memory for operations that need random access.
5
+
6
+ 8.0.1 (2026-01-19)
7
+
8
+ * Performance: Vips backend now uses sequential access by default for better memory efficiency.
9
+ Sequential access streams images from top to bottom, keeping only a few scanlines in memory
10
+ rather than loading the entire image. This significantly reduces memory usage for large images.
11
+ Users can override via source_file_options: { access: :random } if needed.
12
+
1
13
  8.0.0 (2026-01-13)
2
14
 
3
15
  * Feature: Add libvips backend alongside ImageMagick via the image_processing gem
@@ -51,20 +51,22 @@ Good news! Many common `convert_options` now work with **both** ImageMagick and
51
51
 
52
52
  ### Options That Work on Both Backends
53
53
 
54
- | Option | Description |
55
- |--------|-------------|
56
- | `-strip` | Remove metadata/EXIF data |
57
- | `-quality N` | Output quality (1-100) |
58
- | `-rotate N` | Rotate by degrees |
59
- | `-flip` | Vertical flip |
60
- | `-flop` | Horizontal flip |
61
- | `-blur 0xN` | Gaussian blur |
62
- | `-sharpen 0xN` | Sharpen image |
63
- | `-colorspace X` | Color space (Gray, sRGB, CMYK) |
64
- | `-negate` | Invert colors |
65
- | `-flatten` | Flatten transparency |
66
- | `-auto-orient` | Auto-rotate via EXIF |
67
- | `-interlace X` | Progressive/interlaced output |
54
+ | Option | Description | Example |
55
+ |--------|-------------|---------|
56
+ | `-strip` | Remove metadata/EXIF | `convert_options: "-strip"` |
57
+ | `-quality N` | Output quality (1-100) | `convert_options: "-quality 80"` |
58
+ | `-rotate N` | Rotate by degrees | `convert_options: "-rotate 90"` |
59
+ | `-flip` | Vertical flip | `convert_options: "-flip"` |
60
+ | `-flop` | Horizontal flip | `convert_options: "-flop"` |
61
+ | `-blur 0xN` | Gaussian blur | `convert_options: "-blur 0x2"` |
62
+ | `-sharpen 0xN` | Sharpen image | `convert_options: "-sharpen 0x1"` |
63
+ | `-colorspace X` | Color space (Gray, sRGB, CMYK) | `convert_options: "-colorspace Gray"` |
64
+ | `-negate` | Invert colors | `convert_options: "-negate"` |
65
+ | `-flatten` | Flatten transparency | `convert_options: "-flatten"` |
66
+ | `-gamma N` | Adjust image gamma | `convert_options: "-gamma 1.5"` |
67
+ | `-auto-orient` | Auto-rotate via EXIF | `convert_options: "-auto-orient"` |
68
+ | `-interlace X` | Progressive output | `convert_options: "-interlace Plane"` |
69
+
68
70
 
69
71
  **Example:**
70
72
  ```ruby
@@ -183,6 +183,22 @@ module Paperclip
183
183
  def build_pipeline(source_path)
184
184
  pipeline = image_processing_module.source(source_path)
185
185
 
186
+ # Auto-orient based on EXIF data
187
+ if auto_orient
188
+ if backend == :vips
189
+ pipeline = pipeline.loader(autorotate: true)
190
+ elsif backend == :image_magick
191
+ pipeline = pipeline.auto_orient
192
+ end
193
+ end
194
+
195
+ # For vips backend, default to sequential access for better memory efficiency.
196
+ # Sequential access streams the image from top to bottom, keeping only a few
197
+ # scanlines in memory. Users can override via source_file_options: { access: :random }
198
+ if backend == :vips
199
+ pipeline = pipeline.loader(access: :sequential)
200
+ end
201
+
186
202
  # Handle source file options
187
203
  if @source_file_options
188
204
  loader_options = parse_loader_options(@source_file_options)
@@ -210,15 +226,6 @@ module Paperclip
210
226
  end
211
227
  end
212
228
 
213
- # Auto-orient based on EXIF data
214
- if auto_orient
215
- pipeline = if backend == :vips
216
- pipeline.autorot
217
- else
218
- pipeline.auto_orient
219
- end
220
- end
221
-
222
229
  # Apply resize operation
223
230
  if target_geometry
224
231
  pipeline = apply_resize(pipeline)
@@ -467,13 +474,15 @@ module Paperclip
467
474
  # Vips rotate via similarity for arbitrary angles
468
475
  if value
469
476
  angle = value.to_f
470
- pipeline.custom { |img| img.similarity(angle: angle) }
477
+ # Similarity requires random access (or memory copy) for non-trivial angles
478
+ pipeline.custom { |img| img.copy_memory.similarity(angle: angle) }
471
479
  else
472
480
  pipeline
473
481
  end
474
482
  when "flip"
475
483
  # Vips uses flip with direction
476
- pipeline.custom(&:flipver)
484
+ # Vertical flip requires random access (needs full image)
485
+ pipeline.custom { |img| img.copy_memory.flipver }
477
486
  when "flop"
478
487
  pipeline.custom(&:fliphor)
479
488
  when "blur", "gaussian_blur", "gaussblur"
@@ -504,14 +513,15 @@ module Paperclip
504
513
  when "median"
505
514
  value ? pipeline.median(value.to_i) : pipeline
506
515
  when "rot90"
507
- pipeline.rot90
516
+ # Rotations change scanline order, requiring random access
517
+ pipeline.custom { |img| img.copy_memory.rot90 }
508
518
  when "rot180"
509
- pipeline.rot180
519
+ pipeline.custom { |img| img.copy_memory.rot180 }
510
520
  when "rot270"
511
- pipeline.rot270
521
+ pipeline.custom { |img| img.copy_memory.rot270 }
512
522
  when "similarity"
513
523
  # similarity for arbitrary rotation/scale
514
- value ? pipeline.custom { |img| img.similarity(angle: value.to_f) } : pipeline
524
+ value ? pipeline.custom { |img| img.copy_memory.similarity(angle: value.to_f) } : pipeline
515
525
  # Edge detection filters (no arguments)
516
526
  when "canny"
517
527
  pipeline.canny
@@ -1,3 +1,3 @@
1
1
  module Paperclip
2
- VERSION = "8.0.0".freeze
2
+ VERSION = "8.0.2".freeze
3
3
  end
@@ -830,6 +830,34 @@ describe Paperclip::Thumbnail do
830
830
  end
831
831
  end
832
832
 
833
+ describe "-rot90" do
834
+ it "rotates the image 90 degrees" do
835
+ result = make_vips_thumb_with_options(@file, "-rot90")
836
+ expect(File.exist?(result.path)).to be true
837
+
838
+ dimensions = `identify -format "%wx%h" "#{result.path}"`.strip
839
+ # Resized to 100x15, then rotated 90 -> 15x100
840
+ expect(dimensions).to eq("15x100")
841
+ end
842
+ end
843
+
844
+ describe "-rot180" do
845
+ it "rotates the image 180 degrees" do
846
+ File.open(fixture_file("big_image.jpg"), "rb") do |file|
847
+ thumb = Paperclip::Thumbnail.new(file, {
848
+ geometry: "2000x2000",
849
+ convert_options: "-rot180",
850
+ backend: :vips,
851
+ }, attachment)
852
+ result = thumb.make
853
+ expect(File.exist?(result.path)).to be true
854
+
855
+ dimensions = `identify -format "%wx%h" "#{result.path}"`.strip
856
+ expect(dimensions).to eq("2000x1581")
857
+ end
858
+ end
859
+ end
860
+
833
861
  describe "-flip" do
834
862
  it "flips the image vertically" do
835
863
  result = make_vips_thumb_with_options(@file, "-flip")
Binary file
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jr-paperclip
3
3
  version: !ruby/object:Gem::Version
4
- version: 8.0.0
4
+ version: 8.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jukka Rautanen
@@ -571,6 +571,7 @@ files:
571
571
  - spec/support/fixtures/animated.unknown
572
572
  - spec/support/fixtures/aws_s3.yml
573
573
  - spec/support/fixtures/bad.png
574
+ - spec/support/fixtures/big_image.jpg
574
575
  - spec/support/fixtures/empty.html
575
576
  - spec/support/fixtures/empty.xlsx
576
577
  - spec/support/fixtures/fog.yml
@@ -712,6 +713,7 @@ test_files:
712
713
  - spec/support/fixtures/animated.unknown
713
714
  - spec/support/fixtures/aws_s3.yml
714
715
  - spec/support/fixtures/bad.png
716
+ - spec/support/fixtures/big_image.jpg
715
717
  - spec/support/fixtures/empty.html
716
718
  - spec/support/fixtures/empty.xlsx
717
719
  - spec/support/fixtures/fog.yml