// Set up the drawingwand "dw" for the given font name, font size, and colour. // If the font or size changes sx get the new width of a space // (the magickwand is required if it is necessary to query the font metrics) func draw_setfont(mw *imagick.MagickWand, dw *imagick.DrawingWand, font string, size float64, colour string, sx *float64) { sflag := false if len(font) > 0 { dw.SetFont(font) sflag = true } if len(colour) > 0 { pw := imagick.NewPixelWand() pw.SetColor(colour) dw.SetFillColor(pw) pw.Destroy() sflag = true } if size > 0 { dw.SetFontSize(size) } // If either the font or the fontsize (or both) have changed // we need to get the size of a space again if sflag { fm := mw.QueryFontMetrics(dw, " ") *sx = fm.TextWidth } }
func glitchImage(wand *imagick.MagickWand, q url.Values) ([]byte, error) { data := wand.GetImage().GetImageBlob() jpgHeaderLength := getJpegHeaderSize(data) maxIndex := len(data) - jpgHeaderLength - 4 params := getParams(q) length := int(params["iterations"]) for i := 0; i < length; i++ { pxMin := math.Floor(float64(maxIndex) / params["iterations"] * float64(i)) pxMax := math.Floor(float64(maxIndex) / params["iterations"] * float64((i + 1))) delta := pxMax - pxMin pxI := math.Floor(pxMin + delta*params["seed"]) if int(pxI) > maxIndex { pxI = float64(maxIndex) } index := math.Floor(float64(jpgHeaderLength) + pxI) data[int(index)] = byte(math.Floor(params["amount"] * float64(256))) } wand2 := imagick.NewMagickWand() if err := wand2.ReadImageBlob(data); err != nil { return nil, err } if err := wand2.SetImageFormat("PNG"); err != nil { return nil, err } return wand2.GetImage().GetImageBlob(), nil }
func createChunk(mask, image *imagick.MagickWand, x, y int) error { if err := mask.CompositeImage(image, imagick.COMPOSITE_OP_SRC_IN, -x, -y); err != nil { return err // fmt.Sprintf("Chunking for (%d;%d) failed: %v", x, y, err) } if err := mask.WriteImage("tmp/" + strconv.Itoa(x) + "_" + strconv.Itoa(y) + ".png"); err != nil { return err // fmt.Sprintf("Saving chunk for (%d;%d) failed: %v", x, y, err) } return nil }
func calcDnR(image *imagick.MagickWand) (d uint, r float64) { width := image.GetImageWidth() height := image.GetImageHeight() if height > width { d = width / minChunksPerSide } else { d = height / minChunksPerSide } r = float64(d) / 2 return }
func (orientation *Orientation) Fix(wand *imagick.MagickWand) error { if orientation.fn == nil { return nil } if err := orientation.fn(wand); err != nil { return err } if err := wand.SetImageOrientation(imagick.ORIENTATION_TOP_LEFT); err != nil { return err } *orientation = Orientation{swapXY: false, flipX: false, flipY: false, fn: nil} return nil }
func (i *Image) resize(wand *imagick.MagickWand, w, h uint) { ow := wand.GetImageWidth() oh := wand.GetImageHeight() if (float64(ow) / float64(oh)) < (float64(w) / float64(h)) { h = oh * w / ow } else { w = ow * h / oh } wand.SetImageInterpolateMethod(imagick.INTERPOLATE_PIXEL_BICUBIC) wand.ResizeImage(w, h, imagick.FILTER_LANCZOS2_SHARP, 1) }
func crop(mw *imagick.MagickWand, x, y int, cols, rows uint) error { var result error result = nil imCols := mw.GetImageWidth() imRows := mw.GetImageHeight() if x < 0 { x = 0 } if y < 0 { y = 0 } if uint(x) >= imCols || uint(y) >= imRows { result = fmt.Errorf("x, y more than image cols, rows") return result } if cols == 0 || imCols < uint(x)+cols { cols = imCols - uint(x) } if rows == 0 || imRows < uint(y)+rows { rows = imRows - uint(y) } fmt.Print(fmt.Sprintf("wi_crop(im, %d, %d, %d, %d)\n", x, y, cols, rows)) result = mw.CropImage(cols, rows, x, y) return result }
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 }
// Shrink an image so that its longest dimension is no longer than maxSize func shrinkImage(wand *imagick.MagickWand, maxSize int) (w, h uint) { w, h = getDimensions(wand) shrinkBy := 1 if w >= h { shrinkBy = int(w) / maxSize } else { shrinkBy = int(h) / maxSize } wand.AdaptiveResizeImage( uint(int(w)/shrinkBy), uint(int(h)/shrinkBy), ) // Sharpen the image to bring back some of the color lost in the shrinking wand.AdaptiveSharpenImage(0, AdaptiveSharpenVal) w, h = getDimensions(wand) return }
// The easiest (?) way to handle vertical text placement is // not to use gravity at all because then you know that all the text is // placed relative to ImageMagick's (0,0) coordinate which is the top left of // the screen and the baseline will be y=0. func draw_metrics(mw *imagick.MagickWand, dw *imagick.DrawingWand, dx *float64, dy, sx float64, text string) { mw.AnnotateImage(dw, *dx, dy, 0, text) mw.DrawImage(dw) // get the font metrics fm := mw.QueryFontMetrics(dw, text) if fm != nil { // Adjust the new x coordinate *dx += fm.TextWidth + sx } }
func drawMetrics(mw *imagick.MagickWand, dw *imagick.DrawingWand, dx *float64, text string) { rotation := float64(random(-30, 30)) mw.AnnotateImage(dw, *dx, 35, rotation, text) mw.DrawImage(dw) // get the font metrics fm := mw.QueryFontMetrics(dw, text) if fm != nil { // Adjust the new x coordinate *dx += fm.TextWidth + 2 } }
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 speedLine(mw *imagick.MagickWand, aw *imagick.MagickWand) error { cols, rows := mw.GetImageHeight(), mw.GetImageWidth() dw := imagick.NewDrawingWand() defer dw.Destroy() cw := imagick.NewPixelWand() cw.SetColor(*color) dw.SetFillColor(cw) center := []float64{float64(rows) / 2.0, float64(cols) / 2.0} const radiusCenter float64 = 0.75 const step float64 = 0.02 const bold float64 = 1.0 var theeta float64 for theeta < math.Pi*2 { stepNoise := rand.Float64() + 0.5 theeta += step * stepNoise radiusCenterNoise := rand.Float64()*0.3 + 1.0 boldNoise := rand.Float64() + 0.7 + 0.3 point0 := imagick.PointInfo{ X: math.Sin(theeta)*center[0]*radiusCenter*radiusCenterNoise + center[0], Y: math.Cos(theeta)*center[1]*radiusCenter*radiusCenterNoise + center[1], } point1 := imagick.PointInfo{ X: math.Sin(theeta)*center[0]*2 + center[0], Y: math.Cos(theeta)*center[1]*2 + center[1], } point2 := imagick.PointInfo{ X: math.Sin(theeta+step*bold*boldNoise)*center[0]*2 + center[0], Y: math.Cos(theeta+step*bold*boldNoise)*center[1]*2 + center[1], } dw.Polygon([]imagick.PointInfo{point0, point1, point2}) } if err := aw.DrawImage(dw); err != nil { return err } return nil }
// make-tile creates a tileable image from an input image. // ( +clone -flop ) +append ( +clone -flip ) -append -resize 50% func make_tile(mw *imagick.MagickWand, outfile string) { mwc := mw.Clone() mwc.FlopImage() mw.AddImage(mwc) mwc.Destroy() mwc = mw.AppendImages(false) mwf := mwc.Clone() mwf.FlipImage() mwc.AddImage(mwf) mwf.Destroy() mwf = mwc.AppendImages(true) w := mwf.GetImageWidth() h := mwf.GetImageHeight() // 1 = Don't blur or sharpen image mwf.ResizeImage(w/2, h/2, imagick.FILTER_LANCZOS, 1) mwf.WriteImage(outfile) mwf.Destroy() mwc.Destroy() }
func (i *Image) sizeFrames(sz *imgry.Sizing) error { var canvas *imagick.MagickWand var bg *imagick.PixelWand // Shortcut if there is nothing to size if sz.Size.Equal(imgry.ZeroRect) && sz.CropBox.Equal(imgry.ZeroFloatingRect) { return nil } coalesceAndDeconstruct := !sz.Flatten && i.mw.GetNumberImages() > 1 if coalesceAndDeconstruct { i.mw = i.mw.CoalesceImages() } if sz.Canvas != nil { // If the user requested a canvas. canvas = imagick.NewMagickWand() bg = imagick.NewPixelWand() bg.SetColor("transparent") defer func() { bg.Destroy() if canvas != nil && canvas != i.mw { canvas.Destroy() } }() } i.mw.SetFirstIterator() for n := true; n; n = i.mw.NextImage() { pw, ph := int(i.mw.GetImageWidth()), int(i.mw.GetImageHeight()) srcSize := imgry.NewRect(pw, ph) // Initial crop of the source image cropBox, cropOrigin, err := sz.CalcCropBox(srcSize) if err != nil { return err } if cropBox != nil && cropOrigin != nil && !cropBox.Equal(imgry.ZeroRect) { err := i.mw.CropImage(uint(cropBox.Width), uint(cropBox.Height), cropOrigin.X, cropOrigin.Y) if err != nil { return err } srcSize = cropBox i.mw.ResetImagePage("") } // Resize the image resizeRect, cropBox, cropOrigin := sz.CalcResizeRect(srcSize) if resizeRect != nil && !resizeRect.Equal(imgry.ZeroRect) { err := i.mw.ResizeImage(uint(resizeRect.Width), uint(resizeRect.Height), imagick.FILTER_LANCZOS, 1.0) if err != nil { return err } i.mw.ResetImagePage("") } // Perform any final crops from an operation if cropBox != nil && cropOrigin != nil && !cropBox.Equal(imgry.ZeroRect) { err := i.mw.CropImage(uint(cropBox.Width), uint(cropBox.Height), cropOrigin.X, cropOrigin.Y) if err != nil { return err } i.mw.ResetImagePage("") } // If we have a canvas we put the image at its center. if canvas != nil { canvas.NewImage(uint(sz.Canvas.Width), uint(sz.Canvas.Height), bg) canvas.SetImageBackgroundColor(bg) canvas.SetImageFormat(i.mw.GetImageFormat()) x := (sz.Canvas.Width - int(i.mw.GetImageWidth())) / 2 y := (sz.Canvas.Height - int(i.mw.GetImageHeight())) / 2 canvas.CompositeImage(i.mw, imagick.COMPOSITE_OP_OVER, x, y) canvas.ResetImagePage("") } if sz.Flatten { break } } if canvas != nil { i.mw.Destroy() i.mw = canvas } if coalesceAndDeconstruct { // Compares each frame of the image, removes pixels that are already on the // background and updates offsets accordingly. i.mw = i.mw.DeconstructImages() } return nil }
func proportion(mw *imagick.MagickWand, proportion int, cols uint, rows uint) error { var result error result = nil imCols := mw.GetImageWidth() imRows := mw.GetImageHeight() if proportion == 0 { fmt.Sprintf("p=0, wi_scale(im, %d, %d)\n", cols, rows) result = mw.ResizeImage(cols, rows, imagick.FILTER_UNDEFINED, 1.0) } else if proportion == 1 { if cols == 0 || rows == 0 { if cols > 0 { rows = uint(round(float64((cols / imCols) * imRows))) } else { cols = uint(round(float64((rows / imRows) * imCols))) } fmt.Sprintf("p=1, wi_scale(im, %d, %d)\n", cols, rows) result = mw.ResizeImage(cols, rows, imagick.FILTER_UNDEFINED, 1.0) } else { var x, y, sCols, sRows uint x, y = 0, 0 colsRate := cols / imCols rowsRate := rows / imRows if colsRate > rowsRate { sCols = cols sRows = uint(round(float64(colsRate * imRows))) y = uint(math.Floor(float64((sRows - rows) / 2.0))) } else { sCols = uint(round(float64(rowsRate * imCols))) sRows = rows x = uint(math.Floor(float64((sCols - cols) / 2.0))) } fmt.Sprintf("p=2, wi_scale(im, %d, %d)\n", sCols, sRows) result = mw.ResizeImage(sCols, sRows, imagick.FILTER_UNDEFINED, 1.0) fmt.Sprintf("p=2, wi_crop(im, %d, %d, %d, %d)\n", x, y, cols, rows) result = mw.CropImage(cols, rows, int(x), int(y)) } } else if proportion == 2 { x := int(math.Floor(float64((imCols - cols) / 2.0))) y := int(math.Floor(float64((imRows - rows) / 2.0))) fmt.Sprintf("p=3, wi_crop(im, %d, %d, %d, %d)\n", x, y, cols, rows) result = mw.CropImage(cols, rows, x, y) } else if proportion == 3 { if cols == 0 || rows == 0 { var rate uint if cols > 0 { rate = cols } else { rate = rows } rows = uint(round(float64(imRows * rate / 100))) cols = uint(round(float64(imCols * rate / 100))) fmt.Sprintf("p=3, wi_scale(im, %d, %d)\n", cols, rows) result = mw.ResizeImage(cols, rows, imagick.FILTER_UNDEFINED, 1.0) } else { rows = uint(round(float64(imRows * rows / 100))) cols = uint(round(float64(imCols * cols / 100))) fmt.Sprintf("p=3, wi_scale(im, %d, %d)\n", cols, rows) result = mw.ResizeImage(cols, rows, imagick.FILTER_UNDEFINED, 1.0) } } else if proportion == 4 { var rate float64 rate = 1.0 if cols == 0 || rows == 0 { if cols > 0 { rate = float64(cols / imCols) } else { rate = float64(rows / imRows) } } else { rateCol := cols / imCols rateRow := rows / imRows if rateCol < rateRow { rate = float64(rateCol) } else { rate = float64(rateRow) } } cols = uint(round(float64(float64(imCols) * rate))) rows = uint(round(float64(float64(imRows) * rate))) fmt.Sprintf("p=4, wi_scale(im, %d, %d)\n", cols, rows) result = mw.ResizeImage(cols, rows, imagick.FILTER_UNDEFINED, 1.0) } return result }
func convert(mw *imagick.MagickWand, request *ZRequest) error { fmt.Println("【zscale】:调用convert()方法......处理图片参数") var result error result = nil mw.ResetIterator() mw.SetImageOrientation(imagick.ORIENTATION_TOP_LEFT) x := request.X y := request.Y cols := uint(request.Width) rows := uint(request.Height) fmt.Sprintf("image cols %d, rows %d \n", cols, rows) if !(cols == 0 && rows == 0) { //fmt.Println("call crop&scal function......") /* crop and scale */ if x == -1 && y == -1 { // fmt.Println("call crop&scal function......") // fmt.Print(fmt.Sprintf("proportion(im, %d, %d, %d) \n", request.Proportion, cols, rows)) result = proportion(mw, request.Proportion, cols, rows) if result != nil { return result } } else { // fmt.Print(fmt.Sprintf("crop(im, %d, %d, %d, %d) \n", x, y, cols, rows)) result = crop(mw, x, y, cols, rows) if result != nil { return result } } } /* rotate image */ if request.Rotate != 0 { // fmt.Print(fmt.Sprintf("wi_rotate(im, %d) \n", request.Rotate)) background := imagick.NewPixelWand() if background == nil { result = fmt.Errorf("init new pixelwand faile.") return result } defer background.Destroy() isOk := background.SetColor("#ffffff") if !isOk { result = fmt.Errorf("set background color faile.") return result } result = mw.RotateImage(background, float64(request.Rotate)) if result != nil { return result } } /* set gray */ if request.Gary == 1 { // fmt.Print(fmt.Sprintf("wi_gray(im) \n")) result = mw.SetImageType(imagick.IMAGE_TYPE_GRAYSCALE) if result != nil { return result } } /* set quality */ //fmt.Print(fmt.Sprintf("wi_set_quality(im, %d) \n", request.Quality)) result = mw.SetImageCompressionQuality(uint(request.Quality)) if result != nil { return result } /* set format */ if "none" != request.Format { // fmt.Print(fmt.Sprintf("wi_set_format(im, %s) \n", request.Format)) result = mw.SetImageFormat(request.Format) if result != nil { return result } } //fmt.Print(fmt.Sprintf("convert(im, req) %s \n", result)) return result }
// Returns an the width and height of magick wand func getDimensions(wand *imagick.MagickWand) (w, h uint) { h = wand.GetImageHeight() w = wand.GetImageWidth() return }
func resizeImage(wand *imagick.MagickWand, size int, mozaic bool) *imagick.MagickWand { width := float32(wand.GetImageWidth()) height := float32(wand.GetImageHeight()) var rate float32 if width > height { rate = float32(size) / width } else { rate = float32(size) / height } if mozaic { wand.ResizeImage(uint(width*rate/20), uint(height*rate/20), imagick.FILTER_LANCZOS, 1) wand.ResizeImage(uint(width*rate), uint(height*rate), imagick.FILTER_POINT, 1) } else { wand.ResizeImage(uint(width*rate), uint(height*rate), imagick.FILTER_LANCZOS, 1) } return wand.GetImage() }
func heightToWidthRatio(im *imagick.MagickWand) float64 { return (float64)(im.GetImageHeight()) / (float64)(im.GetImageWidth()) }
func resizeRatio(im *imagick.MagickWand, width, height int) float64 { return math.Abs((float64)(width*height) / (float64)(im.GetImageWidth()*im.GetImageHeight())) }
func tileLineImage(wand *imagick.MagickWand) { it := wand.NewPixelIterator() it.SetLastIteratorRow() width := float32(wand.GetImageWidth()) height := float32(wand.GetImageHeight()) heightRemain := float32(int(height / 20)) if heightRemain != 0 { heightRemain = height/float32(heightRemain) - 20 } widthRemain := float32(int(width / 20)) if widthRemain != 0 { widthRemain = width/float32(widthRemain) - 20 } cnt := it.GetIteratorRow() it.SetFirstIteratorRow() heightCount := 0 nextHeight := 21 hLineCount := 0 hRemainCount := heightRemain widthCount := 0 nextWidth := 21 wLineCount := 0 wRemainCount := widthRemain for i := 0; i <= cnt; i++ { heightCount++ it.SetIteratorRow(i) pws := it.GetCurrentIteratorRow() if nextHeight-heightCount < 2 { for j := 0; j < len(pws); j++ { pws[j].SetColor("#ffffff") } if nextHeight == heightCount { heightCount = 0 hLineCount++ hRemainCount += heightRemain if hRemainCount > 1 { hRemainCount -= 1 nextHeight = 21 } else { nextHeight = 20 } } } else { for j := 0; j < len(pws); j++ { widthCount++ if nextWidth-widthCount < 2 { pws[j].SetColor("#ffffff") if nextWidth == widthCount { widthCount = 0 wLineCount++ wRemainCount += widthRemain if wRemainCount > 1 { wRemainCount -= 1 nextWidth = 21 } else { nextWidth = 20 } } } // if j % 20 < 2 { // pws[j].SetColor("#ffffff") // } } } it.SyncIterator() } }
func (i *Image) Process(wand *imagick.MagickWand, q *Query) { defer wand.Clear() // wand.SetOption("jpeg:size", fmt.Sprintf("%dx%d", q.ResizedWidth, q.ResizedHeight)) bench("wand read", func() { wand.ReadImage(i.Path) }) bench("wand set image format", func() { wand.SetImageFormat("jpeg") }) bench("wand set compress", func() { wand.SetCompression(imagick.COMPRESSION_JPEG2000) }) bench("wand set image quality", func() { wand.SetImageCompressionQuality(95) }) bench("wand resize", func() { i.resize(wand, q.ResizedWidth, q.ResizedHeight) }) bench("wand strip", func() { wand.StripImage() }) i.Blob = wand.GetImageBlob() i.Processed = true }