diff --git a/api_integration_test.go b/api_integration_test.go index b74818a..7d745d6 100644 --- a/api_integration_test.go +++ b/api_integration_test.go @@ -305,6 +305,40 @@ func TestIntegration_CR2(t *testing.T) { {Name: "JPEGInterchangeFormatLength", Value: uint32(13120)}, }, }, + { + Name: "Canon", + ExactTagCount: 28, + Tags: []imxtest.TagExpectation{ + {Name: "CameraSettings"}, + {Name: "FocalLength"}, + {Name: "FlashInfo"}, + {Name: "ShotInfo"}, + {Name: "ImageType", Value: "Canon EOS-1Ds Mark II"}, + {Name: "FirmwareVersion", Value: "Firmware Version 1.0.2"}, + {Name: "OwnerName"}, + {Name: "SerialNumber", Value: uint32(304421)}, + {Name: "CameraInfo"}, + {Name: "CustomFunctions"}, + {Name: "ModelID", Value: uint32(2147484040)}, + {Name: "AFInfo"}, + {Name: "ThumbnailImageValidArea"}, + {Name: "SerialNumberFormat"}, + {Name: "0x0019"}, + {Name: "OriginalDecisionDataOffset"}, + {Name: "PersonalFunctions"}, + {Name: "PersonalFunctionValues"}, + {Name: "CanonFileInfo"}, + {Name: "AFPointsInFocus1D"}, + {Name: "ProcessingInfo"}, + {Name: "MeasuredColor"}, + {Name: "SensorInfo"}, + {Name: "VRDOffset"}, + {Name: "ColorData"}, + {Name: "CRWParam"}, + {Name: "ColorInfo"}, + {Name: "0x4004"}, + }, + }, }) if result.Failed() { for _, err := range result.Errors { diff --git a/internal/parser/tiff/ifd.go b/internal/parser/tiff/ifd.go index e4466c3..dacd81d 100644 --- a/internal/parser/tiff/ifd.go +++ b/internal/parser/tiff/ifd.go @@ -572,6 +572,14 @@ func (p *Parser) handleMakerNote(r *imxbin.Reader, fileReader io.ReaderAt, entry return } + // Always add raw MakerNote tag (for backward compatibility) + *dirTags = append(*dirTags, parser.Tag{ + ID: parser.TagID("ExifIFD:0x927C"), + Name: "MakerNote", + Value: data, + DataType: "UNDEFINED", + }) + // Detect manufacturer and parse // exifBase is 0 for standard TIFF files (TIFF header at file start) // TODO: For JPEG files, this would need to be the APP1 EXIF header offset diff --git a/internal/parser/tiff/tiff.go b/internal/parser/tiff/tiff.go index c89b347..f938426 100644 --- a/internal/parser/tiff/tiff.go +++ b/internal/parser/tiff/tiff.go @@ -10,6 +10,7 @@ import ( "github.com/gomantics/imx/internal/parser/icc" "github.com/gomantics/imx/internal/parser/iptc" "github.com/gomantics/imx/internal/parser/tiff/makernote" + "github.com/gomantics/imx/internal/parser/tiff/makernote/canon" "github.com/gomantics/imx/internal/parser/tiff/makernote/sony" "github.com/gomantics/imx/internal/parser/xmp" ) @@ -44,8 +45,9 @@ type Parser struct { func New() *Parser { registry := makernote.NewRegistry() // Register MakerNote handlers in priority order (most specific first) - // Sony must be registered before Canon (Canon has no header, is fallback) + // Canon must be LAST (no header, validated by IFD structure, is fallback) registry.Register(sony.New()) + registry.Register(canon.New()) return &Parser{ icc: icc.New(),