Skip to content

Commit

Permalink
Adds max scale option to prevent over-sizing
Browse files Browse the repository at this point in the history
  • Loading branch information
davidbyttow committed Apr 3, 2018
1 parent 0749978 commit c4f1dfe
Show file tree
Hide file tree
Showing 5 changed files with 48 additions and 2 deletions.
Binary file added assets/fixtures/tomatoes.TestMaxScale.golden.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/fixtures/tomatoes.TestScale3x.golden.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
7 changes: 7 additions & 0 deletions pkg/vips/bridge.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import "C"
import (
"fmt"
"log"
"math"
"runtime"
dbg "runtime/debug"
"unsafe"
Expand All @@ -14,6 +15,7 @@ import (
const (
defaultQuality = 90
defaultCompression = 6
maxScaleFactor = 10
)

var stringBuffer4096 = fixedString(4096)
Expand Down Expand Up @@ -257,6 +259,11 @@ func vipsFlattenBackground(input *C.VipsImage, color Color) (*C.VipsImage, error
func vipsResize(input *C.VipsImage, scale, vscale float64, kernel Kernel) (*C.VipsImage, error) {
incOpCounter("resize")
var output *C.VipsImage

// Let's not be insane
scale = math.Min(scale, maxScaleFactor)
vscale = math.Min(vscale, maxScaleFactor)

defer C.g_object_unref(C.gpointer(input))
if err := C.resize_image(input, &output, C.double(scale), C.double(vscale), C.int(kernel)); err != 0 {
return nil, handleVipsError()
Expand Down
18 changes: 16 additions & 2 deletions pkg/vips/regression_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,18 @@ func TestRotate(t *testing.T) {
})
}

func TestScale3x(t *testing.T) {
goldenTest(t, "../../assets/fixtures/tomatoes.png", func(tx *vips.Transform) {
tx.Scale(3.0)
})
}

func TestMaxScale(t *testing.T) {
goldenTest(t, "../../assets/fixtures/tomatoes.png", func(tx *vips.Transform) {
tx.MaxScale(1.0).ResizeWidth(100000)
})
}

func TestOverlay(t *testing.T) {
if testing.Short() {
return
Expand Down Expand Up @@ -131,11 +143,13 @@ func assertGoldenMatch(t *testing.T, file string, buf []byte) {
panic("bad filename")
}
name := strings.Replace(t.Name(), "/", "_", -1)
goldenFile := file[:i] + "." + name + ".golden" + file[i:]
prefix := file[:i] + "." + name
ext := file[i:]
goldenFile := prefix + ".golden" + ext
golden, _ := ioutil.ReadFile(goldenFile)
if golden != nil {
if !assert.Equal(t, golden, buf) {
failed := file[:i] + "." + name + ".failed" + file[i:]
failed := prefix + ".failed" + ext
err := ioutil.WriteFile(failed, buf, 0666)
if err != nil {
panic(err)
Expand Down
25 changes: 25 additions & 0 deletions pkg/vips/transform.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ type TransformParams struct {
Height Scalar
CropOffsetX Scalar
CropOffsetY Scalar
MaxScale float64
}

// Transform handles single image transformations
Expand Down Expand Up @@ -234,6 +235,12 @@ func (t *Transform) Scale(scale float64) *Transform {
return t
}

// MaxScale sets the max scale factor that this image can be enlarged or reduced by
func (t *Transform) MaxScale(max float64) *Transform {
t.tx.MaxScale = max
return t
}

// ResizeWidth resizes the image to the given width, maintaining aspect ratio
func (t *Transform) ResizeWidth(width int) *Transform {
t.tx.Width.SetInt(width)
Expand Down Expand Up @@ -387,6 +394,15 @@ func NewBlackboard(image *C.VipsImage, imageType ImageType, p *TransformParams)
bb.targetWidth = p.Width.GetRounded(imageWidth)
bb.targetHeight = p.Height.GetRounded(imageHeight)

if bb.MaxScale > 0 {
if bb.targetWidth > 0 && ratio(bb.targetWidth, imageWidth) > bb.MaxScale {
bb.targetWidth = int(float64(imageWidth) * bb.MaxScale)
}
if bb.targetHeight > 0 && ratio(bb.targetHeight, imageHeight) > bb.MaxScale {
bb.targetHeight = int(float64(imageHeight) * bb.MaxScale)
}
}

switch {
case bb.targetWidth > 0 && bb.targetHeight > 0:
// Nothing to do
Expand All @@ -407,6 +423,11 @@ func NewBlackboard(image *C.VipsImage, imageType ImageType, p *TransformParams)
bb.targetScale = sx
}
}

if bb.MaxScale != 0 && bb.targetScale > bb.MaxScale {
bb.targetScale = bb.MaxScale
}

return bb
}

Expand Down Expand Up @@ -709,6 +730,10 @@ type Scalar struct {
Relative bool
}

func (s *Scalar) IsZero() bool {
return s.Value == 0 && !s.Relative
}

func (s *Scalar) SetInt(value int) {
s.Set(float64(value))
}
Expand Down

0 comments on commit c4f1dfe

Please sign in to comment.