image_pack 0.2.1 → 0.2.3
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/CHANGELOG.md +20 -0
- data/README.md +75 -16
- data/ext/image_pack/extconf.rb +41 -126
- data/ext/image_pack/image_pack.c +1151 -596
- data/ext/image_pack/mozjpeg_sources.rb +178 -0
- data/ext/image_pack/vendor/mozjpeg/BUILDING.md +744 -0
- data/ext/image_pack/vendor/mozjpeg/CODE_OF_CONDUCT.md +15 -0
- data/ext/image_pack/vendor/mozjpeg/ChangeLog.md +1996 -0
- data/lib/image_pack/configuration.rb +54 -8
- data/lib/image_pack/version.rb +1 -1
- data/lib/image_pack.rb +124 -41
- metadata +13 -79
- data/ext/image_pack/vendor/mozjpeg/README.ijg +0 -258
- data/ext/image_pack/vendor/mozjpeg/cdjpeg.c +0 -156
- data/ext/image_pack/vendor/mozjpeg/cjpeg.c +0 -961
- data/ext/image_pack/vendor/mozjpeg/djpeg.c +0 -855
- data/ext/image_pack/vendor/mozjpeg/jaricom.c +0 -157
- data/ext/image_pack/vendor/mozjpeg/jcarith.c +0 -972
- data/ext/image_pack/vendor/mozjpeg/jcstest.c +0 -126
- data/ext/image_pack/vendor/mozjpeg/jdarith.c +0 -782
- data/ext/image_pack/vendor/mozjpeg/jdatadst-tj.c +0 -198
- data/ext/image_pack/vendor/mozjpeg/jdatasrc-tj.c +0 -194
- data/ext/image_pack/vendor/mozjpeg/jpegtran.c +0 -827
- data/ext/image_pack/vendor/mozjpeg/jpegyuv.c +0 -172
- data/ext/image_pack/vendor/mozjpeg/rdbmp.c +0 -690
- data/ext/image_pack/vendor/mozjpeg/rdcolmap.c +0 -253
- data/ext/image_pack/vendor/mozjpeg/rdgif.c +0 -720
- data/ext/image_pack/vendor/mozjpeg/rdjpeg.c +0 -160
- data/ext/image_pack/vendor/mozjpeg/rdjpgcom.c +0 -494
- data/ext/image_pack/vendor/mozjpeg/rdpng.c +0 -194
- data/ext/image_pack/vendor/mozjpeg/rdppm.c +0 -781
- data/ext/image_pack/vendor/mozjpeg/rdswitch.c +0 -642
- data/ext/image_pack/vendor/mozjpeg/rdtarga.c +0 -508
- data/ext/image_pack/vendor/mozjpeg/simd/arm/aarch32/jccolext-neon.c +0 -148
- data/ext/image_pack/vendor/mozjpeg/simd/arm/aarch32/jchuff-neon.c +0 -334
- data/ext/image_pack/vendor/mozjpeg/simd/arm/aarch32/jsimd.c +0 -976
- data/ext/image_pack/vendor/mozjpeg/simd/i386/jsimd.c +0 -1312
- data/ext/image_pack/vendor/mozjpeg/simd/mips/jsimd.c +0 -1143
- data/ext/image_pack/vendor/mozjpeg/simd/mips64/jccolext-mmi.c +0 -455
- data/ext/image_pack/vendor/mozjpeg/simd/mips64/jccolor-mmi.c +0 -148
- data/ext/image_pack/vendor/mozjpeg/simd/mips64/jcgray-mmi.c +0 -132
- data/ext/image_pack/vendor/mozjpeg/simd/mips64/jcgryext-mmi.c +0 -374
- data/ext/image_pack/vendor/mozjpeg/simd/mips64/jcsample-mmi.c +0 -98
- data/ext/image_pack/vendor/mozjpeg/simd/mips64/jdcolext-mmi.c +0 -415
- data/ext/image_pack/vendor/mozjpeg/simd/mips64/jdcolor-mmi.c +0 -139
- data/ext/image_pack/vendor/mozjpeg/simd/mips64/jdmerge-mmi.c +0 -149
- data/ext/image_pack/vendor/mozjpeg/simd/mips64/jdmrgext-mmi.c +0 -615
- data/ext/image_pack/vendor/mozjpeg/simd/mips64/jdsample-mmi.c +0 -304
- data/ext/image_pack/vendor/mozjpeg/simd/mips64/jfdctfst-mmi.c +0 -255
- data/ext/image_pack/vendor/mozjpeg/simd/mips64/jfdctint-mmi.c +0 -398
- data/ext/image_pack/vendor/mozjpeg/simd/mips64/jidctfst-mmi.c +0 -395
- data/ext/image_pack/vendor/mozjpeg/simd/mips64/jidctint-mmi.c +0 -571
- data/ext/image_pack/vendor/mozjpeg/simd/mips64/jquanti-mmi.c +0 -124
- data/ext/image_pack/vendor/mozjpeg/simd/mips64/jsimd.c +0 -866
- data/ext/image_pack/vendor/mozjpeg/simd/powerpc/jccolext-altivec.c +0 -269
- data/ext/image_pack/vendor/mozjpeg/simd/powerpc/jccolor-altivec.c +0 -116
- data/ext/image_pack/vendor/mozjpeg/simd/powerpc/jcgray-altivec.c +0 -111
- data/ext/image_pack/vendor/mozjpeg/simd/powerpc/jcgryext-altivec.c +0 -228
- data/ext/image_pack/vendor/mozjpeg/simd/powerpc/jcsample-altivec.c +0 -159
- data/ext/image_pack/vendor/mozjpeg/simd/powerpc/jdcolext-altivec.c +0 -276
- data/ext/image_pack/vendor/mozjpeg/simd/powerpc/jdcolor-altivec.c +0 -106
- data/ext/image_pack/vendor/mozjpeg/simd/powerpc/jdmerge-altivec.c +0 -130
- data/ext/image_pack/vendor/mozjpeg/simd/powerpc/jdmrgext-altivec.c +0 -329
- data/ext/image_pack/vendor/mozjpeg/simd/powerpc/jdsample-altivec.c +0 -400
- data/ext/image_pack/vendor/mozjpeg/simd/powerpc/jfdctfst-altivec.c +0 -154
- data/ext/image_pack/vendor/mozjpeg/simd/powerpc/jfdctint-altivec.c +0 -258
- data/ext/image_pack/vendor/mozjpeg/simd/powerpc/jidctfst-altivec.c +0 -255
- data/ext/image_pack/vendor/mozjpeg/simd/powerpc/jidctint-altivec.c +0 -357
- data/ext/image_pack/vendor/mozjpeg/simd/powerpc/jquanti-altivec.c +0 -250
- data/ext/image_pack/vendor/mozjpeg/simd/powerpc/jsimd.c +0 -884
- data/ext/image_pack/vendor/mozjpeg/strtest.c +0 -170
- data/ext/image_pack/vendor/mozjpeg/tjbench.c +0 -1044
- data/ext/image_pack/vendor/mozjpeg/tjexample.c +0 -406
- data/ext/image_pack/vendor/mozjpeg/tjunittest.c +0 -961
- data/ext/image_pack/vendor/mozjpeg/tjutil.c +0 -70
- data/ext/image_pack/vendor/mozjpeg/transupp.c +0 -2373
- data/ext/image_pack/vendor/mozjpeg/turbojpeg-jni.c +0 -1259
- data/ext/image_pack/vendor/mozjpeg/turbojpeg.c +0 -2320
- data/ext/image_pack/vendor/mozjpeg/wrbmp.c +0 -552
- data/ext/image_pack/vendor/mozjpeg/wrgif.c +0 -580
- data/ext/image_pack/vendor/mozjpeg/wrjpgcom.c +0 -577
- data/ext/image_pack/vendor/mozjpeg/wrppm.c +0 -366
- data/ext/image_pack/vendor/mozjpeg/wrtarga.c +0 -258
- data/ext/image_pack/vendor/mozjpeg/yuvjpeg.c +0 -268
- data/lib/image_pack/backend.rb +0 -8
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 606688569aac1fa1515edefe270b18a04e5b0042de602b18663964726d8fbb34
|
|
4
|
+
data.tar.gz: 9092fcf9fa3c061edc87ce2a22544acfe52dfa6ce4fe39961c95a1d17220a6b0
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: ad6b0db99c56d69c99d9216559e3c114a2079941a4f879e69508126bbf12b070844dc53e806b3da7637783a205528c10136c3cd3bac8f60b5fd6ee2ddcad01eb
|
|
7
|
+
data.tar.gz: f1acfa9f5a7154d1ea201ae66658da704a5ee5d207886b096d284b7b69eca175d668993dba127b0a609d6fb5b68492196edb8d3bb70d12575f129c095c6b7704
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,25 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
- Lowered the runtime floor to Ruby >= 3.1.0 while keeping `execution: :offload` Ruby >= 3.4-only and explicitly unsupported on older Rubies.
|
|
4
|
+
## 0.2.2
|
|
5
|
+
|
|
6
|
+
- Fixed native cleanup safety: native contexts are now released through `rb_ensure`, including Ruby exception paths from argument coercion, config reads, native status errors, output `String` allocation, and file-output failures.
|
|
7
|
+
- Fixed libjpeg `longjmp` cleanup for encode/decode/luma-decode transient buffers.
|
|
8
|
+
- Fixed `max_output_size = 0` semantics; all size/dimension limits now consistently treat `0` as disabled.
|
|
9
|
+
- Fixed `compress_pixels(min_ssim:)`: it now uses the raw pixel buffer as the reference instead of a temporary quality-95 seed JPEG, and it respects the requested execution mode.
|
|
10
|
+
- Fixed metadata preservation drift: `strip_metadata: false` now preserves markers across fast, size, and SSIM paths.
|
|
11
|
+
- Fixed EXIF Orientation stripping: when metadata is stripped, orientation is applied to decoded pixels before output.
|
|
12
|
+
- Fixed `progressive:` for `algo: :mozjpeg`; `progressive: false` no longer silently inherits the max-compression progressive scan script.
|
|
13
|
+
- Added decode/luma-decode cancellation checkpoints.
|
|
14
|
+
- Reduced avoidable copying for explicit `execution: :direct` String/pixel inputs.
|
|
15
|
+
- Batched RGBA→RGB scanline encoding instead of writing one line at a time.
|
|
16
|
+
- Decoded SSIM candidate luma directly as grayscale instead of RGB + manual luma conversion.
|
|
17
|
+
- Made output-path writes safer by writing to a temporary file, checking `fclose`, and renaming into place.
|
|
18
|
+
- Added `compress_bytes`, `compress_file`, `optimize_jpeg`, `optimize_bytes`, `optimize_file`, and `build_info`.
|
|
19
|
+
- Added coefficient-level lossless JPEG optimization through `jpeg_read_coefficients` / `jpeg_write_coefficients`; this avoids decode→pixels→re-encode when only optimizing an existing JPEG.
|
|
20
|
+
- Made private native entrypoints private class methods.
|
|
21
|
+
- Added `-fvisibility=hidden` and `IMAGE_PACK_REQUIRE_SIMD=1` build guard.
|
|
22
|
+
|
|
3
23
|
## 0.2.1
|
|
4
24
|
|
|
5
25
|
- `ip_compute_ssim_luma_buffer`: rewrote inner accumulators from `double` to
|
data/README.md
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# image_pack
|
|
2
2
|
|
|
3
|
-
`image_pack` is a Ruby-native JPEG compressor prototype for Ruby `>= 3.
|
|
3
|
+
`image_pack` is a Ruby-native JPEG compressor prototype for Ruby `>= 3.1.0`.
|
|
4
4
|
|
|
5
|
-
Current version: `0.2.
|
|
5
|
+
Current version: `0.2.2`.
|
|
6
6
|
|
|
7
7
|
This pure-C variant intentionally removes Jpegli and any C++ toolchain requirement.
|
|
8
8
|
The native layer is written in C and links against vendored MozJPEG, which is libjpeg-compatible and based on libjpeg-turbo.
|
|
@@ -14,8 +14,8 @@ ImagePack.compress(input, algo: :jpeg_turbo)
|
|
|
14
14
|
ImagePack.compress(input, algo: :mozjpeg)
|
|
15
15
|
```
|
|
16
16
|
|
|
17
|
-
- `:jpeg_turbo` — fast libjpeg-compatible mode with MozJPEG-specific size optimizations disabled.
|
|
18
|
-
- `:mozjpeg` — size-oriented mode using
|
|
17
|
+
- `:jpeg_turbo` / `:fast` — fast libjpeg-compatible mode with MozJPEG-specific size optimizations disabled.
|
|
18
|
+
- `:mozjpeg` / `:size` — size-oriented mode using optimized Huffman coding and optional progressive output through the MozJPEG/libjpeg API.
|
|
19
19
|
|
|
20
20
|
Both modes produce ordinary `.jpg` files.
|
|
21
21
|
|
|
@@ -52,6 +52,14 @@ ImagePack.compress(jpeg, algo: :mozjpeg, min_ssim: 0.985)
|
|
|
52
52
|
ImagePack.compress(jpeg, algo: :mozjpeg, quality: 75, min_ssim: 0.985)
|
|
53
53
|
|
|
54
54
|
ImagePack.compress("photo.jpg", output: "photo.optimized.jpg", algo: :mozjpeg)
|
|
55
|
+
ImagePack.compress_file("photo.jpg", output: "photo.optimized.jpg", algo: :mozjpeg)
|
|
56
|
+
ImagePack.compress_bytes(jpeg, algo: :fast, quality: 82)
|
|
57
|
+
|
|
58
|
+
# Lossless coefficient-level JPEG optimization/transcode.
|
|
59
|
+
# This rewrites JPEG coefficients without decoding/re-encoding pixels.
|
|
60
|
+
ImagePack.optimize_jpeg(jpeg, progressive: true, strip_metadata: false)
|
|
61
|
+
ImagePack.optimize_file("photo.jpg", output: "photo.lossless.jpg")
|
|
62
|
+
ImagePack.optimize_bytes(jpeg)
|
|
55
63
|
|
|
56
64
|
ImagePack.compress_pixels(rgb_buffer,
|
|
57
65
|
width: 1920,
|
|
@@ -69,19 +77,32 @@ ImagePack.inspect_image(jpeg)
|
|
|
69
77
|
`compress(input, ...)` accepts JPEG input only:
|
|
70
78
|
|
|
71
79
|
- binary `String` (`ASCII-8BIT`) — JPEG bytes;
|
|
72
|
-
- non-binary `String` — file path;
|
|
80
|
+
- non-binary `String` that points to an existing file — file path;
|
|
73
81
|
- `Pathname` — file path;
|
|
74
82
|
- `IO::Buffer` — JPEG bytes, copied before native no-GVL execution for safety.
|
|
75
83
|
|
|
84
|
+
For non-ambiguous call sites prefer `compress_bytes(bytes, ...)` or `compress_file(path, ...)`.
|
|
85
|
+
|
|
76
86
|
`compress_pixels(buffer, ...)` accepts raw pixels as binary `String` or `IO::Buffer`.
|
|
77
|
-
`channels` must be `1`, `3`, or `4`. Alpha in RGBA input is dropped in v0.2.
|
|
87
|
+
`channels` must be `1`, `3`, or `4`. Alpha in RGBA input is dropped in v0.2.2; pass `drop_alpha: true` to make that explicit, or `drop_alpha: false` to reject it.
|
|
88
|
+
|
|
89
|
+
`output: nil` returns binary JPEG bytes. `output: String/Pathname` writes through a temporary file and renames it into place.
|
|
90
|
+
Streaming output is intentionally not supported in v0.2.2.
|
|
91
|
+
|
|
92
|
+
## Lossless JPEG optimize
|
|
93
|
+
|
|
94
|
+
`optimize_jpeg`, `optimize_bytes`, and `optimize_file` are coefficient-level JPEG transcode helpers. They use `jpeg_read_coefficients` / `jpeg_write_coefficients`, so pixels are not decoded and re-encoded. This is the preferred path when you only want to rewrite an existing JPEG with optimized Huffman tables and optional progressive scans.
|
|
95
|
+
|
|
96
|
+
Defaults are intentionally conservative:
|
|
78
97
|
|
|
79
|
-
|
|
80
|
-
|
|
98
|
+
- `progressive: true` creates a progressive optimized JPEG;
|
|
99
|
+
- `strip_metadata: false` preserves APP/COM metadata by default because this path is meant to be visually/losslessly safe.
|
|
100
|
+
|
|
101
|
+
If `strip_metadata: true` is requested and the source JPEG has EXIF Orientation, `optimize_jpeg` raises `UnsupportedError` instead of silently removing the orientation tag and changing how viewers display the image. Use `strip_metadata: false` for coefficient-level optimization, or `compress(..., strip_metadata: true)` if you want pixel-level orientation normalization.
|
|
81
102
|
|
|
82
103
|
## SSIM guard
|
|
83
104
|
|
|
84
|
-
`compress`
|
|
105
|
+
`compress` and `compress_pixels` accept `min_ssim:`. This enables a native guarded path:
|
|
85
106
|
|
|
86
107
|
1. decode the original JPEG to reference pixels;
|
|
87
108
|
2. encode trial JPEG candidates with the existing MozJPEG/libjpeg backend;
|
|
@@ -96,11 +117,31 @@ the encoder raises quality only if the candidate violates the SSIM floor.
|
|
|
96
117
|
If no quality can satisfy the requested floor, `ImagePack::QualityConstraintError`
|
|
97
118
|
is raised. With `execution: :auto`, guarded compression uses the no-GVL/offload
|
|
98
119
|
path instead of the small-image direct path because it may encode/decode several
|
|
99
|
-
candidates. `
|
|
100
|
-
|
|
120
|
+
candidates. For `compress_pixels`, the reference is the raw pixel buffer itself, not a seed JPEG. RGBA + `min_ssim` is rejected because JPEG cannot represent alpha.
|
|
121
|
+
|
|
122
|
+
The metric is a fast native luma SSIM-like guard based on 8x8 blocks, not a full Wang-style Gaussian-window reference implementation. It is intended as a compression guard, not as a general-purpose image quality benchmark.
|
|
101
123
|
|
|
102
124
|
## Execution modes
|
|
103
125
|
|
|
126
|
+
### Ruby compatibility for offload
|
|
127
|
+
|
|
128
|
+
ImagePack supports Ruby `>= 3.1.0`. Ruby `>= 3.4.0` is required only for the scheduler-aware `execution: :offload` path.
|
|
129
|
+
|
|
130
|
+
On Ruby 3.1–3.3:
|
|
131
|
+
|
|
132
|
+
- `execution: :direct` works.
|
|
133
|
+
- `execution: :nogvl` works.
|
|
134
|
+
- `execution: :auto` works, but never selects `:offload`.
|
|
135
|
+
- explicit `execution: :offload` raises `ImagePack::UnsupportedError`.
|
|
136
|
+
|
|
137
|
+
On Ruby 3.4+:
|
|
138
|
+
|
|
139
|
+
- `execution: :offload` is available.
|
|
140
|
+
- `execution: :auto` may select `:offload` when a Fiber scheduler is active.
|
|
141
|
+
|
|
142
|
+
Use `ImagePack.offload_safe?` or `ImagePack.build_info[:offload_safe]` to check the native capability at runtime.
|
|
143
|
+
|
|
144
|
+
|
|
104
145
|
```ruby
|
|
105
146
|
ImagePack.compress(jpeg, execution: :direct)
|
|
106
147
|
ImagePack.compress(jpeg, execution: :nogvl)
|
|
@@ -110,13 +151,24 @@ ImagePack.compress(jpeg, execution: :auto)
|
|
|
110
151
|
|
|
111
152
|
- `:direct` — executes under GVL, intended for small images.
|
|
112
153
|
- `:nogvl` — uses `rb_nogvl(..., flags: 0)`.
|
|
113
|
-
- `:offload` — uses `rb_nogvl(..., RB_NOGVL_OFFLOAD_SAFE)` on Ruby 3.4
|
|
114
|
-
- `:auto` — header-first policy chooses direct/nogvl/offload.
|
|
154
|
+
- `:offload` — uses `rb_nogvl(..., RB_NOGVL_OFFLOAD_SAFE)` on Ruby 3.4+; raises `ImagePack::UnsupportedError` on Ruby 3.1–3.3.
|
|
155
|
+
- `:auto` — header-first policy chooses direct/nogvl/offload; on Ruby 3.1–3.3 it never selects offload.
|
|
115
156
|
|
|
116
157
|
## Cancellation
|
|
117
158
|
|
|
118
|
-
`cancellable: true` is supported
|
|
119
|
-
Cancellation is cooperative at
|
|
159
|
+
`cancellable: true` is supported for `execution: :nogvl`, `:offload`, or `:auto`.
|
|
160
|
+
Cancellation is cooperative at decode, encode, and SSIM-search checkpoints, not instant.
|
|
161
|
+
|
|
162
|
+
## Metadata / EXIF orientation
|
|
163
|
+
|
|
164
|
+
`strip_metadata: true` removes metadata. If the source JPEG contains EXIF Orientation, `image_pack` applies that orientation to decoded pixels before stripping metadata, so the visual orientation is preserved. With `strip_metadata: false`, APP/COM markers are preserved across both fast and size-oriented paths.
|
|
165
|
+
|
|
166
|
+
## Build info
|
|
167
|
+
|
|
168
|
+
```ruby
|
|
169
|
+
ImagePack.build_info
|
|
170
|
+
# => { version: "0.2.2", mozjpeg: "4.1.5", simd: true, offload_safe: true }
|
|
171
|
+
```
|
|
120
172
|
|
|
121
173
|
## Vendoring
|
|
122
174
|
|
|
@@ -130,11 +182,18 @@ bundle exec rake compile
|
|
|
130
182
|
|
|
131
183
|
`rake vendor` pins MozJPEG `v4.1.5`.
|
|
132
184
|
|
|
185
|
+
## Current limitations
|
|
186
|
+
|
|
187
|
+
- Pixel-level `compress` rejects CMYK/YCCK JPEG input because it decodes to RGB/gray before re-encoding. Use `optimize_jpeg` for coefficient-level lossless optimization of existing CMYK/YCCK JPEGs.
|
|
188
|
+
- Arithmetic-coded JPEG support is disabled in the vendored `jconfig.h` for v0.2.2.
|
|
189
|
+
- The SSIM guard is a fast 8x8 luma block metric and still assumes quality/SSIM monotonicity during binary search.
|
|
190
|
+
- `compress(input, ...)` still has a legacy path-vs-bytes heuristic for non-binary `String`; prefer `compress_bytes` / `compress_file` and `optimize_bytes` / `optimize_file` in new code.
|
|
191
|
+
|
|
133
192
|
## What is intentionally not included
|
|
134
193
|
|
|
135
194
|
- Jpegli / C++ code
|
|
136
195
|
- AVIF/WebP/PNG
|
|
137
196
|
- FFI
|
|
138
197
|
- shell-out
|
|
139
|
-
- tempfiles
|
|
198
|
+
- external tempfiles for in-memory output
|
|
140
199
|
- byte-size targets / max-bytes policy
|
data/ext/image_pack/extconf.rb
CHANGED
|
@@ -4,127 +4,19 @@ require "mkmf"
|
|
|
4
4
|
require "fileutils"
|
|
5
5
|
require "rbconfig"
|
|
6
6
|
|
|
7
|
-
if Gem::Version.new(RUBY_VERSION) < Gem::Version.new("3.
|
|
8
|
-
abort "image_pack requires Ruby >= 3.
|
|
7
|
+
if Gem::Version.new(RUBY_VERSION) < Gem::Version.new("3.1.0")
|
|
8
|
+
abort "image_pack requires Ruby >= 3.1.0; got #{RUBY_VERSION}"
|
|
9
9
|
end
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
jcinit.c
|
|
21
|
-
jcmainct.c
|
|
22
|
-
jcmarker.c
|
|
23
|
-
jcmaster.c
|
|
24
|
-
jcomapi.c
|
|
25
|
-
jcparam.c
|
|
26
|
-
jcphuff.c
|
|
27
|
-
jcprepct.c
|
|
28
|
-
jcsample.c
|
|
29
|
-
jctrans.c
|
|
30
|
-
jdapimin.c
|
|
31
|
-
jdapistd.c
|
|
32
|
-
jdatadst.c
|
|
33
|
-
jdatasrc.c
|
|
34
|
-
jdcoefct.c
|
|
35
|
-
jdcolor.c
|
|
36
|
-
jddctmgr.c
|
|
37
|
-
jdhuff.c
|
|
38
|
-
jdicc.c
|
|
39
|
-
jdinput.c
|
|
40
|
-
jdmainct.c
|
|
41
|
-
jdmarker.c
|
|
42
|
-
jdmaster.c
|
|
43
|
-
jdmerge.c
|
|
44
|
-
jdphuff.c
|
|
45
|
-
jdpostct.c
|
|
46
|
-
jdsample.c
|
|
47
|
-
jdtrans.c
|
|
48
|
-
jerror.c
|
|
49
|
-
jfdctflt.c
|
|
50
|
-
jfdctfst.c
|
|
51
|
-
jfdctint.c
|
|
52
|
-
jidctflt.c
|
|
53
|
-
jidctfst.c
|
|
54
|
-
jidctint.c
|
|
55
|
-
jidctred.c
|
|
56
|
-
jquant1.c
|
|
57
|
-
jquant2.c
|
|
58
|
-
jutils.c
|
|
59
|
-
jmemmgr.c
|
|
60
|
-
jmemnobs.c
|
|
61
|
-
].freeze
|
|
62
|
-
|
|
63
|
-
NEON_AARCH64_SOURCES = [
|
|
64
|
-
"simd/arm/aarch64/jsimd.c",
|
|
65
|
-
"simd/arm/aarch64/jchuff-neon.c",
|
|
66
|
-
"simd/arm/jccolor-neon.c",
|
|
67
|
-
"simd/arm/jcgray-neon.c",
|
|
68
|
-
"simd/arm/jcphuff-neon.c",
|
|
69
|
-
"simd/arm/jcsample-neon.c",
|
|
70
|
-
"simd/arm/jdcolor-neon.c",
|
|
71
|
-
"simd/arm/jdmerge-neon.c",
|
|
72
|
-
"simd/arm/jdsample-neon.c",
|
|
73
|
-
"simd/arm/jfdctfst-neon.c",
|
|
74
|
-
"simd/arm/jfdctint-neon.c",
|
|
75
|
-
"simd/arm/jidctfst-neon.c",
|
|
76
|
-
"simd/arm/jidctint-neon.c",
|
|
77
|
-
"simd/arm/jidctred-neon.c",
|
|
78
|
-
"simd/arm/jquanti-neon.c",
|
|
79
|
-
].freeze
|
|
80
|
-
|
|
81
|
-
X86_64_C_SOURCES = [
|
|
82
|
-
"simd/x86_64/jsimd.c",
|
|
83
|
-
].freeze
|
|
84
|
-
|
|
85
|
-
X86_64_ASM_SOURCES = %w[
|
|
86
|
-
simd/x86_64/jsimdcpu.asm
|
|
87
|
-
simd/x86_64/jfdctflt-sse.asm
|
|
88
|
-
simd/x86_64/jccolor-sse2.asm
|
|
89
|
-
simd/x86_64/jcgray-sse2.asm
|
|
90
|
-
simd/x86_64/jchuff-sse2.asm
|
|
91
|
-
simd/x86_64/jcphuff-sse2.asm
|
|
92
|
-
simd/x86_64/jcsample-sse2.asm
|
|
93
|
-
simd/x86_64/jdcolor-sse2.asm
|
|
94
|
-
simd/x86_64/jdmerge-sse2.asm
|
|
95
|
-
simd/x86_64/jdsample-sse2.asm
|
|
96
|
-
simd/x86_64/jfdctfst-sse2.asm
|
|
97
|
-
simd/x86_64/jfdctint-sse2.asm
|
|
98
|
-
simd/x86_64/jidctflt-sse2.asm
|
|
99
|
-
simd/x86_64/jidctfst-sse2.asm
|
|
100
|
-
simd/x86_64/jidctint-sse2.asm
|
|
101
|
-
simd/x86_64/jidctred-sse2.asm
|
|
102
|
-
simd/x86_64/jquantf-sse2.asm
|
|
103
|
-
simd/x86_64/jquanti-sse2.asm
|
|
104
|
-
simd/x86_64/jccolor-avx2.asm
|
|
105
|
-
simd/x86_64/jcgray-avx2.asm
|
|
106
|
-
simd/x86_64/jcsample-avx2.asm
|
|
107
|
-
simd/x86_64/jdcolor-avx2.asm
|
|
108
|
-
simd/x86_64/jdmerge-avx2.asm
|
|
109
|
-
simd/x86_64/jdsample-avx2.asm
|
|
110
|
-
simd/x86_64/jfdctint-avx2.asm
|
|
111
|
-
simd/x86_64/jidctint-avx2.asm
|
|
112
|
-
simd/x86_64/jquanti-avx2.asm
|
|
113
|
-
].freeze
|
|
114
|
-
|
|
115
|
-
X86_64_ASM_TEMPLATE_SOURCES = %w[
|
|
116
|
-
simd/x86_64/jccolext-sse2.asm
|
|
117
|
-
simd/x86_64/jcgryext-sse2.asm
|
|
118
|
-
simd/x86_64/jdcolext-sse2.asm
|
|
119
|
-
simd/x86_64/jdmrgext-sse2.asm
|
|
120
|
-
simd/x86_64/jccolext-avx2.asm
|
|
121
|
-
simd/x86_64/jcgryext-avx2.asm
|
|
122
|
-
simd/x86_64/jdcolext-avx2.asm
|
|
123
|
-
simd/x86_64/jdmrgext-avx2.asm
|
|
124
|
-
].freeze
|
|
125
|
-
|
|
126
|
-
MOZJPEG_VERSION = "4.1.5"
|
|
127
|
-
MOZJPEG_VERSION_NUMBER = "4001005"
|
|
11
|
+
require_relative "mozjpeg_sources"
|
|
12
|
+
|
|
13
|
+
MOZJPEG_CORE_SOURCES = ImagePackMozjpegSources::TOPLEVEL_C_SOURCES
|
|
14
|
+
MOZJPEG_INCLUDE_TEMPLATES = ImagePackMozjpegSources::TOPLEVEL_INCLUDE_TEMPLATES
|
|
15
|
+
NEON_AARCH64_SOURCES = ImagePackMozjpegSources::NEON_AARCH64_C_SOURCES
|
|
16
|
+
X86_64_C_SOURCES = ImagePackMozjpegSources::X86_64_C_SOURCES
|
|
17
|
+
X86_64_ASM_SOURCES = ImagePackMozjpegSources::X86_64_ASM_SOURCES
|
|
18
|
+
MOZJPEG_VERSION = ImagePackMozjpegSources::VERSION
|
|
19
|
+
MOZJPEG_VERSION_NUMBER = ImagePackMozjpegSources::VERSION_NUMBER
|
|
128
20
|
|
|
129
21
|
def find_vendor_dir
|
|
130
22
|
candidates = [
|
|
@@ -285,8 +177,14 @@ def select_simd_backend(mozjpeg_dir, arch)
|
|
|
285
177
|
else
|
|
286
178
|
missing = NEON_AARCH64_SOURCES.reject { |rel| File.exist?(File.join(mozjpeg_dir, rel)) }
|
|
287
179
|
missing << "simd/arm/neon-compat.h.in" unless template_present
|
|
288
|
-
|
|
289
|
-
|
|
180
|
+
message = "image_pack: ARM64 detected but NEON sources are incomplete under #{mozjpeg_dir}:
|
|
181
|
+
" "#{missing.map { |m| " - #{m}" }.join("
|
|
182
|
+
")}"
|
|
183
|
+
if ENV["IMAGE_PACK_REQUIRE_SIMD"] == "1"
|
|
184
|
+
abort "#{message}
|
|
185
|
+
image_pack: refusing scalar fallback because IMAGE_PACK_REQUIRE_SIMD=1."
|
|
186
|
+
end
|
|
187
|
+
warn message
|
|
290
188
|
warn "image_pack: re-run `bundle exec rake vendor` after updating script/vendor_libs.rb."
|
|
291
189
|
warn "image_pack: falling back to scalar."
|
|
292
190
|
{ kind: :none }
|
|
@@ -294,16 +192,32 @@ def select_simd_backend(mozjpeg_dir, arch)
|
|
|
294
192
|
|
|
295
193
|
when :x86_64
|
|
296
194
|
if find_nasm.nil?
|
|
297
|
-
|
|
195
|
+
message = "image_pack: x86_64 detected but NASM/YASM not found on PATH."
|
|
196
|
+
if ENV["IMAGE_PACK_REQUIRE_SIMD"] == "1"
|
|
197
|
+
abort "#{message} Install nasm/yasm or unset IMAGE_PACK_REQUIRE_SIMD."
|
|
198
|
+
end
|
|
199
|
+
warn "#{message} Falling back to scalar; install nasm for ~3-4x speedup. Set IMAGE_PACK_REQUIRE_SIMD=1 to fail instead."
|
|
298
200
|
{ kind: :none }
|
|
299
201
|
elsif !X86_64_C_SOURCES.all? { |rel| File.exist?(File.join(mozjpeg_dir, rel)) }
|
|
300
|
-
|
|
202
|
+
missing = X86_64_C_SOURCES.reject { |rel| File.exist?(File.join(mozjpeg_dir, rel)) }
|
|
203
|
+
message = "image_pack: x86_64 SIMD C sources missing under #{mozjpeg_dir}: #{missing.join(', ')}"
|
|
204
|
+
ENV["IMAGE_PACK_REQUIRE_SIMD"] == "1" ? abort(message) : warn("#{message}. Falling back to scalar.")
|
|
301
205
|
{ kind: :none }
|
|
302
206
|
else
|
|
207
|
+
missing_asm = X86_64_ASM_SOURCES.reject { |rel| File.exist?(File.join(mozjpeg_dir, rel)) }
|
|
208
|
+
unless missing_asm.empty?
|
|
209
|
+
message = "image_pack: x86_64 SIMD ASM sources missing under #{mozjpeg_dir}: #{missing_asm.join(', ')}"
|
|
210
|
+
if ENV["IMAGE_PACK_REQUIRE_SIMD"] == "1"
|
|
211
|
+
abort message
|
|
212
|
+
end
|
|
213
|
+
warn "#{message}. Falling back to scalar."
|
|
214
|
+
return { kind: :none }
|
|
215
|
+
end
|
|
216
|
+
|
|
303
217
|
{
|
|
304
218
|
kind: :x86_64_simd,
|
|
305
219
|
c_sources: X86_64_C_SOURCES,
|
|
306
|
-
asm_sources: X86_64_ASM_SOURCES
|
|
220
|
+
asm_sources: X86_64_ASM_SOURCES,
|
|
307
221
|
extra_includes: [
|
|
308
222
|
File.join(mozjpeg_dir, "simd"),
|
|
309
223
|
File.join(mozjpeg_dir, "simd", "nasm"),
|
|
@@ -363,7 +277,8 @@ def configure_vendored_mozjpeg(vendor_dir)
|
|
|
363
277
|
|
|
364
278
|
abort "vendored MozJPEG sources not found in #{mozjpeg_dir}" unless Dir.exist?(mozjpeg_dir)
|
|
365
279
|
|
|
366
|
-
|
|
280
|
+
required_sources = MOZJPEG_CORE_SOURCES + MOZJPEG_INCLUDE_TEMPLATES
|
|
281
|
+
missing_sources = required_sources.reject { |source| File.exist?(File.join(mozjpeg_dir, source)) }
|
|
367
282
|
abort "vendored MozJPEG sources are incomplete: #{missing_sources.join(', ')}" unless missing_sources.empty?
|
|
368
283
|
|
|
369
284
|
arch = detect_simd_arch
|
|
@@ -489,7 +404,7 @@ $warnflags = ""
|
|
|
489
404
|
|
|
490
405
|
unless msvc?
|
|
491
406
|
$CFLAGS += " -O3 -Wall -Wextra -Wno-unused-parameter -Wno-sign-compare -std=gnu11"
|
|
492
|
-
$CFLAGS += " -fno-math-errno -fno-trapping-math"
|
|
407
|
+
$CFLAGS += " -fno-math-errno -fno-trapping-math -fvisibility=hidden"
|
|
493
408
|
|
|
494
409
|
march = ENV["IMAGE_PACK_MARCH"].to_s
|
|
495
410
|
unless march.empty?
|