aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexander Rakoczy <[email protected]>2021-11-18 17:12:12 -0500
committerAlexander Rakoczy <[email protected]>2021-11-18 17:12:12 -0500
commit4a6e64b918d7bdb77ee42c5f14ea7663e5802d08 (patch)
treedceda90ab7319eec3a1e610d66a03e1fc8e03cd4
parentcc25b8d9d888fbb524dcc66c22e19fd80e28e004 (diff)
preserve orientation
-rw-r--r--cmd/server/main.go69
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)