garyhouston / exif44

Exif44 is a Go library for encoding and decoding Exif metadata in JPEG and TIFF files.
MIT License
4 stars 0 forks source link

[Question] Help with transplanting exif.TIFF into tiff file #2

Open gdunstone opened 6 years ago

gdunstone commented 6 years ago

I feel like I'm really stumbling around in the dark with this.

I am trying to get it so that tiffbytes has valid metadata from a jpeg.

tiffbytes is the bytes for a TIFF file that has no tags, created using golang.org/x/image/tiff Encode()

Can you suggest how I would do this?

type ReadExifHandle struct{
    tiffbytes *bytes.Buffer
}

func (readexif ReadExifHandle)ReadExif(format exif44.FileFormat, imageIdx uint32, exif exif44.Exif, err error) error{
    if err != nil {
        return err
    }

    buf := readexif.tiffbytes.Bytes()
    valid, order, ifdPos := tiff66.GetHeader(buf)
    if !valid {
        fmt.Println("Not a valid tiff file wtf")
        return nil
    }
    root, err := tiff66.GetIFDTree(buf, order, ifdPos, tiff66.TIFFSpace)
    if err != nil{
        return err
    }
    exif.TIFF.Fix()
    exif.TIFF.DeleteEmptyIFDs()

    fileSize := tiff66.HeaderSize + root.TreeSize()
    out := make([]byte, fileSize)

    tiff66.PutHeader(out, order, tiff66.HeaderSize)
    next, err := root.PutIFDTree(out, tiff66.HeaderSize)
    if err != nil {
        return err
    }
    var tiffbytes bytes.Buffer
    tiffwriter := bufio.NewWriter(&tiffbytes)
    tiffwriter.Write(out[:next])
    tiffwriter.Write(buf[:])
    tiffwriter.Flush()

    return nil
}
garyhouston commented 6 years ago

I think it would be possible. The TIFF file may have no metadata, but I don't think it would be correct to say it has no tags, i.e., root.Fields won't be empty, it will contain the tags used to represent the image. On the JPEG side, you've got exif.TIFF.Fields, which are compatible and can be copied to root.Fields, maybe just by calling root.Fields.AddFields(exif.TIFF.Fields).

However, the Exif data is typically stored in multiple IFDs, and that will only take the tags from the top-level. Perhaps you can just do root.SubIFDs = exif.TIFF.SubIFDs, but I'm not really sure without trying it.

gdunstone commented 6 years ago

Its only really the meta data that I'm trying to keep (datetime, lens, exposure etc).

Ill play around with what you suggested with the subifds when Im back at work.

If I get it working I'll submit a pull request witth an example.

garyhouston commented 6 years ago

if you don't need any of the tags in the top IFD then you wouldn't need to copy any of those fields. There are some descriptive things like Make, Model, Software, Artist, Copyright, which are are also TIFF tags.

The tags are listed in section 4.6 in the Exif spec, where section 4.6.5 lists the tags in the Exif (sub) IFD.

garyhouston commented 6 years ago

Copying the []SubIFD slice alone wouldn't be enough, because the parent IFD needs to contain the field that points to the SubIFD. E.g., an ExifIFD field for an Exif sub IFD, or a GPSIFD field for a GPS sub IFD. The data value of the field won't matter because it will be set later when serialising.

The SubIFD struct contains the Tag value of the field that's needed.