mirror of
https://github.com/talgo-cloud/bimg.git
synced 2026-03-07 21:48:13 -08:00
Adding trim operation.
Closes #22 Signed-off-by: Yoan Blanc <yoan@dosimple.ch>
This commit is contained in:
parent
b35675c245
commit
c1f2667c0f
8 changed files with 64 additions and 5 deletions
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
BIN
fixtures/transparent_trim.png
Normal file
BIN
fixtures/transparent_trim.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 78 KiB |
7
image.go
7
image.go
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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")
|
||||
|
|
@ -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")
|
||||
|
||||
|
|
|
|||
|
|
@ -205,6 +205,7 @@ type Options struct {
|
|||
NoProfile bool
|
||||
Interlace bool
|
||||
StripMetadata bool
|
||||
Trim bool
|
||||
Extend Extend
|
||||
Rotate Angle
|
||||
Background Color
|
||||
|
|
|
|||
10
resizer.go
10
resizer.go
|
|
@ -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 {
|
||||
|
|
@ -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
|
||||
|
|
|
|||
16
vips.go
16
vips.go
|
|
@ -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])
|
||||
|
|
|
|||
8
vips.h
8
vips.h
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue