Skip to content

Commit

Permalink
Merge pull request #192 from greut/trim
Browse files Browse the repository at this point in the history
Add the Trim operation
  • Loading branch information
h2non authored Sep 12, 2017
2 parents b35675c + c1f2667 commit 37aea4b
Show file tree
Hide file tree
Showing 8 changed files with 64 additions and 5 deletions.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ If you're using `gopkg.in`, you can still rely in the `v0` without worrying abou

- Resize
- Enlarge
- Crop (including smart crop support)
- Crop (including smart crop support, libvips 8.5+)
- Rotate (with auto-rotate based on EXIF orientation)
- Flip (with auto-flip based on EXIF metadata)
- Flop
Expand All @@ -47,6 +47,7 @@ If you're using `gopkg.in`, you can still rely in the `v0` without worrying abou
- Custom output color space (RGB, grayscale...)
- Format conversion (with additional quality/compression settings)
- EXIF metadata (size, alpha channel, profile, orientation...)
- Trim (libvips 8.6+)

## Prerequisites

Expand Down
Binary file added fixtures/transparent_trim.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 image.go
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,13 @@ func (i *Image) Colourspace(c Interpretation) ([]byte, error) {
return i.Process(options)
}

// Trim removes the background from the picture. It can result in a 0x0 output
// if the image is all background.
func (i *Image) Trim() ([]byte, error) {
options := Options{Trim: true}
return i.Process(options)
}

// Process processes the image based on the given transformation options,
// talking with libvips bindings accordingly and returning the resultant
// image buffer.
Expand Down
24 changes: 22 additions & 2 deletions image_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -457,8 +457,8 @@ func TestFluentInterface(t *testing.T) {

func TestImageSmartCrop(t *testing.T) {

if !(VipsMajorVersion >= 8 && VipsMinorVersion > 4) {
t.Skipf("Skipping this test, libvips doesn't meet version requirement %s > 8.4", VipsVersion)
if !(VipsMajorVersion >= 8 && VipsMinorVersion >= 5) {
t.Skipf("Skipping this test, libvips doesn't meet version requirement %s >= 8.5", VipsVersion)
}

i := initImage("northern_cardinal_bird.jpg")
Expand All @@ -475,6 +475,26 @@ func TestImageSmartCrop(t *testing.T) {
Write("fixtures/test_smart_crop.jpg", buf)
}

func TestImageTrim(t *testing.T) {

if !(VipsMajorVersion >= 8 && VipsMinorVersion >= 6) {
t.Skipf("Skipping this test, libvips doesn't meet version requirement %s >= 8.6", VipsVersion)
}

i := initImage("transparent.png")
buf, err := i.Trim()
if err != nil {
t.Errorf("Cannot process the image: %#v", err)
}

err = assertSize(buf, 250, 208)
if err != nil {
t.Errorf("The image wasn't trimmed.")
}

Write("fixtures/transparent_trim.png", buf)
}

func TestImageLength(t *testing.T) {
i := initImage("test.jpg")

Expand Down
1 change: 1 addition & 0 deletions options.go
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,7 @@ type Options struct {
NoProfile bool
Interlace bool
StripMetadata bool
Trim bool
Extend Extend
Rotate Angle
Background Color
Expand Down
10 changes: 8 additions & 2 deletions resizer.go
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,8 @@ func normalizeOperation(o *Options, inWidth, inHeight int) {

func shouldTransformImage(o Options, inWidth, inHeight int) bool {
return o.Force || (o.Width > 0 && o.Width != inWidth) ||
(o.Height > 0 && o.Height != inHeight) || o.AreaWidth > 0 || o.AreaHeight > 0
(o.Height > 0 && o.Height != inHeight) || o.AreaWidth > 0 || o.AreaHeight > 0 ||
o.Trim
}

func shouldApplyEffects(o Options) bool {
Expand Down Expand Up @@ -268,7 +269,12 @@ func extractOrEmbedImage(image *C.VipsImage, o Options) (*C.VipsImage, error) {
left, top := (o.Width-inWidth)/2, (o.Height-inHeight)/2
image, err = vipsEmbed(image, left, top, o.Width, o.Height, o.Extend, o.Background)
break

case o.Trim:
left, top, width, height, err := vipsTrim(image)
if err == nil {
image, err = vipsExtract(image, left, top, width, height)
}
break
case o.Top != 0 || o.Left != 0 || o.AreaWidth != 0 || o.AreaHeight != 0:
if o.AreaWidth == 0 {
o.AreaHeight = o.Width
Expand Down
16 changes: 16 additions & 0 deletions vips.go
Original file line number Diff line number Diff line change
Expand Up @@ -503,6 +503,22 @@ func vipsSmartCrop(image *C.VipsImage, width, height int) (*C.VipsImage, error)
return buf, nil
}

func vipsTrim(image *C.VipsImage) (int, int, int, int, error) {
defer C.g_object_unref(C.gpointer(image))

top := C.int(0)
left := C.int(0)
width := C.int(0)
height := C.int(0)

err := C.vips_find_trim_bridge(image, &top, &left, &width, &height)
if err != 0 {
return 0, 0, 0, 0, catchVipsError()
}

return int(top), int(left), int(width), int(height), nil
}

func vipsShrinkJpeg(buf []byte, input *C.VipsImage, shrink int) (*C.VipsImage, error) {
var image *C.VipsImage
var ptr = unsafe.Pointer(&buf[0])
Expand Down
8 changes: 8 additions & 0 deletions vips.h
Original file line number Diff line number Diff line change
Expand Up @@ -539,3 +539,11 @@ vips_smartcrop_bridge(VipsImage *in, VipsImage **out, int width, int height) {
return 0;
#endif
}

int vips_find_trim_bridge(VipsImage *in, int *top, int *left, int *width, int *height) {
#if (VIPS_MAJOR_VERSION >= 8 && VIPS_MINOR_VERSION >= 6)
return vips_find_trim(in, top, left, width, height, NULL);
#else
return 0;
#endif
}

0 comments on commit 37aea4b

Please sign in to comment.