diff --git a/third_party/github.com/camlistore/goexif/README.camlistore b/third_party/github.com/camlistore/goexif/README.camlistore new file mode 100644 index 000000000..eb1efc3be --- /dev/null +++ b/third_party/github.com/camlistore/goexif/README.camlistore @@ -0,0 +1,82 @@ +Changing code under third_party/github.com/camlistore/goexif +============================================================ + +These instructions assume you have a github.com account. + +Sync github.com/rwcarlsen/goexif -> github.com/camlistore/goexif +---------------------------------------------------------------- +1. Issue a pull request at https://github.com/camlistore/goexif/pulls, set + the base fork to camlistore/goexif go1 branch, and the head fork as + rwcarlsen/goexif go1 branch. Follow the normal github workflow until + someone on the camlistore project merges in the changes. + +Sync github.com/camlistore/goexif -> camlistore.org/third_party/github.com/camlistore/goexif +-------------------------------------------------------------------------------------------- +1. Once someone on the camlistore team merges in the latest from upstream, + checkout a local copy: + + $ git clone https://github.com/camlistore/goexif + $ cd goexif + +2. Make a patch to apply to the camlistore.org copy. You'll need to know the + git rev of github.com/camlistore/goexif that was last merged to + camlistore.org/third_party, for this example we'll use 030a4566: + + # Create individual patches that have been applied upstream. + $ git format-patch -o /tmp/patches 030a4566 + $ cd /path/to/camlistore.org/third_party/github.com/camlistore/goexif + # Create new branch to temporarily apply each upstream change. + $ git checkout -b patches_individual + # Apply patches. + $ git am --directory=third_party/github.com/camlistore/goexif /tmp/patches/* + + # If something fails to apply try: + $ git apply --reject + $ edit edit edit + $ git add + $ git am --resolved + + # If it is a patch camlistore already had, because we created it and + # pushed it upstream, you can skip it with: + $ git am --skip + + # Now create a new branch to squash all the changes into one. Keeping a + # record of upstream commits in the default commit message of a single + # commit. + $ git checkout -b patches_squashed master + $ git merge --squash patches_individual + + # Verify no new files have been added that require import path updating: + $ cd /path/to/camlistore.org/third_party/ + $ ./rewrite-imports.sh -l + # If any rewrites are required, run: + $ ./rewrite-imports.sh -w + + # Now create a commit that will be sent for review. + $ git commit -v + + # Enter your commit message on the first line per usual. + # You should see summaries of all the changes merged in the commit + # message. Leave these, they will be useful next sync as we'll know what + # commits were sync'd. Send the change for review. + $ ./misc/review + +Sync camlistore.org/third_party/github.com/camlistore/goexif -> github.com/camlistore/goexif +---------------------------------------------------------------------------------------------- +1. TODO(wathiede): this should follow a similar process as 'Sync + github.com/camlistore/goexif -> + camlistore.org/third_party/github.com/camlistore/goexif' Basically use + format-patch to generate a patch for each change we've made in + camlistore.org's repo and apply to a fork of github.com/camlistore/goexif. + Maybe skip the 'merge --squash' step, and keep each change in the log of + github.com/camlistore/goexif. + +Sync github.com/camlistore/goexif -> github.com/rwcarlsen/goexif +-------------------------------------------------------------------- +1. This should follow the standard github pull-request workflow. Issue a + pull request at https://github.com/request/goexif/pulls, set the base fork + to rwcarlsen/goexif go1 branch, and the head fork as camlistore/goexif go1 + branch. + +2. Address any feedback during review and rwcarlsen will merge changes to + github.com/rwcarlsen/goexif as appropriate. diff --git a/third_party/github.com/camlistore/goexif/README.md b/third_party/github.com/camlistore/goexif/README.md index 3b55e5e6c..2694d76ca 100644 --- a/third_party/github.com/camlistore/goexif/README.md +++ b/third_party/github.com/camlistore/goexif/README.md @@ -57,3 +57,4 @@ func main() { ``` +[![githalytics.com alpha](https://cruel-carlota.pagodabox.com/5e166f74cdb82b999ccd84e3c4dc4348 "githalytics.com")](http://githalytics.com/rwcarlsen/goexif) diff --git a/third_party/github.com/camlistore/goexif/exif/exif.go b/third_party/github.com/camlistore/goexif/exif/exif.go index 0c99812e8..ab3722239 100644 --- a/third_party/github.com/camlistore/goexif/exif/exif.go +++ b/third_party/github.com/camlistore/goexif/exif/exif.go @@ -58,15 +58,61 @@ type Exif struct { // Decode parses EXIF-encoded data from r and returns a queryable Exif object. func Decode(r io.Reader) (*Exif, error) { - sec, err := newAppSec(0xE1, r) + // EXIF data in JPEG is stored in the APP1 marker. EXIF data uses the TIFF + // format to store data. + // If we're parsing a TIFF image, we don't need to strip away any data. + // If we're parsing a JPEG image, we need to strip away the JPEG APP1 + // marker and also the EXIF header. + header := make([]byte, 4) + n, err := r.Read(header) + if n < len(header) { + return nil, errors.New("exif: short read on header") + } if err != nil { return nil, err } - er, err := sec.exifReader() - if err != nil { - return nil, err + + var isTiff bool + switch string(header) { + case "II*\x00": + // TIFF - Little endian (Intel) + isTiff = true + case "MM\x00*": + // TIFF - Big endian (Motorola) + isTiff = true + default: + // Not TIFF, assume JPEG } - tif, err := tiff.Decode(er) + + // Put the header bytes back into the reader. + r = io.MultiReader(bytes.NewReader(header), r) + var ( + er *bytes.Reader + tif *tiff.Tiff + ) + + if isTiff { + // Functions below need the IFDs from the TIFF data to be stored in a + // *bytes.Reader. We use TeeReader to get a copy of the bytes as a + // side-effect of tiff.Decode() doing its work. + b := &bytes.Buffer{} + tr := io.TeeReader(r, b) + tif, err = tiff.Decode(tr) + er = bytes.NewReader(b.Bytes()) + } else { + // Strip away JPEG APP1 header. + sec, err := newAppSec(0xE1, r) + if err != nil { + return nil, err + } + // Strip away EXIF header. + er, err = sec.exifReader() + if err != nil { + return nil, err + } + tif, err = tiff.Decode(er) + } + if err != nil { return nil, errors.New("exif: decode failed: " + err.Error()) } diff --git a/third_party/github.com/camlistore/goexif/exif/exif_test.go b/third_party/github.com/camlistore/goexif/exif/exif_test.go index e887bba4a..888020275 100644 --- a/third_party/github.com/camlistore/goexif/exif/exif_test.go +++ b/third_party/github.com/camlistore/goexif/exif/exif_test.go @@ -19,7 +19,7 @@ func TestDecode(t *testing.T) { t.Fatal(err) } if x == nil { - t.Fatal("No error and yet %v was not decoded\n", name) + t.Fatalf("No error and yet %v was not decoded\n", name) } val, err := x.Get("Model") diff --git a/third_party/github.com/camlistore/goexif/tiff/tag.go b/third_party/github.com/camlistore/goexif/tiff/tag.go index d41c2dae0..b2e87f2c6 100644 --- a/third_party/github.com/camlistore/goexif/tiff/tag.go +++ b/third_party/github.com/camlistore/goexif/tiff/tag.go @@ -186,16 +186,16 @@ func (t *Tag) convertVals() { t.ratVals[i] = []int64{int64(n), int64(d)} } case 11: // float32 + t.floatVals = make([]float64, int(t.Ncomp)) for i := 0; i < int(t.Ncomp); i++ { - t.floatVals = make([]float64, int(t.Ncomp)) var v float32 err := binary.Read(r, t.order, &v) panicOn(err) t.floatVals[i] = float64(v) } case 12: // float64 (double) + t.floatVals = make([]float64, int(t.Ncomp)) for i := 0; i < int(t.Ncomp); i++ { - t.floatVals = make([]float64, int(t.Ncomp)) var u float64 err := binary.Read(r, t.order, &u) panicOn(err)