Skip to content

Raw support, performance improvements and misc cleanups#62

Merged
bep merged 3 commits into
mainfrom
feat/raw
Feb 26, 2026
Merged

Raw support, performance improvements and misc cleanups#62
bep merged 3 commits into
mainfrom
feat/raw

Conversation

@bep

@bep bep commented Feb 26, 2026

Copy link
Copy Markdown
Owner
  • Fix AVIF decoding iloc/iinf ordering issue
  • Speed up AVIF and TIFF decoding when only config source is requested
  • Group fourCC constants into per-format structs
  • Add DNG, CR2, NEF, and ARW RAW format support
  • Speed up decoding with an buffered and pooled reader
  • Wrap jpeg, tiff and raw markers into structs

tonimelisma and others added 2 commits February 26, 2026 12:10
RAW files are structurally TIFF — the new imageDecoderRAW reuses the
existing EXIF parser with SubIFD following, so all four formats get
EXIF/IPTC/XMP/CONFIG support with minimal new code.

CONFIG dimensions are resolved by scanning IFD0, ExifIFD, and SubIFDs
for the largest image, with DNG DefaultCropSize taking priority.

Implements exiftool-compatible context-dependent tag naming for
strip/thumbnail offset tags (0x0111, 0x0117, 0x0201, 0x0202), which
get different names depending on IFD, format, Compression value, and
SubfileType. This is necessary for all four RAW formats to pass golden
comparison against exiftool output.

Closes #59

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
All sources:

```
goos: darwin
goarch: arm64
pkg: github.com/bep/imagemeta
cpu: Apple M1 Pro
                   │ stash.bench │           feat-raw.bench           │
                   │   sec/op    │   sec/op     vs base               │
Decode/all/png-10    201.7µ ± 1%   154.0µ ± 1%  -23.68% (p=0.002 n=6)
Decode/all/webp-10   368.3µ ± 1%   365.6µ ± 1%   -0.73% (p=0.041 n=6)
Decode/all/jpg-10    374.8µ ± 1%   373.9µ ± 1%        ~ (p=0.485 n=6)
Decode/all/tiff-10   929.1µ ± 1%   793.5µ ± 1%  -14.60% (p=0.002 n=6)
Decode/all/avif-10   403.9µ ± 1%   387.6µ ± 1%   -4.04% (p=0.002 n=6)
Decode/all/dng-10    218.6µ ± 0%   102.0µ ± 0%  -53.32% (p=0.002 n=6)
Decode/all/cr2-10    338.7µ ± 1%   247.5µ ± 1%  -26.94% (p=0.002 n=6)
Decode/all/nef-10    222.5µ ± 1%   118.5µ ± 1%  -46.73% (p=0.002 n=6)
Decode/all/arw-10    256.6µ ± 2%   118.9µ ± 1%  -53.67% (p=0.002 n=6)
geomean              328.2µ        236.4µ       -27.98%

                   │ stash.bench  │           feat-raw.bench           │
                   │     B/op     │     B/op      vs base              │
Decode/all/png-10    47.78Ki ± 0%   47.83Ki ± 0%  +0.10% (p=0.002 n=6)
Decode/all/webp-10   144.1Ki ± 0%   144.1Ki ± 0%  +0.05% (p=0.002 n=6)
Decode/all/jpg-10    145.9Ki ± 0%   145.9Ki ± 0%  +0.06% (p=0.002 n=6)
Decode/all/tiff-10   351.5Ki ± 0%   351.5Ki ± 0%       ~ (p=0.065 n=6)
Decode/all/avif-10   144.5Ki ± 0%   144.6Ki ± 0%  +0.06% (p=0.002 n=6)
Decode/all/dng-10    4.890Ki ± 0%   4.892Ki ± 0%  +0.05% (p=0.002 n=6)
Decode/all/cr2-10    154.2Ki ± 0%   154.2Ki ± 0%  +0.04% (p=0.002 n=6)
Decode/all/nef-10    20.74Ki ± 0%   20.75Ki ± 0%  +0.05% (p=0.002 n=6)
Decode/all/arw-10    7.191Ki ± 0%   7.194Ki ± 0%  +0.04% (p=0.009 n=6)
geomean              56.35Ki        56.38Ki       +0.05%

                   │ stash.bench │           feat-raw.bench            │
                   │  allocs/op  │  allocs/op   vs base                │
Decode/all/png-10     311.0 ± 0%    311.0 ± 0%       ~ (p=1.000 n=6) ¹
Decode/all/webp-10   2.630k ± 0%   2.630k ± 0%       ~ (p=1.000 n=6) ¹
Decode/all/jpg-10    2.703k ± 0%   2.703k ± 0%       ~ (p=1.000 n=6) ¹
Decode/all/tiff-10   2.839k ± 0%   2.840k ± 0%  +0.04% (p=0.002 n=6)
Decode/all/avif-10   2.652k ± 0%   2.652k ± 0%       ~ (p=1.000 n=6) ¹
Decode/all/dng-10     205.0 ± 0%    205.0 ± 0%       ~ (p=1.000 n=6) ¹
Decode/all/cr2-10     143.0 ± 0%    143.0 ± 0%       ~ (p=1.000 n=6) ¹
Decode/all/nef-10     459.0 ± 0%    459.0 ± 0%       ~ (p=1.000 n=6) ¹
Decode/all/arw-10     184.0 ± 0%    184.0 ± 0%       ~ (p=1.000 n=6) ¹
geomean               701.6         701.7       +0.00%
¹ all samples are equal
```

