1// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
2// See LICENSE.txt for license information.
3
4package imaging
5
6import (
7	"fmt"
8	"image"
9	"io"
10
11	"github.com/disintegration/imaging"
12	"github.com/rwcarlsen/goexif/exif"
13)
14
15const (
16	/*
17	  EXIF Image Orientations
18	  1        2       3      4         5            6           7          8
19
20	  888888  888888      88  88      8888888888  88                  88  8888888888
21	  88          88      88  88      88  88      88  88          88  88      88  88
22	  8888      8888    8888  8888    88          8888888888  8888888888          88
23	  88          88      88  88
24	  88          88  888888  888888
25	*/
26	Upright = iota + 1
27	UprightMirrored
28	UpsideDown
29	UpsideDownMirrored
30	RotatedCWMirrored
31	RotatedCCW
32	RotatedCCWMirrored
33	RotatedCW
34)
35
36// MakeImageUpright changes the orientation of the given image.
37func MakeImageUpright(img image.Image, orientation int) image.Image {
38	switch orientation {
39	case UprightMirrored:
40		return imaging.FlipH(img)
41	case UpsideDown:
42		return imaging.Rotate180(img)
43	case UpsideDownMirrored:
44		return imaging.FlipV(img)
45	case RotatedCWMirrored:
46		return imaging.Transpose(img)
47	case RotatedCCW:
48		return imaging.Rotate270(img)
49	case RotatedCCWMirrored:
50		return imaging.Transverse(img)
51	case RotatedCW:
52		return imaging.Rotate90(img)
53	default:
54		return img
55	}
56}
57
58// GetImageOrientation reads the input data and returns the EXIF encoded
59// image orientation.
60func GetImageOrientation(input io.Reader) (int, error) {
61	exifData, err := exif.Decode(input)
62	if err != nil {
63		return Upright, fmt.Errorf("failed to decode exif data: %w", err)
64	}
65
66	tag, err := exifData.Get("Orientation")
67	if err != nil {
68		return Upright, fmt.Errorf("failed to get orientation field from exif data: %w", err)
69	}
70
71	orientation, err := tag.Int(0)
72	if err != nil {
73		return Upright, fmt.Errorf("failed to get value from exif tag: %w", err)
74	}
75
76	return orientation, nil
77}
78