Esempio n. 1
0
// Create a new blob object from an existing size
func (im *Image) MakeSize(sizing *imgry.Sizing) (*Image, error) {
	defer metrics.MeasureSince([]string{"fn.image.MakeSize"}, time.Now())

	if err := im.ValidateKey(); err != nil {
		return nil, err
	}

	im2 := &Image{
		Key:         im.Key,
		Data:        im.Data,
		SrcUrl:      im.SrcUrl,
		Sizing:      sizing,
		SizingQuery: sizing.ToQuery().Encode(),
	}

	// Clone the originating image
	var err error

	if err = im2.LoadImage(); err != nil {
		return nil, err
	}

	// Resize the new image object
	if err = im2.SizeIt(sizing); err != nil {
		return nil, err
	}

	return im2, nil
}
Esempio n. 2
0
func (i *Image) sizeFrames(sz *imgry.Sizing) error {
	// Shortcut if there is nothing to size
	if sz.Size.Equal(imgry.ZeroRect) && sz.CropBox.Equal(imgry.ZeroFloatingRect) {
		return nil
	}

	// TODO: instead of Coalesce, better to change the offsets.
	// This is required for animated image resizing
	if !sz.Flatten && i.mw.GetNumberImages() > 1 {
		i.mw = i.mw.CoalesceImages()
	}

	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 sz.Flatten {
			break
		}
	}

	return nil
}
Esempio n. 3
0
func (b *Bucket) DbIndexKey(imageKey string, optSizing ...*imgry.Sizing) string {
	var sizing *imgry.Sizing
	if len(optSizing) > 0 { // sizing is optional
		sizing = optSizing[0]
	}
	key := fmt.Sprintf("%s/%s", b.ID, imageKey)
	if sizing != nil {
		key = fmt.Sprintf("%s:q/%s", key, sha1Hash(sizing.ToQuery().Encode()))
	}
	return key
}
Esempio n. 4
0
func (b *Bucket) GetImageSize(key string, sizing *imgry.Sizing) (*Image, error) {
	m := metrics.GetOrRegisterTimer("fn.bucket.GetImageSize", nil)
	defer m.UpdateSince(time.Now())

	// Find the original image
	origIm, err := b.DbFindImage(key, nil)
	if err != nil {
		return nil, err
	}

	// Calculate the sizing ahead of time so our query is updated
	// and we can find it in our db
	sizing.CalcResizeRect(&imgry.Rect{origIm.Width, origIm.Height})
	sizing.Size.Width = sizing.GranularizedWidth()
	sizing.Size.Height = sizing.GranularizedHeight()

	// Find the specific size
	im, err := b.DbFindImage(key, sizing)
	if err != nil && err != ErrImageNotFound {
		return nil, err
	}
	if im != nil { // Got it!
		return im, nil
	}

	// Build a new size from the original
	im2, err := origIm.MakeSize(sizing)
	defer im2.Release()
	if err != nil {
		return nil, err
	}

	err = b.DbSaveImage(im2, sizing)
	return im2, err
}
Esempio n. 5
0
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
}