diff --git a/halfshell/config.go b/halfshell/config.go index 88467d1..948aec6 100644 --- a/halfshell/config.go +++ b/halfshell/config.go @@ -23,12 +23,17 @@ package halfshell import ( "encoding/json" "fmt" + "net/http" "os" "reflect" "regexp" "strings" ) +type WaterMark struct { + WaterMarkImage *Image +} + // Config is the primary configuration of Halfshell. It contains the server // configuration as well as a list of route configurations. type Config struct { @@ -77,6 +82,7 @@ type ProcessorConfig struct { MaxBlurRadiusPercentage float64 AutoOrient bool Formats map[string]FormatConfig + WaterMark *WaterMark // DEPRECATED MaintainAspectRatio bool @@ -247,6 +253,24 @@ func (c *configParser) parseProcessorConfig(processorName string) *ProcessorConf } } + watermark := new(WaterMark) + + waterMarkUrl := c.stringForKeypath("processors.%s.water_image_url", processorName) + + if waterMarkUrl != "" { + res, err := http.Get(waterMarkUrl) + if err != nil { + panic("Water Mark Image is not accessiable") + } + defer res.Body.Close() + m, err := NewImageFromBuffer(res.Body) + if err != nil { + panic("Water Mark Image is incorrect") + } + + watermark.WaterMarkImage = m + } + config := &ProcessorConfig{ Name: processorName, ImageCompressionQuality: c.uintForKeypath("processors.%s.image_compression_quality", processorName), @@ -257,6 +281,7 @@ func (c *configParser) parseProcessorConfig(processorName string) *ProcessorConf MaxBlurRadiusPercentage: c.floatForKeypath("processors.%s.max_blur_radius_percentage", processorName), AutoOrient: c.boolForKeypath("processors.%s.auto_orient", processorName), Formats: formats, + WaterMark: watermark, // DEPRECATED MaintainAspectRatio: c.boolForKeypath("processors.%s.maintain_aspect_ratio", processorName), diff --git a/halfshell/image_processor.go b/halfshell/image_processor.go index 6d43db4..794bbed 100644 --- a/halfshell/image_processor.go +++ b/halfshell/image_processor.go @@ -89,6 +89,19 @@ func (ip *imageProcessor) ProcessImage(img *Image, req *ImageProcessorOptions) e return err } + err = ip.watermark(img, req) + if err != nil { + ip.Logger.Errorf("Error applying watermark image: %s", err) + return err + } + + return nil +} + +func (ip *imageProcessor) watermark(img *Image, req *ImageProcessorOptions) error { + if ip.Config.WaterMark.WaterMarkImage != nil { + return ip.watermarkApply(img, ip.Config.WaterMark) + } return nil } @@ -310,6 +323,40 @@ func (ip *imageProcessor) blur(image *Image, request *ImageProcessorOptions) err return image.Wand.GaussianBlurImage(blurRadius, blurRadius) } +func (ip *imageProcessor) watermarkApply(img *Image, watermark *WaterMark) error { + imgDimensions := img.GetDimensions() + + if imgDimensions.Width < 100 || imgDimensions.Height < 100 { + return nil + } else { + + waterMarkImage := watermark.WaterMarkImage.Wand.Clone() + + defer waterMarkImage.Clear() + + watermarkDimensions := watermark.WaterMarkImage.GetDimensions() + + resultDimensions := new(ImageDimensions) + resultDimensions.Width = imgDimensions.Width + resultDimensions.Height = imgDimensions.Height + + if imgDimensions.Height < watermarkDimensions.Height || imgDimensions.Width < watermarkDimensions.Width { + err := waterMarkImage.ScaleImage(imgDimensions.Width, imgDimensions.Height) + if err != nil { + return nil + } + resultDimensions.Width = imgDimensions.Width + resultDimensions.Height = imgDimensions.Height + + } + + x := (imgDimensions.Width - resultDimensions.Width) / 2 + y := (imgDimensions.Height - resultDimensions.Height) / 2 + + return img.Wand.CompositeImage(waterMarkImage, watermark.WaterMarkImage.Wand.GetImageCompose(), int(x), int(y)) + } +} + func aspectHeight(aspectRatio float64, width uint) uint { return uint(math.Floor(float64(width)/aspectRatio + 0.5)) } diff --git a/halfshell/route.go b/halfshell/route.go index aff559b..7158a43 100644 --- a/halfshell/route.go +++ b/halfshell/route.go @@ -90,6 +90,5 @@ func (p *Route) SourceAndProcessorOptionsForRequest(r *http.Request) ( Dimensions: ImageDimensions{uint(width), uint(height)}, BlurRadius: blurRadius, ScaleMode: uint(scaleMode), - Focalpoint: NewFocalpointFromString(focalpoint), - } + Focalpoint: NewFocalpointFromString(focalpoint)} } diff --git a/halfshell/source_s3.go b/halfshell/source_s3.go index d95bdeb..b6441b0 100644 --- a/halfshell/source_s3.go +++ b/halfshell/source_s3.go @@ -77,7 +77,7 @@ func (s *S3ImageSource) signedHTTPRequestForRequest(request *ImageSourceOptions) imageURLPathComponents[index] = component } requestURL := &url.URL{ - Opaque: strings.Join(imageURLPathComponents, "/"), + Path: strings.Join(imageURLPathComponents, "/"), Scheme: "http", Host: fmt.Sprintf("%s.s3.amazonaws.com", s.Config.S3Bucket), }