func (pr *MagickProcessor) Process(buffer []byte, geo btcdn.GeoBox) (img btcdn.Image, err error) { mw := imagick.NewMagickWand() // Schedule cleanup defer mw.Destroy() err = mw.ReadImageBlob(buffer) if err != nil { return } if geo.Cropped() && geo.Resized() { err = resize(mw, geo) if err != nil { return } err = crop(mw, geo) if err != nil { return } } else if geo.Resized() { err = resize(mw, geo) if err != nil { return } } else if geo.Cropped() { err = crop(mw, geo) if err != nil { return } } if geo.Greyscale() { err = mw.SetColorspace(imagick.COLORSPACE_GRAY) } err = mw.SetImageFormat("jpg") if err != nil { return } err = mw.SetImageCompressionQuality(80) if err != nil { return } err = mw.StripImage() if err != nil { return } newImage := mw.GetImageBlob() img = &Image{ body: newImage, mime: "image/jpeg", } return }
func crop(mw *imagick.MagickWand, geo btcdn.GeoBox) (err error) { offsetX, offsetY, err := calculateGravityOffsets(int(mw.GetImageWidth()), int(mw.GetImageHeight()), geo) if err != nil { return } err = mw.CropImage(uint(geo.Width()), uint(geo.Height()), offsetX, offsetY) if err != nil { return } return }
func (pr *MultiProcessor) Process(buffer []byte, geo btcdn.GeoBox) (img btcdn.Image, err error) { matches := ExtensionExp.FindAllStringSubmatch(geo.Src(), -1) if matches != nil { ext := strings.ToLower(matches[0][1]) if ext == "gif" { img, err = pr.magick.Process(buffer, geo) } else { img, err = pr.bimg.Process(buffer, geo) } } else { img, err = pr.bimg.Process(buffer, geo) } return }
func calculateGravityOffsets(baseWidth int, baseHeight int, geo btcdn.GeoBox) (offsetX int, offsetY int, err error) { cropWidth := geo.Width() cropHeight := geo.Height() if cropWidth > baseWidth { cropWidth = baseWidth } if cropHeight > cropHeight { cropHeight = baseHeight } switch geo.Gravity() { case "": offsetX = geo.Offset()[0] offsetY = geo.Offset()[1] case "c": offsetX = (baseWidth - cropWidth) / 2 offsetY = (baseHeight - cropHeight) / 2 case "n": offsetX = (baseWidth - cropWidth) / 2 offsetY = 0 case "nw": offsetX = 0 offsetY = 0 case "ne": offsetX = baseWidth - cropWidth offsetY = 0 case "s": offsetX = (baseWidth - cropWidth) / 2 offsetY = baseHeight - cropHeight case "sw": offsetX = 0 offsetY = baseHeight - cropHeight case "se": offsetX = baseWidth - cropWidth offsetY = baseHeight - cropHeight case "w": offsetX = 0 offsetY = (baseHeight - cropHeight) / 2 case "e": offsetX = baseWidth - cropWidth offsetY = (baseHeight - cropHeight) / 2 } return }
func resize(mw *imagick.MagickWand, geo btcdn.GeoBox) (err error) { var height uint width := geo.Width() baseWidth := int(mw.GetImageWidth()) if width > baseWidth { width = baseWidth } if geo.Mode() == "!" { height = uint(geo.Height()) } else { ratio := heightToWidthRatio(mw) height = uint((float64)(width) * ratio) } err = mw.ResizeImage(uint(width), height, imagick.FILTER_LANCZOS, 1) if err != nil { return } return }
func (pr *BimgProcessor) Process(buffer []byte, geo btcdn.GeoBox) (img btcdn.Image, err error) { bimgImg := bimg.NewImage(buffer) var newImage []byte gravity := resolveGravity(geo.Gravity()) if geo.Cropped() && geo.Resized() { newImage, err = resizeAndCrop(bimgImg, geo.Width(), geo.Height(), gravity) } else if geo.Resized() { if geo.Mode() == "!" { newImage, err = forceResize(bimgImg, geo.Width(), geo.Height()) } else { newImage, err = resize(bimgImg, geo.Width()) } } else if geo.Cropped() { newImage, err = crop(bimgImg, int(float64(geo.Offset()[1])), int(float64(geo.Offset()[0])), geo.Width(), geo.Height()) } if geo.Greyscale() { newImage, err = bimgImg.Colourspace(bimg.INTERPRETATION_B_W) } img = &Image{ body: newImage, mime: Mimes[bimgImg.Type()], } return }