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) }
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 }