Skip to content
Open
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
3 changes: 0 additions & 3 deletions v3/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,7 @@ go 1.12
require (
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do not include module changes.

github.com/dsoprea/go-logging v0.0.0-20200710184922-b02d349568dd
github.com/dsoprea/go-utility/v2 v2.0.0-20221003172846-a3e1774ef349
github.com/go-errors/errors v1.4.2 // indirect
github.com/golang/geo v0.0.0-20210211234256-740aa86cb551
github.com/jessevdk/go-flags v1.5.0
golang.org/x/net v0.0.0-20221002022538-bcab6841153b // indirect
golang.org/x/sys v0.0.0-20220928140112-f11e5e49a4ec // indirect
gopkg.in/yaml.v2 v2.4.0
)
6 changes: 6 additions & 0 deletions v3/go.sum
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
github.com/dsoprea/go-exif/v2 v2.0.0-20200321225314-640175a69fe4/go.mod h1:Lm2lMM2zx8p4a34ZemkaUV95AnMl4ZvLbCUbwOvLC2E=
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do not include module changes.

github.com/dsoprea/go-exif/v3 v3.0.0-20200717053412-08f1b6708903/go.mod h1:0nsO1ce0mh5czxGeLo4+OCZ/C6Eo6ZlMWsz7rH/Gxv8=
github.com/dsoprea/go-exif/v3 v3.0.0-20210625224831-a6301f85c82b/go.mod h1:cg5SNYKHMmzxsr9X6ZeLh/nfBRHHp5PngtEPcujONtk=
github.com/dsoprea/go-exif/v3 v3.0.0-20221003160559-cf5cd88aa559/go.mod h1:rW6DMEv25U9zCtE5ukC7ttBRllXj7g7TAHl7tQrT5No=
github.com/dsoprea/go-exif/v3 v3.0.0-20221003171958-de6cb6e380a8/go.mod h1:akyZEJZ/k5bmbC9gA612ZLQkcED8enS9vuTiuAkENr0=
github.com/dsoprea/go-logging v0.0.0-20190624164917-c4f10aab7696/go.mod h1:Nm/x2ZUNRW6Fe5C3LxdY1PyZY5wmDv/s5dkPJ/VB3iA=
github.com/dsoprea/go-logging v0.0.0-20200517223158-a10564966e9d/go.mod h1:7I+3Pe2o/YSU88W0hWlm9S22W7XI1JFNJ86U0zPKMf8=
github.com/dsoprea/go-logging v0.0.0-20200710184922-b02d349568dd h1:l+vLbuxptsC6VQyQsfD7NnEC8BZuFpz45PgY+pH8YTg=
github.com/dsoprea/go-logging v0.0.0-20200710184922-b02d349568dd/go.mod h1:7I+3Pe2o/YSU88W0hWlm9S22W7XI1JFNJ86U0zPKMf8=
github.com/dsoprea/go-utility v0.0.0-20200711062821-fab8125e9bdf h1:/w4QxepU4AHh3AuO6/g8y/YIIHH5+aKP3Bj8sg5cqhU=
github.com/dsoprea/go-utility v0.0.0-20200711062821-fab8125e9bdf/go.mod h1:95+K3z2L0mqsVYd6yveIv1lmtT3tcQQ3dVakPySffW8=
github.com/dsoprea/go-utility/v2 v2.0.0-20200717064901-2fccff4aa15e/go.mod h1:uAzdkPTub5Y9yQwXe8W4m2XuP0tK4a9Q/dantD0+uaU=
github.com/dsoprea/go-utility/v2 v2.0.0-20221003142440-7a1927d49d9d/go.mod h1:LVjRU0RNUuMDqkPTxcALio0LWPFPXxxFCvVGVAwEpFc=
github.com/dsoprea/go-utility/v2 v2.0.0-20221003160719-7bc88537c05e/go.mod h1:VZ7cB0pTjm1ADBWhJUOHESu4ZYy9JN+ZPqjfiW09EPU=
github.com/dsoprea/go-utility/v2 v2.0.0-20221003172846-a3e1774ef349 h1:DilThiXje0z+3UQ5YjYiSRRzVdtamFpvBQXKwMglWqw=
github.com/dsoprea/go-utility/v2 v2.0.0-20221003172846-a3e1774ef349/go.mod h1:4GC5sXji84i/p+irqghpPFZBF8tRN/Q7+700G0/DLe8=
github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q=
Expand Down
81 changes: 81 additions & 0 deletions v3/undefined/exif_C4A5_print_image_matching.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
package exifundefined

import (
"bytes"
"encoding/binary"
"fmt"

log "github.com/dsoprea/go-logging"

exifcommon "github.com/dsoprea/go-exif/v3/common"
)

var PrintImageMatchingHeader = []byte{0x50, 0x72, 0x69, 0x6e, 0x74, 0x49, 0x4d, 0x00}

type TagC4A5PrintImageMatching struct {
Version string
Value []byte
}

func (TagC4A5PrintImageMatching) EncoderName() string {
return "CodecC4A5PrintImageMatching"
}

func (ev TagC4A5PrintImageMatching) String() string {
return fmt.Sprintf("TagC4A5PrintImageMatching<VERSION=(%s) BYTES=(%v)>", ev.Version, ev.Value)
}

type CodecC4A5PrintImageMatching struct{}

func (CodecC4A5PrintImageMatching) Encode(value interface{}, byteOrder binary.ByteOrder) (encoded []byte, unitCount uint32, err error) {
defer func() {
if state := recover(); state != nil {
err = log.Wrap(state.(error))
}
}()

pim, ok := value.(TagC4A5PrintImageMatching)
if !ok {
log.Panicf("can only encode a TagC4A5PrintImageMatching")
}

return pim.Value, uint32(len(pim.Value)), nil
}

