Example #1
0
func rescale(im image.Image, opts *DecodeOpts) image.Image {
	mw, mh := opts.MaxWidth, opts.MaxHeight
	mwf, mhf := opts.ScaleWidth, opts.ScaleHeight
	b := im.Bounds()
	// only do downscaling, otherwise just serve the original image
	if !opts.wantRescale(b) {
		return im
	}
	// ScaleWidth and ScaleHeight overrule MaxWidth and MaxHeight
	if mwf > 0.0 && mwf <= 1 {
		mw = int(mwf * float32(b.Dx()))
	}
	if mhf > 0.0 && mhf <= 1 {
		mh = int(mhf * float32(b.Dy()))
	}

	const huge = 2400
	// If it's gigantic, it's more efficient to downsample first
	// and then resize; resizing will smooth out the roughness.
	// (trusting the moustachio guys on that one).
	if b.Dx() > huge || b.Dy() > huge {
		w, h := mw*2, mh*2
		if b.Dx() > b.Dy() {
			w = b.Dx() * h / b.Dy()
		} else {
			h = b.Dy() * w / b.Dx()
		}
		im = resize.Resample(im, b, w, h)
		b = im.Bounds()
	}
	mw, mh = ScaledDimensions(b.Dx(), b.Dy(), mw, mh)
	return resize.Resize(im, b, mw, mh)
}
Example #2
0
func (ih *ImageHandler) scaleImage(buf *bytes.Buffer, file *blobref.BlobRef) (format string, err error) {
	mw, mh := ih.MaxWidth, ih.MaxHeight

	fr, err := schema.NewFileReader(ih.storageSeekFetcher(), file)
	if err != nil {
		return format, err
	}

	_, err = io.Copy(buf, fr)
	if err != nil {
		return format, fmt.Errorf("image resize: error reading image %s: %v", file, err)
	}
	i, format, err := images.Decode(bytes.NewReader(buf.Bytes()), nil)
	if err != nil {
		return format, err
	}
	b := i.Bounds()

	// TODO(mpl): sort the useBytesUnchanged story out,
	// so that a rotation/flip is not being ignored
	// when there was no rescaling required.
	useBytesUnchanged := true

	isSquare := b.Dx() == b.Dy()
	if ih.Square && !isSquare {
		useBytesUnchanged = false
		i = squareImage(i)
		b = i.Bounds()
	}

	// only do downscaling, otherwise just serve the original image
	if mw < b.Dx() || mh < b.Dy() {
		useBytesUnchanged = false

		const huge = 2400
		// If it's gigantic, it's more efficient to downsample first
		// and then resize; resizing will smooth out the roughness.
		// (trusting the moustachio guys on that one).
		if b.Dx() > huge || b.Dy() > huge {
			w, h := mw*2, mh*2
			if b.Dx() > b.Dy() {
				w = b.Dx() * h / b.Dy()
			} else {
				h = b.Dy() * w / b.Dx()
			}
			i = resize.Resample(i, i.Bounds(), w, h)
			b = i.Bounds()
		}
		// conserve proportions. use the smallest of the two as the decisive one.
		if mw > mh {
			mw = b.Dx() * mh / b.Dy()
		} else {
			mh = b.Dy() * mw / b.Dx()
		}
	}

	if !useBytesUnchanged {
		i = resize.Resize(i, b, mw, mh)
		// Encode as a new image
		buf.Reset()
		switch format {
		case "jpeg":
			err = jpeg.Encode(buf, i, nil)
		default:
			err = png.Encode(buf, i)
		}
		if err != nil {
			return format, err
		}
	}
	return format, nil
}