func readOrientation(r io.ReadSeeker) (int, error) { _, err := r.Seek(0, os.SEEK_SET) if err != nil { fmt.Println("Failed to seek to beginning of stream") return 0, err } x, err := exif.Decode(r) if err != nil { fmt.Println("Failed to decode EXIF", err) return 0, err } orientationData, err := x.Get(exif.Orientation) if err != nil { fmt.Println("Failed to read orientation property") return 0, err } orientation, err := orientationData.Int(0) if err != nil { fmt.Println("Failed to decode orientation") return 0, err } return orientation, nil }
func main() { fi, err := ioutil.ReadDir("../../../images/") if err != nil { log.Fatal(err) } for _, v := range fi { f, err := os.Open(v.Name()) if err != nil { log.Fatal(err) } x, err := exif.Decode(f) if err != nil { log.Fatal(err) } tm, _ := x.DateTime() fmt.Println("Taken: ", tm) lat, long, _ := x.LatLong() fmt.Println("lat, long: ", lat, ", ", long) } }
func main() { filepath.Walk("../../../images/", func(path string, info os.FileInfo, err error) error { if info.IsDir() { return nil } f, err := os.Open(path) if err != nil { log.Fatal(err) } x, err := exif.Decode(f) if err != nil { log.Fatal(err) } // Two convenience functions exist for date/time taken and GPS coords: tm, _ := x.DateTime() fmt.Println("Taken: ", tm) lat, long, _ := x.LatLong() fmt.Println("lat, long: ", lat, ", ", long) f.Close() return nil }) }
// Load initializes a Photograph from a file. func (p *Photograph) Load(fileName string) error { p.OriginalFileName = fileName fd, err := os.Open(fileName) if err != nil { logging.Log.Error("%v", err) return err } defer fd.Close() exif.RegisterParsers(mknote.All...) exifData, err := exif.Decode(fd) if err != nil { logging.Log.Error("%v", err) return err } err = exifData.Walk(p) if err != nil { logging.Log.Error("%v", err) return err } offset, err := fd.Seek(0, 0) if err != nil { logging.Log.Error("%v", err) return err } logging.Log.Debug("offset=%v", offset) p.Data, err = ioutil.ReadAll(fd) if err != nil { logging.Log.Error("%v", err) return err } return nil }
// ReadRAF makes a new RAF from a file func ReadRAF(fname string) *RAF { raf := new(RAF) f, err := os.Open(fname) defer f.Close() if err == nil { err = binary.Read(f, binary.BigEndian, &raf.Header) } jbuf := make([]byte, raf.Header.Dir.Jpeg.Len) f.ReadAt(jbuf, int64(raf.Header.Dir.Jpeg.IDX)) raf.Jpeg = jbuf // Soon. // exif.RegisterParsers(mknote.Fuji) buf := bytes.NewBuffer(jbuf) raf.Exif, err = exif.Decode(buf) if err != nil { panic(err) } return raf }
func getDateFromExif(file string) (error, time.Time) { f, err := os.Open(file) defer f.Close() if err != nil { return errors.New("pclassify: warning: read exif info failed"), time.Now() } x, err := exif.Decode(f) if err != nil { return errors.New("pclassify: warning: read exif info failed"), time.Now() } ts, err := x.Get(exif.DateTimeOriginal) if err != nil { return errors.New("pclassify: warning: read exif info failed"), time.Now() } const layout = "2006:01:02 15:04:05" t, err := time.ParseInLocation(layout, ts.StringVal(), time.Local) if err != nil { return errors.New("pclassify: warning: read exif info failed"), time.Now() } return nil, t }
func orient(r io.Reader, i image.Image) (image.Image, error) { t := log.Start() defer log.End(t) e, err := exif.Decode(r) if err != nil { log.Printf("fail to decode exif: %v", err) return nil, err } tag, err := e.Get(exif.Orientation) // Orientationタグが存在しない場合、処理を完了する if err != nil { log.Println("oritentation tag doesn't exist") return nil, err } o, err := tag.Int(0) if err != nil { log.Println("oritentation tag is't int") return nil, err } rect := i.Bounds() // orientation=5~8 なら画像サイズの縦横を入れ替える if o >= 5 && o <= 8 { rect = RotateRect(rect) } d := image.NewRGBA64(rect) a := affines[o] a.TransformCenter(d, i, interp.Bilinear) return d, nil }
// getDateTime reads the exif data from fname and returns a string representation // of the DateTimeOriginal tag. // TODO move to its own package? func getDateTime(fname string) (time.Time, error) { f, err := os.Open(fname) if err != nil { return time.Now(), err } defer f.Close() x, err := exif.Decode(f) if err != nil { return time.Now(), err } date, err := x.Get(exif.DateTimeOriginal) if err != nil { return time.Now(), err } dateStr, err := date.StringVal() if err != nil { return time.Now(), nil } log.Println("Setting DateTimeOriginal to ", dateStr, " on ", fname) t, err := time.Parse("2006:01:02 15:04:05", dateStr) if err != nil { return time.Now(), err } return t, nil }
func main() { ImageFileName := flag.String("image", "", "Dont use pngs please.") flag.Parse() var R io.Reader if len(*ImageFileName) > 0 { Rrr, err := os.Open(*ImageFileName) if err != nil { fmt.Fprintf(os.Stderr, "%s\n", "Cant open file.") } R = Rrr } if len(*ImageFileName) == 0 { R = os.Stdin } ExifData, err := exif.Decode(R) if err == io.EOF { fmt.Fprintf(os.Stderr, "%s\n", "Error decoding file.") } if err != io.EOF { Location, err := goexifgps.DecodeGPS(ExifData) if err != io.EOF { fmt.Println(Location) } if err == io.EOF { fmt.Fprintf(os.Stderr, "%s\n", "Contains no GPS exif data.") } } }
func main() { fname := "01.jpg" f, err := os.Open(fname) if err != nil { log.Fatal(err) } // Optionally register camera makenote data parsing - currently Nikon and // Canon are supported. exif.RegisterParsers(mknote.All...) x, err := exif.Decode(f) if err != nil { log.Fatal(err) } camModel, _ := x.Get(exif.Model) // normally, don't ignore errors! fmt.Println(camModel.StringVal()) focal, _ := x.Get(exif.FocalLength) numer, denom, _ := focal.Rat2(0) // retrieve first (only) rat. value fmt.Printf("%v/%v", numer, denom) // Two convenience functions exist for date/time taken and GPS coords: tm, _ := x.DateTime() fmt.Println("Taken: ", tm) lat, long, _ := x.LatLong() fmt.Println("lat, long: ", lat, ", ", long) }
func main() { path := "../../../images/" fi, err := ioutil.ReadDir(path) if err != nil { log.Fatal(err) } for _, v := range fi { fmt.Println(v.Name()) } for _, v := range fi { fmt.Println(v.Sys()) } for _, v := range fi { f, err := os.Open(path + v.Name()) if err != nil { log.Fatal(err) } x, err := exif.Decode(f) if err != nil { log.Fatal(err) } // Two convenience functions exist for date/time taken and GPS coords: tm, _ := x.DateTime() fmt.Println("Taken: ", tm) lat, long, _ := x.LatLong() fmt.Println("lat, long: ", lat, ", ", long) } }
func createPhoto(sourceFilename string) (util.Photo, error) { photo := util.Photo{} f, err := os.Open(imageSourceFolderPath + sourceFilename) if err != nil { log.Println(err) return photo, err } x, err := exif.Decode(f) if err != nil { log.Println(sourceFilename, err) return photo, err } tm, _ := x.DateTime() if false { log.Println("Taken: ", tm) } albumTime := time.Date(tm.Year(), tm.Month(), tm.Day(), 0, 0, 0, 0, time.UTC) photo.AlbumDateTime = int(albumTime.Unix()) photo.DateTime = int(tm.Unix()) photo.Filename = sourceFilename return photo, nil }
// Our programs starts executing here func main() { // We need exactly 2 parameters: the first one is the program name, // the second one should be the photo we want to operate on if len(os.Args) != 2 { fmt.Println("Please give a single file name as an argument!") os.Exit(1) } // Retrieve the photo file name from the arguments array fileName := os.Args[1] // Try to opern the given file, error out on failure file, err := os.Open(fileName) exitOnError(err, "Couldn't open file") // Try to extract the EXIF data, error out on failure exifData, err := exif.Decode(file) exitOnError(err, "Couldn't find EXIF data") // Try to find a GPS coordinates entry in the EXIF data structure. // Error out on failure lat, long, err := exifData.LatLong() exitOnError(err, "Couldn't read GPS coordinates") // Create the final URL by using the Google Maps URL template url := fmt.Sprintf(googleMapsURLTemplate, lat, long) // Try to start the default browser for the current OS. // Show the computer URL on error, so that the user can still // access it manually err = open.Start(url) exitOnError(err, fmt.Sprintf( "Couldn't start the default browser, please visit %v manually", url)) }
func main() { filepath.Walk("../../../images/", func(path string, info os.FileInfo, err error) error { if info.IsDir() { return nil } fmt.Println(path) f, err := os.Open(path) if err != nil { log.Fatal(err) } defer f.Close() // Optionally register camera makenote data parsing - currently Nikon and // Canon are supported. exif.RegisterParsers(mknote.All...) x, err := exif.Decode(f) if err != nil { log.Fatal(err) } // Two convenience functions exist for date/time taken and GPS coords: tm, _ := x.DateTime() fmt.Println("Taken: ", tm) lat, long, _ := x.LatLong() fmt.Println("lat, long: ", lat, ", ", long) return nil }) }
func (f *File) ParseExif() error { fpath := filepath.Join(f.TagDir, f.Filename) if f.Tempfile != "" { fpath = f.Tempfile } fp, err := os.Open(fpath) defer fp.Close() if err != nil { return err } f.Exif, err = exif.Decode(fp) if err != nil { return err } f.DateTime, err = f.Exif.DateTime() if err != nil { /// XXX: Log } else { f.DateTimeReadable = humanize.Time(f.DateTime) } f.Latitude, f.Longitude, err = f.Exif.LatLong() if err != nil { /// XXX: Log } return nil }
func imageMeta(r io.ReadSeeker) (*Image, error) { conf, err := jpeg.DecodeConfig(r) if err != nil { return nil, fmt.Errorf("cannot decode JPEG: %s", err) } // compute image hash from image content oid := sha256.New() if _, err := io.Copy(oid, r); err != nil { return nil, fmt.Errorf("cannot compute SHA: %s", err) } img := Image{ ImageID: encode(oid), Width: conf.Width, Height: conf.Height, } if _, err := r.Seek(0, os.SEEK_SET); err != nil { return nil, fmt.Errorf("cannot seek: %s", err) } if meta, err := exif.Decode(r); err != nil { log.Error("cannot extract EXIF metadata", "error", err.Error()) } else { if orientation, err := meta.Get(exif.Orientation); err != nil { log.Debug("cannot extract image orientation", "decoder", "EXIF", "error", err.Error()) } else { if o, err := orientation.Int(0); err != nil { log.Debug("cannot format orientation", "decoder", "EXIF", "error", err.Error()) } else { img.Orientation = o } } if dt, err := meta.Get(exif.DateTimeOriginal); err != nil { log.Debug("cannot extract image datetime original", "decoder", "EXIF", "error", err.Error()) } else { if raw, err := dt.StringVal(); err != nil { log.Debug("cannot format datetime original", "decoder", "EXIF", "error", err.Error()) } else { img.Created, err = time.Parse("2006:01:02 15:04:05", raw) if err != nil { log.Debug("cannot parse datetime original", "decoder", "EXIF", "value", raw, "error", err.Error()) } } } } return &img, nil }
// processExif attempts to rotate a JPEG based on the exif data. If the exif data // cannot be decoded or the orientation tag not read, we return nil so that the image // may continue to be uploaded. If there is an error encoding the image after // modification, this is returned to the caller. func (f *FileMetadataType) processExif() error { // Decode exif. ex, err := exif.Decode(bytes.NewReader(f.Content)) if err != nil { return nil } // Get orientation tag. tag, err := ex.Get(exif.Orientation) if err != nil { return nil } orientation, err := tag.Int(0) if err != nil { return nil } var ( angle int flipMode exifutil.FlipDirection switchDimensions bool ) angle, flipMode, switchDimensions = exifutil.ProcessOrientation(int64(orientation)) im, _, err := image.Decode(bytes.NewReader(f.Content)) if err != nil { return err } if angle != 0 { im = exifutil.Rotate(im, angle) } if flipMode != 0 { im = exifutil.Flip(im, flipMode) } if switchDimensions { f.Width, f.Height = f.Height, f.Width } // Encode JPEG and replace f.Content. buf := new(bytes.Buffer) err = jpeg.Encode(buf, im, nil) if err != nil { return err } f.Content = buf.Bytes() // Update the hash and filesize based on changed content. sha1, err := h.SHA1(f.Content) if err != nil { return err } f.FileHash = sha1 f.FileSize = int32(len(f.Content)) return nil }
func rename(filename string, prefix string, suffix string, datetimeFormat string, counterLength int, dryrun bool) (result int, err error) { if !exists(filename) { result = 1 err = os.ErrNotExist return } f, err := os.Open(filename) if err != nil { result = 1 return } e, err := exif.Decode(f) if err != nil { result = 1 return } t, err := e.DateTime() if err != nil { if !exif.IsTagNotPresentError(err) { result = 1 return } /* Exifから撮影時刻が取得できない場合 => ファイルの更新時刻を使用 */ info, _ := os.Stat(filename) t = info.ModTime() err = nil } datetime := t.Format(datetimeFormat) ext := filepath.Ext(filename) for i := 0; ; i++ { counter := fmt.Sprintf(fmt.Sprintf("_%%0%dd", counterLength), i) n := datetime + counter + ext if !exists(n) { newname := prefix + datetime + counter + suffix + ext log.Print("[RENAME] ", filename, " => ", newname) if !dryrun { err := os.Rename(filename, newname) if err != nil { log.Fatal(err) } } break } } result = 0 return }
func ProcessImage(currentUser m.User, file io.ReadCloser, imageWaitGroup *sync.WaitGroup, closeReader bool) error { if closeReader { defer file.Close() } outputPath := "../uploads/" + currentUser.Username + "/" + base64.StdEncoding.EncodeToString([]byte(currentUser.Username+time.Now().String())) if err := os.MkdirAll("../uploads/"+currentUser.Username+"/", 0777); err != nil { log.Error("Error in creating output dir " + err.Error()) return errors.New("Failed to upload the image.") } outputFile, err := os.Create(outputPath) if err != nil { log.Error("Error in creating output file, process image " + err.Error()) return errors.New("Failed to upload the image.") } defer outputFile.Close() if _, err = io.Copy(outputFile, file); err != nil { log.Error("Error in copying file " + err.Error()) os.Remove(outputPath) return errors.New("Failed to upload the image.") } var lat, long string var date time.Time openedFile, err := os.Open(outputPath) if err != nil { log.Error("Error opening file in image upload " + err.Error()) } defer openedFile.Close() if exifParser, _ := exif.Decode(openedFile); exifParser == nil { lat = "" long = "" date = time.Now() } else { lat = "" long = "" date, err = exifParser.DateTime() if err != nil { log.Error("Error in exif parser date: " + err.Error()) date = time.Now() } } image := m.Image{bson.NewObjectId(), currentUser.Id, outputPath, lat, long, date, time.Now(), 1, "", true, bson.NewObjectId(), "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", false} if err = m.GetDB("Image").Insert(&image); err != nil { log.Error("Error in saving image file to db " + err.Error()) return errors.New("Failed to upload the image.") } LinkImageToGps(image, imageWaitGroup) return nil }
func processEXIFMeta(src, dest string) (interface{}, error) { f, err := os.Open(src) if err != nil { return nil, err } defer f.Close() return exif.Decode(f) }
func (m *fileMover) decode(path string, ptype PhotoType) error { // Attempt to open the file for reading. f, err := os.Open(path) if err != nil { return err } defer f.Close() // First, stat the file. stat, err := f.Stat() if err != nil { return err } t := stat.ModTime() // Next, read the exif data. x, err := exif.Decode(f) if err != nil { return err } // Try and read exif field names instead of just the filename. for _, v := range []exif.FieldName{"DateTimeOriginal", "DateTimeDigitized", "DateTime"} { tag, err := x.Get(v) if err != nil { continue } val, err := tag.StringVal() if err != nil { continue } tm, err := time.Parse(form, val) if err != nil { continue } t = tm break } // Generate the output folder name folder := t.Format(folder_format) if ptype == kRaw { folder = folder + "_RAW" } else if ptype == kMov { folder = folder + "_MOV" } dest := filepath.Join(m.destPath, folder, filepath.Base(path)) if exists(dest) { return nil } m.queue <- moveEntry{path, dest} return nil }
func LoadImageFile(file string, image *store.Item) error { fi, err := os.Open(file) if err != nil { log.Printf("Error: %s\n", err.Error()) return err } defer fi.Close() found_time := false var image_time time.Time ex, err := exif.Decode(bufio.NewReader(fi)) if err == nil { dto, err := tagTime(ex, exif.DateTimeOriginal) if err == nil { image_time = dto found_time = true } if !found_time { dtd, err := tagTime(ex, exif.DateTimeDigitized) if err == nil { log.Printf("Using DateTimeDigitized for: %s (%s)\n", file, dtd) image_time = dtd found_time = true } } if !found_time { dt, err := tagTime(ex, exif.DateTime) if err == nil { log.Printf("Using DateTime for: %s (%s)\n", file, dt) image_time = dt found_time = true } } } if !found_time { log.Printf("Using file time for: %s\n", file) image_time = ProtoToTime(*image.FileTimestamp) } its := TimeToProto(image_time) image.ItemTimestamp = &its height, width, kwds, err := getImageInfo(file) if err == nil { if kwds != nil && len(kwds) > 0 { image.Keywords = kwds } image.Image = new(store.Image) image.Image.Height = proto.Int32(int32(height)) image.Image.Width = proto.Int32(int32(width)) } else { log.Printf("Info got error %s: %s", file, err.Error()) } return nil }
// FileTime returns the best guess of the file's creation time (or modtime). // If the file doesn't have its own metadata indication the creation time (such as in EXIF), // FileTime uses the modification time from the file system. // It there was a valid EXIF but an error while trying to get a date from it, // it logs the error and tries the other methods. func FileTime(f io.ReaderAt) (time.Time, error) { var ct time.Time defaultTime := func() (time.Time, error) { if osf, ok := f.(*os.File); ok { fi, err := osf.Stat() if err != nil { return ct, fmt.Errorf("Failed to find a modtime: stat: %v", err) } return fi.ModTime(), nil } return ct, errors.New("All methods failed to find a creation time or modtime.") } size, ok := findSize(f) if !ok { size = 256 << 10 // enough to get the EXIF } r := io.NewSectionReader(f, 0, size) var tiffErr error ex, err := exif.Decode(r) if err != nil { tiffErr = err if exif.IsShortReadTagValueError(err) { return ct, io.ErrUnexpectedEOF } if exif.IsCriticalError(err) || exif.IsExifError(err) { return defaultTime() } } ct, err = ex.DateTime() if err != nil { return defaultTime() } // If the EXIF file only had local timezone, but it did have // GPS, then lookup the timezone and correct the time. if ct.Location() == time.Local { if exif.IsGPSError(tiffErr) { log.Printf("Invalid EXIF GPS data: %v", tiffErr) return ct, nil } if lat, long, err := ex.LatLong(); err == nil { if loc := lookupLocation(latlong.LookupZoneName(lat, long)); loc != nil { if t, err := exifDateTimeInLocation(ex, loc); err == nil { return t, nil } } } else if !exif.IsTagNotPresentError(err) { log.Printf("Invalid EXIF GPS data: %v", err) } } return ct, nil }
func getTimestamp(f *os.File) (rts time.Time, rerr error) { if _, err := f.Seek(0, 0); err != nil { return rts, err } x, err := exif.Decode(f) if err == nil { if ts, ierr := x.DateTime(); ierr == nil { return ts, nil } } return rts, errors.New("Unable to find ts") }
// getFolderDestination simply open the current file ang get the metadata of creation to create the path year/month/day func getFolderDestination(fname string) string { f, err := os.Open(fname) defer f.Close() manageErrors(err) x, err := exif.Decode(f) manageErrors(err) t, err := x.DateTime() manageErrors(err) return RootPath + string(os.PathSeparator) + t.Format("2006") + string(os.PathSeparator) + t.Format("01") + string(os.PathSeparator) + t.Format("02") }
//Opens using filename and does exif.Decode // filename will be known if it is passed as flag via commandline. func OpenClose(filename string) (*exif.Exif, error) { f, err := os.Open(filename) if err != nil { return nil, err } ExifData, err2 := exif.Decode(f) f.Close() if err2 != nil { return nil, err2 } return ExifData, nil }
func home(res http.ResponseWriter, req *http.Request) { type Photo struct { PhotoPath string Lat float64 Long float64 } var model struct { Photos []Photo LoggedIn bool } session, _ := store.Get(req, "session-name") _, model.LoggedIn = session.Values["loggedin"] filepath.Walk("assets/imgs", func(path string, info os.FileInfo, err error) error { if !info.IsDir() { fmt.Println("WALKING", path) var currentPhoto Photo currentPhoto.PhotoPath = path f, err := os.Open(path) if err != nil { log.Fatal(err) } exif.RegisterParsers(mknote.All...) x, err := exif.Decode(f) if err != nil { log.Println("no info") return nil } currentPhoto.Lat, currentPhoto.Long, _ = x.LatLong() fmt.Println("lat, long: ", currentPhoto.Lat, ", ", currentPhoto.Long) model.Photos = append(model.Photos, currentPhoto) } return nil }) err := tpl.ExecuteTemplate(res, "index.gohtml", model) if err != nil { http.Error(res, err.Error(), 500) } }
func (i *ImageObj) getTags() (*exif.Exif, error) { fp, err := os.Open(i.filename) if err != nil { // Issue opening the file return nil, err } tags, err := exif.Decode(fp) if err != nil { return nil, err } return tags, nil }
func main() { flag.Parse() root := flag.Arg(0) f, err := os.Open(root) if err != nil { fmt.Printf("%v\n", err) } defer f.Close() x, err := exif.Decode(f) if err != nil { fmt.Printf("%v\n", err) } if x == nil { fmt.Printf("%v\n", err) } b, err := x.MarshalJSON() if err != nil { fmt.Printf("%v\n", err) } fmt.Printf("%s\n", b) date, _ := x.Get("DateTimeOriginal") fmt.Printf("\nDateTimeOriginal %s\n", date.StringVal()) /* artist, _ := x.Get("Artist") fmt.Printf("Artist %s\n", artist.StringVal()) */ expo, _ := x.Get("ExposureTime") n, d := expo.Rat2(0) fmt.Printf("ExposureTime %v/%v\n", n, d) fnumber, _ := x.Get("FNumber") n1, d1 := fnumber.Rat2(0) fmt.Printf("FNumber %v/%v\n", n1, d1) focal, _ := x.Get("FocalLength") n2, d2 := focal.Rat2(0) fmt.Printf("FocalLength %v/%v\n", n2, d2) iso, _ := x.Get("ISOSpeedRatings") if iso != nil { n3 := iso.Int(0) fmt.Printf("iso %v\n", n3) } }
func NewGeoPhotoFromFile(path string) (GeoPhoto, error) { file, err := os.Open(path) if err != nil { return GeoPhoto{}, err } defer file.Close() exifData, err := exif.Decode(file) if err != nil { return GeoPhoto{}, err } return NewGeoPhotoFromExif(exifData), nil }