diff options
| author | Alexander Rakoczy <[email protected]> | 2021-11-18 17:12:12 -0500 |
|---|---|---|
| committer | Alexander Rakoczy <[email protected]> | 2021-11-18 17:12:12 -0500 |
| commit | 4a6e64b918d7bdb77ee42c5f14ea7663e5802d08 (patch) | |
| tree | dceda90ab7319eec3a1e610d66a03e1fc8e03cd4 | |
| parent | cc25b8d9d888fbb524dcc66c22e19fd80e28e004 (diff) | |
preserve orientation
| -rw-r--r-- | cmd/server/main.go | 69 |
1 files changed, 54 insertions, 15 deletions
diff --git a/cmd/server/main.go b/cmd/server/main.go index f0f7637..41dbce0 100644 --- a/cmd/server/main.go +++ b/cmd/server/main.go @@ -8,6 +8,7 @@ import ( "crypto/sha256" "encoding/base64" "encoding/hex" + "encoding/json" "errors" "flag" "fmt" @@ -113,6 +114,11 @@ const ( const maxUpload = 100 * MiB +type exifTag struct { + SourceFile string + Orientation string +} + func upload(b *storage.BucketHandle) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if r.Method != http.MethodPost { @@ -168,25 +174,18 @@ func upload(b *storage.BucketHandle) http.Handler { tmp.Close() file.Close() r.MultipartForm.RemoveAll() - cmd := exec.Command("exiftool", "-all=", "--icc_profile:all", "-overwrite_original_in_place", tmp.Name()) - var stdOutErr bytes.Buffer - cmd.Stdout = &stdOutErr - cmd.Stderr = &stdOutErr - if err := cmd.Start(); err != nil { - log.Printf("cmd.Start() = %v", err) - http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) - return + or, err := orientation(r.Context(), tmp.Name()) + if err != nil { + log.Printf("orientation(%q) = %v, %v", tmp.Name(), or, err) } - if err := WaitOrStop(r.Context(), cmd, os.Kill, 100*time.Millisecond); err != nil { - log.Printf("WaitOrStop(_, %v, %s) = %v", cmd, 100*time.Millisecond, err) - log.Printf("Output: %s", stdOutErr.String()) + out, err := commandContext(r.Context(), "exiftool", "-all=", "--icc_profile:all", "-overwrite_original_in_place", tmp.Name()) + if err != nil { + log.Printf("commandContext(): %v, %q", err, string(out)) http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) return } - if code := cmd.ProcessState.ExitCode(); code != 0 { - log.Printf("cmd.ProcessState.ExitCode() = %d", code) - http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) - return + if err := setOrientation(r.Context(), tmp.Name(), or); err != nil { + log.Printf("setOrientation(%q) = %v", tmp.Name(), err) } ct := head.Header.Get("content-type") @@ -220,6 +219,46 @@ func upload(b *storage.BucketHandle) http.Handler { }) } +func commandContext(ctx context.Context, name string, arg ...string) ([]byte, error) { + cmd := exec.Command(name, arg...) + var stdOutErr bytes.Buffer + cmd.Stdout = &stdOutErr + cmd.Stderr = &stdOutErr + if err := cmd.Start(); err != nil { + return stdOutErr.Bytes(), fmt.Errorf("cmd.Start() = %w", err) + } + if err := WaitOrStop(ctx, cmd, os.Kill, 100*time.Millisecond); err != nil { + return stdOutErr.Bytes(), fmt.Errorf("WaitOrStop(_, %v, %s) = %w", cmd, 100*time.Millisecond, err) + } + if code := cmd.ProcessState.ExitCode(); code != 0 { + return stdOutErr.Bytes(), fmt.Errorf("cmd.ProcessState.ExitCode() = %d", code) + } + return stdOutErr.Bytes(), nil +} + +func orientation(ctx context.Context, filename string) (string, error) { + o, err := commandContext(ctx, "exiftool", "-j", "-Orientation", filename) + if err != nil { + return "", err + } + var tags []exifTag + if err := json.Unmarshal(o, &tags); err != nil || len(tags) == 0 { + return "", err + } + log.Println(tags) + return tags[0].Orientation, nil +} + +func setOrientation(ctx context.Context, filename string, or string) error { + args := []string{fmt.Sprintf("-Orientation=%s", or), "-overwrite_original_in_place", filename} + out, err := commandContext(ctx, "exiftool", args...) + if err != nil { + log.Printf("setOrientation: %v, %+v, %q", err, args, out) + return err + } + return nil +} + func filename() string { b := make([]byte, 8) n, err := rand.Read(b) |