Config only:

```
goos: darwin
goarch: arm64
pkg: github.com/bep/imagemeta
cpu: Apple M1 Pro
                      │ 4aeab38.bench │           feat-raw.bench           │
                      │                     sec/op                     │   sec/op     vs base               │
Decode/config/png-10                                       3.636µ ± 1%   2.267µ ± 2%  -37.65% (p=0.002 n=6)
Decode/config/webp-10                                      3.580µ ± 1%   2.221µ ± 2%  -37.96% (p=0.002 n=6)
Decode/config/jpg-10                                      13.664µ ± 0%   9.447µ ± 1%  -30.86% (p=0.002 n=6)
Decode/config/tiff-10                                      8.300µ ± 2%   3.990µ ± 0%  -51.93% (p=0.002 n=6)
Decode/config/avif-10                                      36.49µ ± 1%   25.61µ ± 0%  -29.83% (p=0.002 n=6)
Decode/config/dng-10                                      136.66µ ± 0%   63.94µ ± 2%  -53.21% (p=0.002 n=6)
Decode/config/cr2-10                                       76.37µ ± 1%   37.61µ ± 1%  -50.75% (p=0.002 n=6)
Decode/config/nef-10                                      123.41µ ± 1%   56.90µ ± 2%  -53.89% (p=0.002 n=6)
Decode/config/arw-10                                      122.03µ ± 0%   58.44µ ± 2%  -52.11% (p=0.002 n=6)
geomean                                                    27.32µ        15.02µ       -45.02%

                      │ 4aeab38.bench │           feat-raw.bench           │
                      │                      B/op                      │    B/op     vs base                │
Decode/config/png-10                                        352.0 ± 0%   352.0 ± 0%       ~ (p=1.000 n=6) ¹
Decode/config/webp-10                                       368.0 ± 0%   368.0 ± 0%       ~ (p=1.000 n=6) ¹
Decode/config/jpg-10                                        352.0 ± 0%   352.0 ± 0%       ~ (p=1.000 n=6) ¹
Decode/config/tiff-10                                       356.0 ± 0%   356.0 ± 0%       ~ (p=1.000 n=6) ¹
Decode/config/avif-10                                       472.0 ± 0%   472.0 ± 0%       ~ (p=1.000 n=6) ¹
Decode/config/dng-10                                        367.0 ± 0%   368.0 ± 0%  +0.27% (p=0.015 n=6)
Decode/config/cr2-10                                        356.0 ± 0%   356.0 ± 0%       ~ (p=1.000 n=6) ¹
Decode/config/nef-10                                        367.0 ± 0%   368.0 ± 0%  +0.27% (p=0.015 n=6)
Decode/config/arw-10                                        367.0 ± 0%   368.0 ± 0%  +0.27% (p=0.002 n=6)
geomean                                                     371.5        371.9       +0.09%
¹ all samples are equal

                      │ 4aeab38.bench │           feat-raw.bench           │
                      │                   allocs/op                    │ allocs/op   vs base                │
Decode/config/png-10                                        8.000 ± 0%   8.000 ± 0%       ~ (p=1.000 n=6) ¹
Decode/config/webp-10                                       9.000 ± 0%   9.000 ± 0%       ~ (p=1.000 n=6) ¹
Decode/config/jpg-10                                        8.000 ± 0%   8.000 ± 0%       ~ (p=1.000 n=6) ¹
Decode/config/tiff-10                                       9.000 ± 0%   9.000 ± 0%       ~ (p=1.000 n=6) ¹
Decode/config/avif-10                                       23.00 ± 0%   23.00 ± 0%       ~ (p=1.000 n=6) ¹
Decode/config/dng-10                                        10.00 ± 0%   10.00 ± 0%       ~ (p=1.000 n=6) ¹
Decode/config/cr2-10                                        9.000 ± 0%   9.000 ± 0%       ~ (p=1.000 n=6) ¹
Decode/config/nef-10                                        10.00 ± 0%   10.00 ± 0%       ~ (p=1.000 n=6) ¹
Decode/config/arw-10                                        10.00 ± 0%   10.00 ± 0%       ~ (p=1.000 n=6) ¹
geomean                                                     10.08        10.08       +0.00%
¹ all samples are equal
````
@codecov-commenter

codecov-commenter commented Feb 26, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 79.05983% with 49 lines in your changes missing coverage. Please review.
✅ Project coverage is 78.39%. Comparing base (69db29f) to head (58d4fb8).
⚠️ Report is 5 commits behind head on main.

Files with missing lines Patch % Lines
imagedecoder_raw.go 77.96% 35 Missing and 4 partials ⚠️
metadecoder_exif.go 64.70% 4 Missing and 2 partials ⚠️
gen/main.go 0.00% 2 Missing ⚠️
imagedecoder_jpg.go 85.71% 0 Missing and 1 partial ⚠️
imagedecoder_tif.go 50.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main      #62      +/-   ##
==========================================
+ Coverage   78.25%   78.39%   +0.13%     
==========================================
  Files          15       16       +1     
  Lines        1890     2101     +211     
==========================================
+ Hits         1479     1647     +168     
- Misses        279      317      +38     
- Partials      132      137       +5     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@bep
bep merged commit c73e1de into main Feb 26, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants