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 +4 -4
- data/NEWS +12 -0
- data/VIPS_MIGRATION_GUIDE.md +16 -14
- data/lib/paperclip/thumbnail.rb +25 -15
- data/lib/paperclip/version.rb +1 -1
- data/spec/paperclip/thumbnail_spec.rb +28 -0
- data/spec/support/fixtures/big_image.jpg +0 -0
- metadata +3 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 832b95743f1be2588ee95b5739e548c630a0c522f579da2234d083b58d82d708
|
|
4
|
+
data.tar.gz: 0034d60bdc931cb92fcd9a338bb2126419a183a9017344e2b036eb553e01ad8a
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
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
|
data/VIPS_MIGRATION_GUIDE.md
CHANGED
|
@@ -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
|
|
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
|
-
| `-
|
|
67
|
-
| `-
|
|
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
|
data/lib/paperclip/thumbnail.rb
CHANGED
|
@@ -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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
data/lib/paperclip/version.rb
CHANGED
|
@@ -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.
|
|
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
|