) //register the type on init func init() { core.RegisterType("image/jpeg", func() core.Inspecter { return &JpegPhoto{} }) } //This is what dates look like in EXIF tags. const ExifDateFormat = "2006:01:02 15:04:05" //apparently some phones/cameras have a bug which sets some of the exif values //to 2002-12-08 12:00:00 +0000 UTC. //so we need to ensure we ignore that date. var exifDateBug = core.TimeMustParse(time.RFC3339, "2002-12-08T12:00:00Z") //these fields might contain exif date-time strings (in "most-likely-to-be-correct" order) var possibleExifDateTimeFields = []exif.FieldName{exif.DateTimeDigitized, exif.DateTime, exif.DateTimeOriginal} //exif orientation flag type ExifOrientation uint //we define the angles in degrees clockwise. //normal means no transform before rotation //mirror means flip along a vertical axis before //rotation, Undefined should be treated as Normal const ( OrientedUndefined ExifOrientation = iota OrientedNormal //1 OrientedMirror //2
if timescale == 0 { return 0, fmt.Errorf("invalid timescale in mp4") } _, err = f.Read(buff) if err != nil { err = fmt.Errorf("read error: %s", err) return 0, err } durationRaw := binary.BigEndian.Uint32(buff) //real duration is raw/timescale duration = int64((float64(durationRaw) / float64(timescale)) + 0.5) return } //now that is seconds since 1904-01-01 00:00:00 var mp4DateEpoch = core.TimeMustParse(time.RFC3339, "1904-01-01T00:00:00Z") //to find the creation date from the "mvhd" atom, take bytes 5-8 as //a Big Endian uint32, as the number of seconds since // 1904-01-01 00:00:00 (?) func getMp4CreationTimeFromMvhdAtom(f io.ReadSeeker) (time.Time, error) { //now we have it! bytes 5-8 f.Seek(4, 1) buff := make([]byte, 4, 4) _, err := f.Read(buff) if err != nil { err = fmt.Errorf("read error: %s", err) return time.Time{}, err } createdUint := binary.BigEndian.Uint32(buff) //and add our seconds