func (self *TiffData) Uint32() uint32 {
	var v uint32
	switch self.byteorder {
	case "M":  
		v = uint32(self.slice[3]) | uint32(self.slice[2])<<8 |
			uint32(self.slice[1])<<16 | uint32(self.slice[0])<<24
	case "I":  
		v = uint32(self.slice[0]) | uint32(self.slice[1])<<8 |
			uint32(self.slice[2])<<16 | uint32(self.slice[3])<<24
	default:
		log.Fatal(fmt.Sprintf("unrecognised byteorder: %v", self.byteorder))
	}
	return v
}
Uint32 returns 32 bit unsigned integer taking into consideration
the endianness defined
package exif
import (
	"bytes"
	"encoding/binary"
	"errors"
	"fmt"
	"io"
	"log"
	"math/big"
	"os"
	"strings"
)
const EXIF_HEADER_READ_SIZE = 12
const EXIF_SUBIFD_OFFSET_TAG = 0x8769  
const EXIF_GPSINFO_TAG = 0x8825        
const EXIF_IOP_TAG = 0xa005            
var EXIF_HEADER_SIGNATURE = []byte{0xff, 0xd8, 0xff, 0xe1}
var EXIF_TAGS = map[uint16]string{
	0x0100: "ImageWidth",
	0x0101: "ImageLength",
	0x0102: "BitsPerSample",
	0x0103: "Compression",
	0x0106: "PhotometricInterpretation",
	0x0111: "StripOffsets",
	0x0115: "SamplesPerPixel",
	0x0116: "RowsPerStrip",
	0x0117: "StripByteConunts",
	0x010e: "ImageDescription",
	0x010f: "Make",
	0x0110: "Model",
	0x0112: "Orientation",
	0x011a: "XResolution",
	0x011b: "YResolution",
	0x011c: "PlanarConfiguration",
	0x0128: "ResolutionUnit",
	0x0131: "Software",
	0x0132: "DateTime",
	0x013e: "WhitePoint",
	0x013f: "PrimaryChromaticities",
	0x0201: "JpegIFOffset",
	0x0202: "JpegIFByteCount",
	0x0211: "YCbCrCoefficients",
	0x0213: "YCbCrPositioning",
	0x0214: "ReferenceBlackWhite",
	0x8298: "Copyright",
	0x8769: "ExifOffset",
	0x829a: "ExposureTime",
	0x829d: "FNumber",
	0x8822: "ExposureProgram",
	0x8827: "ISOSpeedRatings",
	0x9000: "ExifVersion",
	0x9003: "DateTimeOriginal",
	0x9004: "DateTimeDigitized",
	0x9101: "ComponentConfiguration",
	0x9102: "CompressedBitsPerPixel",
	0x9201: "ShutterSpeedValue",
	0x9202: "ApertureValue",
	0x9203: "BrightnessValue",
	0x9204: "ExposureBiasValue",
	0x9205: "MaxApertureValue",
	0x9206: "SubjectDistance",
	0x9207: "MeteringMode",
	0x9208: "LightSource",
	0x9209: "Flash",
	0x920a: "FocalLength",
	0x927c: "MakerNote",
	0x9286: "UserComment",
	0xa000: "FlashPixVersion",
	0xa001: "ColorSpace",
	0xa002: "ExifImageWidth",
	0xa003: "ExifImageHeight",
	0xa004: "RelatedSoundFile",
	0xa005: "ExifInteroperabilityOffset",
	0xa20e: "FocalPlaneXResolution",
	0xa20f: "FocalPlaneYResolution",
	0xa210: "FocalPlaneResolutionUnit",
	0xa217: "SensingMethod",
	0xa300: "FileSource",
	0xa301: "SceneType",
	0xa401: "CustomRendered",
	0xa402: "ExposureMode",
	0xa403: "WhiteBalance",
	0xa404: "DigitalZoomRatio",
	0xa405: "FocalLengthIn35mmFilm",
	0xa406: "SceneCaptureType",
	0xa407: "GainControl",
	0xa408: "Contrast",
	0xa409: "Saturation",
	0xa40a: "Sharpness",
	0xa40b: "DeviceSettingDescription",
	0xa40c: "SubjectDistanceRange",
	0xa420: "ImageUniqueID",
	0xa430: "CameraOwnerName",
	0xa431: "BodySerialNumber",
	0xa432: "LensSpecification",
	0xa433: "LensMake",
	0xa434: "LensModel",
	0xa435: "LensSerialNumber",
}
var EXIF_GPSINFO_TAGS = map[uint16]string{
	0x0000: "GPSVersionID",
	0x0001: "GPSLatitudeRef",
	0x0002: "GPSLatitude",
	0x0003: "GPSLongitudeRef",
	0x0004: "GPSLongitude",
	0x0005: "GPSAltitudeRef",
	0x0006: "GPSAltitude",
	0x0007: "GPSTimeStamp",
	0x0008: "GPSSatellites",
	0x0009: "GPSStatus",
	0x000a: "GPSMeasureMode",
	0x000b: "GPSDOP",
	0x000c: "GPSSpeedRef",
	0x000d: "GPSSpeed",
	0x000e: "GPSTrackRef",
	0x000f: "GPSTrack",
	0x0010: "GPSImgDirectionRef",
	0x0011: "GPSImgDirection",
	0x0012: "GPSMapDatum",
	0x0013: "GPSDestLatitudeRef",
	0x0014: "GPSDestLatitude",
	0x0015: "GPSDestLongitudeRef",
	0x0016: "GPSDestLongitude",
	0x0017: "GPSDestBearingRef",
	0x0018: "GPSDestBearing",
	0x0019: "GPSDestDistanceRef",
	0x001a: "GPSDestDistance",
	0x001b: "GPSProcessingMethod",
	0x001c: "GPSAreaInformation",
	0x001d: "GPSDateStamp",
	0x001e: "GPSDifferential",
}
var EXIF_IOP_TAGS = map[uint16]string{
	0x0001: "InteroperabilityIndex",
	0x0002: "InteroperabilityVersion",
	0x1000: "RelatedImageFileFormat",
	0x1001: "RelatedImageWidth",
	0x1002: "RelatedImageLength",
}
var IfdSeqMap = map[uint8]string{
	0: "Main",
	1: "Thumbnail",
	2: "SubIFD",
	3: "GPSInfo",
	4: "IOPInfo",
}
var FormatType = map[int]string{
	1:  "UB",  
	2:  "A",   
	3:  "US",  
	4:  "UL",  
	5:  "UR",  
	6:  "SB",  
	7:  "?",   
	8:  "SS",  
	9:  "SL",  
	10: "SR",  
}
type ExifData struct {
	headerLength uint16
	IfdData      map[string][]IfdEntries
}
type TiffData struct {
	byteorder string
	data      []byte
	slice     []byte
}
type IfdEntries struct {
	IfdSeq  uint8
	Tag     uint16
	TagDesc string
	Format  uint16
	Values  interface{}
}
type ExifInterface interface {
	GetExifHeader(r io.Reader) (data []byte, err error)
	ProcessExifStream(f *os.File)
	GetTagValues(tag uint16) (values interface{}, ok bool)
}
type TiffInterface interface {
	SetByteOrder(byteorder string)
	SetData(data []byte)
	GetFirstIFD() uint32
	GetNextIFD(ifdOffset uint32) uint32
	GetIFDList() []uint32
	ProcessIFD(ifdSeq uint8, ifdOffset uint32, tagDict map[uint16]string) []IfdEntries
}
func debug(s string) {
	log.Println(s)
}
func (self *ExifData) GetExifData(r io.Reader) (data []byte, err error) {
	b := make([]byte, EXIF_HEADER_READ_SIZE)
	n, err := r.Read(b)
	if err != nil {
		return nil, err
	}
	if n < EXIF_HEADER_READ_SIZE {
		return nil, errors.New(fmt.Sprintf("Read short of EXIF_HEADER_READ_SIZE > %d\n", n))
	}
	if bytes.Equal(b[0:4], EXIF_HEADER_SIGNATURE) &&
		string(b[6:10]) == "Exif" {
		var length uint16
		buf := bytes.NewBuffer(b[4:6])
		err := binary.Read(buf, binary.BigEndian, &length)
		if err != nil {
			return nil, err
		}
		self.headerLength = length - 8
		data := make([]byte, self.headerLength)
		_, err = r.Read(data)
		if err != nil {
			return nil, err
		}
		return data, nil
	}
	return nil, errors.New("File is not in EXIF complaint format")
}
func (self *TiffData) SetByteOrder(byteorder string) {
	self.byteorder = byteorder
}
func (self *TiffData) SetData(data []byte) {
	self.data = make([]byte, len(data))
	copy(self.data, data)
}
func (self TiffData) GetFirstIFD() uint32 {
	return self.Slice(4, 4).Uint32()
}
func (self TiffData) GetNextIFD(ifdOffset uint32) uint32 {
	ifdEntries := uint32(self.Slice(ifdOffset, 2).Uint16())
	nextIfdOffset := self.Slice(ifdOffset+2+ifdEntries*12, 4).Uint32()
	return nextIfdOffset
}
func (self TiffData) GetIFDList() []uint32 {
	var ifdList []uint32
	ifdOffset := self.GetFirstIFD()
	for ifdOffset != 0 {
		ifdList = append(ifdList, ifdOffset)
		ifdOffset = self.GetNextIFD(ifdOffset)
	}
	return ifdList
}
func (self *TiffData) Slice(offset uint32, length uint32) *TiffData {
	self.slice = make([]byte, length)
	self.slice = self.data[offset : offset+length]
	return self
}
func (self *TiffData) Uint16() uint16 {
	var v uint16
	switch self.byteorder {
	case "M":  
		v = uint16(self.slice[1]) | uint16(self.slice[0])<<8
	case "I":  
		v = uint16(self.slice[0]) | uint16(self.slice[1])<<8
	default:
		log.Fatal(fmt.Sprintf("unrecognised byteorder: %v", self.byteorder))
	}
	return v
}