Exemplo n.º 1
0
func Parse(r io.Reader) (eIFD, gIFD, ioIFD tiff.IFD, err error) {
	rars := tiff.NewReadAtReadSeeker(r)
	var two [2]byte
	if _, err = rars.Read(two[:]); err != nil {
		return
	}

	if _, err = rars.Seek(0, 0); err != nil {
		return
	}

	switch string(two[:]) {
	case "MM", "II": // likely a tiff
		var t tiff.TIFF
		if t, err = tiff.Parse(rars, nil, nil); err != nil {
			return
		}
		for _, tIFD := range t.IFDs() {
			if tIFD.HasField(ExifIFDTagID) {
				eFld := tIFD.GetField(ExifIFDTagID)
				offset := eFld.Type().Valuer()(eFld.Value().Bytes(), eFld.Value().Order()).Uint()
				if eIFD, err = tiff.ParseIFD(t.R(), offset, ExifTagSpace, nil); err != nil {
					return
				}
				if tIFD.HasField(GPSIFDTagID) {
					gFld := tIFD.GetField(GPSIFDTagID)
					offset = gFld.Type().Valuer()(gFld.Value().Bytes(), gFld.Value().Order()).Uint()
					if gIFD, err = tiff.ParseIFD(t.R(), offset, GPSTagSpace, nil); err != nil {
						log.Printf("exif: GPS IFD found, but had trouble retrieving it from offset %d: %v\n", offset, err)
					}
				}
				if tIFD.HasField(InteroperabilityIFDTagID) {
					ioFld := tIFD.GetField(InteroperabilityIFDTagID)
					offset = ioFld.Type().Valuer()(ioFld.Value().Bytes(), ioFld.Value().Order()).Uint()
					if ioIFD, err = tiff.ParseIFD(t.R(), offset, IOPTagSpace, nil); err != nil {
						log.Printf("exif: IOP IFD found, but had trouble retrieving it from offset %d: %v\n", offset, err)
					}
				}
				return
			}
		}
		err = fmt.Errorf("exif: no exif ifd found in tiff")
		return
	case "\xff\xd8": // likely a jpeg
		err = fmt.Errorf("exif: still working on jpeg support")
		return
	}
	// Anything else is currently unsupported.
	err = fmt.Errorf("exif: unsupported header: %q", two[:])
	return
}
Exemplo n.º 2
-3
func validateTIFF(t tiff.TIFF) error {
	if len(t.IFDs()) == 0 {
		return fmt.Errorf("tiff/image: no IFDs present in tiff to process")
	}
	if t.IFDs()[0] == nil {
		return fmt.Errorf("tiff/image: IFD 0 is nil")
	}
	if t.IFDs()[0].NumEntries() == 0 || len(t.IFDs()[0].Fields()) == 0 {
		return fmt.Errorf("tiff/image: no entries found in IFD 0")
	}
	return nil
}
Exemplo n.º 3
-5
// For now, findAlternates will only check against two concepts.  One, is the
// "Make" tag and the other checks the presence of tags.
func findAlternateTIFFHandler(t tiff.TIFF) TIFFHandler {
	ifd0 := t.IFDs()[0]
	// Do tag presence check first.  This is useful for identifying
	// tiff files that conform to a certain specification that uses
	// a tag to identify that specification.  For example, tiff/ep
	// uses the "TIFF/EPStandardID" tag (id 37398) to indicate the
	// version number of tiff/ep in use for this tiff file.  DNG has
	// the "DNGVersion" tag (id 50706) for the same.  And Leaf .MOS
	// files do not indicate make/model, but they do have a custom
	// private tag that they use for certain data (tag id 34310).
	// The idea here is that a tiff/ep package or dng package or
	// leaf mos package would be able to better handle processing
	// the tiff than the generic package.
	for _, tagID := range ListRegisteredTagPresenceIDs() {
		if ifd0.HasField(tagID) {
			hndlr := GetHandlerByTagPresence(tagID)
			if hndlr != nil && hndlr.CanHandle(t) {
				return hndlr
			}
		}
	}

	// Check for a specific make next
	// Tag ID 271 is a baseline tag for the "Make" or maker or
	// manufacturer of a device that created this tiff.  The idea
	// here is that a separate manufacturer package may be more
	// directly aware of how to process a specific tiff as opposed
	// to playing guessing games in a generic package.
	if ifd0.HasField(271) {
		f := ifd0.GetField(271)
		maker := string(bytes.TrimRight(f.Value().Bytes(), " \x00"))
		hndlr := GetHandlerByMake(maker)
		if hndlr != nil && hndlr.CanHandle(t) {
			return hndlr
		}
	}
	return nil
}
Exemplo n.º 4
-23
func getDecoder(t tiff.TIFF) (dec Decoder, err error) {
	if err = validateTIFF(t); err != nil {
		return
	}

	// Look for alternates that can handle the whole tiff.
	if handlr := findAlternateTIFFHandler(t); handlr != nil {
		return handlr.Decoder(t)
	}

	// Look for alternates that can handle specific IFDs.
	for _, ifd := range t.IFDs() {
		if handlr := findAlternateIFDHandler(ifd); handlr != nil {
			return handlr.Decoder(ifd, t.R())
		}
	}

	// If no alternates are found...  do our own thing as best we can, which
	// means baseline support only.
	ifd0 := t.IFDs()[0]
	if !new(BaselineHandler).CanHandle(ifd0) {
		return nil, fmt.Errorf("tiff/image: no handlers available for this tiff")
	}
	return new(BaselineHandler).Decoder(ifd0, t.R())
}