func (CodecC4A5PrintImageMatching) Decode(valueContext *exifcommon.ValueContext) (value EncodeableValue, err error) {
// PIM structure explanation: https://www.ozhiker.com/electronics/pjmt/jpeg_info/pim.html Looks like
// there is no sufficient open documentation about this tag:
// https://github.com/Exiv2/exiv2/issues/1419#issuecomment-739723214
// For that reason we are just preserving its raw bytes
defer func() {
if state := recover(); state != nil {
err = log.Wrap(state.(error))
}
}()

ev := TagC4A5PrintImageMatching{}

valueContext.SetUndefinedValueType(exifcommon.TypeByte)
rawBytes, err := valueContext.ReadBytes()
ev.Value = rawBytes
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The documentation describes how to find an entry count and the list of entries. We can parse things better than just yielding an opaque byte slice, yes?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I could not find any decent documentation on PrintIM. It is not specified in the exif 2.2 spec. The only thing I found was the link I posted above and it does not agree with my images. My images have a 106 byte PrintIM. According to the spec this would mean

Header: 8
Version: 5
ExtraNull: 1
EntryCount: 2
Entries: 6*EntryCount

This works out if there are 15 entries. However here is the actual PrintIM bytes of one of my photos:

00000000: 5072 696e 7449 4d00 3033 3030 0000 0300  PrintIM.0300....
00000010: 0200 0100 0000 0300 2200 0000 0101 0000  ........".......
00000020: 0000 0911 0000 1027 0000 0b0f 0000 1027  .......'.......'
00000030: 0000 9705 0000 1027 0000 b008 0000 1027  .......'.......'
00000040: 0000 011c 0000 1027 0000 5e02 0000 1027  .......'..^....'
00000050: 0000 8b00 0000 1027 0000 cb03 0000 1027  .......'.......'
00000060: 0000 e51b 0000 1027 0000 0a              .......'...

Bytes 15-16 are [03 00] which yields 3 entries (order is Little Endian). So it does not work out.

Let's say we ignore the count and treat the remaining bytes as 6 byte entries. Here is what we get:

0200 0100 0000
0300 2200 0000
0101 0000 0000
0911 0000 1027
0000 0b0f 0000
1027 0000 9705
0000 1027 0000

and so on.

If the first 2 bytes of each entry would designate its tag id we have 2 tag ids of [00 00] which does not make much sense as we have a duplication as well as a meaningless tag id.

That's why I gave up and decided I would rather keep the tag opaque rather than parse it incorrectly.


if !bytes.Equal(rawBytes[0:8], PrintImageMatchingHeader[:]) {
log.Panicf("invalid header for tag 0xC4A5 PrintImageMatching")
}

versionLen := bytes.IndexByte(rawBytes[8:], 0)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Validate that versionLen is not -1.

ev.Version = string(rawBytes[8 : 8+versionLen])

return ev, nil
}

func init() {
registerEncoder(
TagC4A5PrintImageMatching{},
CodecC4A5PrintImageMatching{})

registerDecoder(
exifcommon.IfdStandardIfdIdentity.UnindexedString(),
0xc4a5,
CodecC4A5PrintImageMatching{})
}
83 changes: 83 additions & 0 deletions v3/undefined/exif_C4A5_print_image_matching_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
package exifundefined

import (
"bytes"
"reflect"
"testing"

log "github.com/dsoprea/go-logging"
rifs "github.com/dsoprea/go-utility/v2/filesystem"

exifcommon "github.com/dsoprea/go-exif/v3/common"
)

func TestTagC4A5PrintImageMatching_String(t *testing.T) {
ut := TagC4A5PrintImageMatching{
Version: "0300",
Value: []byte{0x01, 0x02, 0x03, 0x04},
}

s := ut.String()

if s != "TagC4A5PrintImageMatching<VERSION=(0300) BYTES=([1 2 3 4])>" {
t.Fatalf("String not correct: [%s]", s)
}
}

func TestCodecC4A5PrintImageMatching_Encode(t *testing.T) {
rawBytes := []byte{
0x50, 0x72, 0x69, 0x6e, 0x74, 0x49, 0x4d, 0x00,
0x30, 0x33, 0x30, 0x30, 0x00,
0x01, 0x02, 0x03, 0x04,
}

ut := TagC4A5PrintImageMatching{
Version: "0300",
Value: rawBytes,
}

codec := CodecC4A5PrintImageMatching{}

encoded, unitCount, err := codec.Encode(ut, exifcommon.TestDefaultByteOrder)
log.PanicIf(err)

if bytes.Equal(encoded, rawBytes) != true {
exifcommon.DumpBytesClause(encoded)

t.Fatalf("Encoded bytes not correct.")
} else if unitCount != 17 {
t.Fatalf("Unit-count not correct: (%d)", unitCount)
}
}

func TestCodecC4A5PrintImageMatching_Decode(t *testing.T) {
rawBytes := []byte{
0x50, 0x72, 0x69, 0x6e, 0x74, 0x49, 0x4d, 0x00,
0x30, 0x33, 0x30, 0x30, 0x00,
0x01, 0x02, 0x03, 0x04,
}

valueContext := exifcommon.NewValueContext(
"",
0,
uint32(len(rawBytes)),
0,
nil,
rifs.NewSeekableBufferWithBytes(rawBytes),
exifcommon.TypeUndefined,
exifcommon.TestDefaultByteOrder)

codec := CodecC4A5PrintImageMatching{}

value, err := codec.Decode(valueContext)
log.PanicIf(err)

expectedValue := TagC4A5PrintImageMatching{
Version: "0300",
Value: rawBytes,
}

if reflect.DeepEqual(value, expectedValue) != true {
t.Fatalf("Decoded value not correct: %s", value)
}
}