From 8327aae5dbf8c1bdc5309c460b1dbb7803e52bf4 Mon Sep 17 00:00:00 2001 From: Artem Nezvigin Date: Thu, 13 Nov 2014 15:29:38 -0800 Subject: [PATCH 1/2] Add support for image orientation --- halfshell/config.go | 2 ++ halfshell/image_processor.go | 53 +++++++++++++++++++++++++++++++++++- 2 files changed, 54 insertions(+), 1 deletion(-) diff --git a/halfshell/config.go b/halfshell/config.go index c95fbc8..5d5a11b 100644 --- a/halfshell/config.go +++ b/halfshell/config.go @@ -73,6 +73,7 @@ type ProcessorConfig struct { DefaultImageWidth uint64 MaxImageDimensions ImageDimensions MaxBlurRadiusPercentage float64 + AutoOrient bool // DEPRECATED MaintainAspectRatio bool @@ -228,6 +229,7 @@ func (c *configParser) parseProcessorConfig(processorName string) *ProcessorConf DefaultImageWidth: c.uintForKeypath("processors.%s.default_image_width", processorName), MaxImageDimensions: maxDimensions, MaxBlurRadiusPercentage: c.floatForKeypath("processors.%s.max_blur_radius_percentage", processorName), + AutoOrient: c.boolForKeypath("processors.%s.auto_orient", processorName), // DEPRECATED MaintainAspectRatio: c.boolForKeypath("processors.%s.maintain_aspect_ratio", processorName), diff --git a/halfshell/image_processor.go b/halfshell/image_processor.go index 360a1d5..2160600 100644 --- a/halfshell/image_processor.go +++ b/halfshell/image_processor.go @@ -68,7 +68,15 @@ func (ip *imageProcessor) ProcessImage(img *Image, req *ImageProcessorOptions) e req.Dimensions.Height = uint(ip.Config.DefaultImageHeight) } - err := ip.resize(img, req) + var err error + + err = ip.orient(img, req) + if err != nil { + ip.Logger.Errorf("Error orienting image: %s", err) + return err + } + + err = ip.resize(img, req) if err != nil { ip.Logger.Errorf("Error resizing image: %s", err) return err @@ -83,6 +91,49 @@ func (ip *imageProcessor) ProcessImage(img *Image, req *ImageProcessorOptions) e return nil } +func (ip *imageProcessor) orient(img *Image, req *ImageProcessorOptions) error { + if !ip.Config.AutoOrient { + return nil + } + + orientation := img.Wand.GetImageOrientation() + + switch orientation { + case imagick.ORIENTATION_UNDEFINED: + case imagick.ORIENTATION_TOP_LEFT: + return nil + } + + transparent := imagick.NewPixelWand() + defer transparent.Destroy() + transparent.SetColor("none") + + var err error + + switch orientation { + case imagick.ORIENTATION_TOP_RIGHT: + err = img.Wand.FlopImage() + case imagick.ORIENTATION_BOTTOM_RIGHT: + err = img.Wand.RotateImage(transparent, 180) + case imagick.ORIENTATION_BOTTOM_LEFT: + err = img.Wand.FlipImage() + case imagick.ORIENTATION_LEFT_TOP: + err = img.Wand.TransposeImage() + case imagick.ORIENTATION_RIGHT_TOP: + err = img.Wand.RotateImage(transparent, 90) + case imagick.ORIENTATION_RIGHT_BOTTOM: + err = img.Wand.TransverseImage() + case imagick.ORIENTATION_LEFT_BOTTOM: + err = img.Wand.RotateImage(transparent, 270) + } + + if err != nil { + return err + } + + return img.Wand.SetImageOrientation(imagick.ORIENTATION_TOP_LEFT) +} + func (ip *imageProcessor) resize(img *Image, req *ImageProcessorOptions) error { scaleMode := req.ScaleMode if scaleMode == 0 { From c610547f4d42668479d962d075cd3572eb84117e Mon Sep 17 00:00:00 2001 From: Artem Nezvigin Date: Thu, 13 Nov 2014 18:37:26 -0800 Subject: [PATCH 2/2] Add documentation for auto_orient --- README.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/README.md b/README.md index 9326ff1..1aa9499 100644 --- a/README.md +++ b/README.md @@ -216,6 +216,14 @@ For Gaussian blur, the radius used is this value * the image width. This allows you to use a blur parameter (from 0-1) which will apply the same proportion of blurring to each image size. +##### auto_orient + +If set to true, the image processor will respect EXIF rotation data. A common +case are photos taken with a camera (eg: iPhone, digital camera) in landscape +mode. The built-in gyroscope will embed rotation data in the image via EXIF. + +Disabled by default. + ### Routes The `routes` block is a mapping of route patterns to route configuration values.