Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion gen/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ func main() {
if err != nil {
return err
}
if info.IsDir() || strings.HasPrefix(info.Name(), ".") {
if info.IsDir() || strings.HasPrefix(info.Name(), ".") || strings.HasSuffix(info.Name(), ".txt") {
return nil
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"width": 6040, "height": 4032}
236 changes: 236 additions & 0 deletions gen/testdata_exiftool/images/bep/jølstravatnet.pef.json

Large diffs are not rendered by default.

20 changes: 0 additions & 20 deletions gen/testdata_exiftool/images/bep/license.txt.json

This file was deleted.

19 changes: 0 additions & 19 deletions gen/testdata_exiftool/images/goexif/license.txt.json

This file was deleted.

19 changes: 0 additions & 19 deletions gen/testdata_exiftool/images/license.txt.json

This file was deleted.

19 changes: 0 additions & 19 deletions gen/testdata_exiftool/images/metadata-extractor/license.txt.json

This file was deleted.

6 changes: 3 additions & 3 deletions gen/testdata_exiftool/images/sample.arw.json
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
[{
"SourceFile": "testdata/images/sample.arw",
"SourceFile": "../testdata/images/sample.arw",
"ExifTool": {
"ExifToolVersion": 13.50
},
"File": {
"FileName": "sample.arw",
"Directory": "testdata/images",
"FileSize": 9601024,
"Directory": "../testdata/images",
"FileSize": 102400,
"FilePermissions": 100644,
"FileType": "ARW",
"FileTypeExtension": "ARW",
Expand Down
6 changes: 3 additions & 3 deletions gen/testdata_exiftool/images/sample.cr2.json
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
[{
"SourceFile": "testdata/images/sample.cr2",
"SourceFile": "../testdata/images/sample.cr2",
"ExifTool": {
"ExifToolVersion": 13.50
},
"File": {
"FileName": "sample.cr2",
"Directory": "testdata/images",
"FileSize": 13287537,
"Directory": "../testdata/images",
"FileSize": 51200,
"FilePermissions": 100644,
"FileType": "CR2",
"FileTypeExtension": "CR2",
Expand Down
6 changes: 3 additions & 3 deletions gen/testdata_exiftool/images/sample.dng.json
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
[{
"SourceFile": "testdata/images/sample.dng",
"SourceFile": "../testdata/images/sample.dng",
"ExifTool": {
"ExifToolVersion": 13.50
},
"File": {
"FileName": "sample.dng",
"Directory": "testdata/images",
"FileSize": 6611520,
"Directory": "../testdata/images",
"FileSize": 51200,
"FilePermissions": 100644,
"FileType": "DNG",
"FileTypeExtension": "DNG",
Expand Down
6 changes: 3 additions & 3 deletions gen/testdata_exiftool/images/sample.nef.json
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
[{
"SourceFile": "testdata/images/sample.nef",
"SourceFile": "../testdata/images/sample.nef",
"ExifTool": {
"ExifToolVersion": 13.50
},
"File": {
"FileName": "sample.nef",
"Directory": "testdata/images",
"FileSize": 4055474,
"Directory": "../testdata/images",
"FileSize": 76800,
"FilePermissions": 100644,
"FileType": "NEF",
"FileTypeExtension": "NEF",
Expand Down
10 changes: 5 additions & 5 deletions imageformat_string.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

11 changes: 7 additions & 4 deletions imagemeta.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ const (
XMP

// CONFIG source, which currently the image dimensions encoded in the image.
// Note that this must not be confused with the dimensions stored in EXIF tags.
// Note that this may not be the same as the dimensions stored in EXIF tags.
CONFIG
)

Expand Down Expand Up @@ -60,6 +60,8 @@ const (
NEF
// ARW is the Sony ARW RAW image format.
ARW
// PEF is the Pentax PEF RAW image format.
PEF
)

// ImageConfig contains basic image configuration.
Expand All @@ -75,7 +77,8 @@ type DecodeResult struct {
ImageConfig ImageConfig
}

// Decode reads EXIF and IPTC metadata from r and returns a Meta struct.
// Decode reads the metadata and passes it to the provided handlers in the options.
// It returns a DecodeResult containing the image configuration if the CONFIG source was requested.
func Decode(opts Options) (result DecodeResult, err error) {
var base *baseStreamingDecoder

Expand Down Expand Up @@ -201,7 +204,7 @@ func Decode(opts Options) (result DecodeResult, err error) {
sourceSet = EXIF | XMP | IPTC | CONFIG
case HEIF, AVIF:
sourceSet = EXIF | XMP | CONFIG
case DNG, CR2, NEF, ARW:
case DNG, CR2, NEF, ARW, PEF:
sourceSet = EXIF | XMP | IPTC | CONFIG
default:
return result, fmt.Errorf("unsupported image format")
Expand Down Expand Up @@ -243,7 +246,7 @@ func Decode(opts Options) (result DecodeResult, err error) {
dec = &imageDecoderPNG{baseStreamingDecoder: base}
case HEIF, AVIF:
dec = &imageDecoderHEIF{baseStreamingDecoder: base}
case DNG, CR2, NEF, ARW:
case DNG, CR2, NEF, ARW, PEF:
dec = &imageDecoderRAW{baseStreamingDecoder: base}
}

Expand Down
10 changes: 10 additions & 0 deletions imagemeta_fuzz_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,16 @@ func FuzzDecodeARW(f *testing.F) {
})
}

func FuzzDecodePEF(f *testing.F) {
filenames := []string{"bep/jølstravatnet.pef"}
for _, filename := range filenames {
f.Add(readTestDataFileAll(f, filename))
}
f.Fuzz(func(t *testing.T, imageBytes []byte) {
fuzzDecodeBytes(t, imageBytes, imagemeta.PEF)
})
}

func fuzzDecodeBytes(t *testing.T, imageBytes []byte, f imagemeta.ImageFormat) error {
r := bytes.NewReader(imageBytes)
_, err := imagemeta.Decode(imagemeta.Options{R: r, ImageFormat: f, Sources: imagemeta.EXIF | imagemeta.IPTC | imagemeta.XMP | imagemeta.CONFIG, Timeout: 600 * time.Millisecond})
Expand Down
21 changes: 16 additions & 5 deletions imagemeta_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,12 @@ func TestDecodeRAW(t *testing.T) {
c.Assert(err, qt.IsNil)
c.Assert(tags.EXIF()["Make"].Value, qt.Equals, "SONY")
c.Assert(tags.EXIF()["Model"].Value, qt.Equals, "DSLR-A330")

// PEF (Pentax K-3 II)
_, tags, err = extractTags(t, "bep/jølstravatnet.pef", imagemeta.EXIF)
c.Assert(err, qt.IsNil)
c.Assert(tags.EXIF()["Make"].Value, qt.Equals, "RICOH IMAGING COMPANY, LTD.")
c.Assert(tags.EXIF()["Model"].Value, qt.Equals, "PENTAX K-3 II")
}

func TestDecodeRAWConfig(t *testing.T) {
Expand All @@ -149,10 +155,11 @@ func TestDecodeRAWConfig(t *testing.T) {
width int
height int
}{
{"sample.dng", imagemeta.DNG, 2592, 1944}, // DefaultCropSize
{"sample.cr2", imagemeta.CR2, 3648, 2736}, // ExifIFD dimensions
{"sample.nef", imagemeta.NEF, 2012, 1324}, // SubIFD dimensions
{"sample.arw", imagemeta.ARW, 3880, 2600}, // ExifIFD dimensions
{"sample.dng", imagemeta.DNG, 2592, 1944}, // DefaultCropSize
{"sample.cr2", imagemeta.CR2, 3648, 2736}, // ExifIFD dimensions
{"sample.nef", imagemeta.NEF, 2012, 1324}, // SubIFD dimensions
{"sample.arw", imagemeta.ARW, 3880, 2600}, // ExifIFD dimensions
{"bep/jølstravatnet.pef", imagemeta.PEF, 6080, 4032}, // IFD0 dimensions
}

for _, tt := range tests {
Expand Down Expand Up @@ -1061,6 +1068,8 @@ func extToFormat(ext string) imagemeta.ImageFormat {
return imagemeta.NEF
case ".arw":
return imagemeta.ARW
case ".pef":
return imagemeta.PEF
case ".txt":
return -1
default:
Expand Down Expand Up @@ -1192,7 +1201,7 @@ func withTestDataFile(t testing.TB, fn func(path string, info os.FileInfo, err e
return err
}

if info.IsDir() || strings.HasPrefix(info.Name(), ".") {
if info.IsDir() || strings.HasPrefix(info.Name(), ".") || strings.HasSuffix(info.Name(), ".txt") {
return nil
}

Expand All @@ -1210,6 +1219,7 @@ var goldenSkip = map[string]bool{
"invalid-encoding-usercomment.jpg": true, // The file has an EXIF error that produces a warning in imagemeta. It's tested separately.
"sample.cr2": true, // CR2 chains 4 IFDs; exiftool reports IFD3 StripByteCounts which we don't reach.
"sample.arw": true, // IFD0 0x0201/0x0202 are preview offsets; exiftool renames to PreviewImageStart/Length so values differ.
"bep/jølstravatnet.pef": true, // GPSProcessingMethod includes encoding prefix; CONFIG dimensions differ (identify uses libraw active area).
}

var isSpaceDelimitedFloatRe = regexp.MustCompile(`^(\d+\.\d+)( \d+\.?\d*)+$`)
Expand Down Expand Up @@ -1431,6 +1441,7 @@ func BenchmarkDecode(b *testing.B) {
{"cr2", imagemeta.CR2, "sample.cr2"},
{"nef", imagemeta.NEF, "sample.nef"},
{"arw", imagemeta.ARW, "sample.arw"},
{"pef", imagemeta.PEF, "bep/jølstravatnet.pef"},
} {
imageFormat = tt.format
runBenchmarkWithFile(b, "exif/"+tt.name, tt.format, tt.filename, func(r io.ReadSeeker) error {
Expand Down
9 changes: 7 additions & 2 deletions metadecoder_exif.go
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,10 @@ var (
"BlackLevelRepeatDim": exifConverters.convertNumbersToSpaceLimited,
"MaskedAreas": exifConverters.convertNumbersToSpaceLimited,
"CFAPattern": func(ctx valueConverterContext, v any) any {
b := v.([]byte)
b, ok := typeAssert[[]byte](ctx, v)
if !ok {
return v
}
horizontalRepeat := ctx.s.byteOrder.Uint16(b[:2])
verticalRepeat := ctx.s.byteOrder.Uint16(b[2:])
repeatLen := int(horizontalRepeat) * int(verticalRepeat)
Expand Down Expand Up @@ -508,7 +511,9 @@ func (e *metaDecoderEXIF) decodeTag(namespace string) error {

if tagName == tagNameThumbnailOffset {
// When set, thumbnailOffset is set to the offset of the EXIF data in the original file.
val = val.(uint32) + uint32(e.readerOffset+e.thumbnailOffset)
if v, ok := typeAssert[uint32](e.valueConverterCtx, val); ok {
val = v + uint32(e.readerOffset+e.thumbnailOffset)
}
}

tagInfo.Value = val
Expand Down
2 changes: 2 additions & 0 deletions testdata/fuzz/FuzzDecodeDNG/85bf2db7be71f22e
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
go test fuzz v1
[]byte("II*\x00\b\x00\x00\x000\x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000i\x87\x04\x00\x01\x00\x00\x00\x84\x02\x00\x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 \x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000\x02\xa3\x05\x00\x01\x00\x00\x00\x01\x04\x00\x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000")
2 changes: 2 additions & 0 deletions testdata/fuzz/FuzzDecodePEF/284853a7f4021859
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
go test fuzz v1
[]byte("II*\x00\b\x00\x00\x000\x00\x01\x02\f\x00\x00\x00\x00\x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000")
Binary file added testdata/images/bep/jølstravatnet.pef
Binary file not shown.