From e83c80c93ce7c0ef0b3255af4e621e491ce51f78 Mon Sep 17 00:00:00 2001 From: Clement DAL PALU Date: Mon, 28 Sep 2015 17:33:38 -0700 Subject: [PATCH 1/2] - Adding a Background option when flattening out a transparent PNG --- image_test.go | 13 +++++++++++++ options.go | 1 + resize.go | 9 +++++++++ vips.go | 10 ++++++++++ vips.h | 9 +++++++++ 5 files changed, 42 insertions(+) diff --git a/image_test.go b/image_test.go index fb20c62..e396857 100644 --- a/image_test.go +++ b/image_test.go @@ -246,6 +246,19 @@ func TestImageConvert(t *testing.T) { Write("fixtures/test_image_convert_out.png", buf) } +func TestTransparentImageConvert(t *testing.T) { + image := initImage("transparent.png") + options := Options{ + Type: JPEG, + Background: Color{255, 255, 255}, + } + buf, err := image.Process(options) + if err != nil { + t.Errorf("Cannot process the image: %#v", err) + } + Write("fixtures/test_transparent_image_convert_out.jpg", buf) +} + func TestImageMetadata(t *testing.T) { data, err := initImage("test.png").Metadata() if err != nil { diff --git a/options.go b/options.go index 9526914..0e7d2e4 100644 --- a/options.go +++ b/options.go @@ -123,4 +123,5 @@ type Options struct { Interpolator Interpolator Interpretation Interpretation GaussianBlur GaussianBlur + Background Color } diff --git a/resize.go b/resize.go index e234841..0ca1479 100644 --- a/resize.go +++ b/resize.go @@ -102,6 +102,15 @@ func Resize(buf []byte, o Options) ([]byte, error) { return nil, err } + // Flatten image on a background, if necessary + black := Color{0, 0, 0} + if imageType == PNG && o.Background != black { + image, err = vipsFlatten(image, o.Background) + if err != nil { + return nil, err + } + } + saveOptions := vipsSaveOptions{ Quality: o.Quality, Type: o.Type, diff --git a/vips.go b/vips.go index 9fcbc5b..8454231 100644 --- a/vips.go +++ b/vips.go @@ -252,6 +252,16 @@ func vipsInterpretation(image *C.VipsImage) Interpretation { return Interpretation(C.vips_image_guess_interpretation_bridge(image)) } +func vipsFlatten(image *C.VipsImage, background Color) (*C.VipsImage, error) { + var outImage *C.VipsImage + backgroundC := [3]C.double{C.double(background.R), C.double(background.G), C.double(background.B)} + err := int(C.vips_flatten_image(image, &outImage, (*C.double)(&backgroundC[0]))) + if err != 0 { + return nil, catchVipsError() + } + return outImage, nil +} + func vipsPreSave(image *C.VipsImage, o *vipsSaveOptions) (*C.VipsImage, error) { // Remove ICC profile metadata if o.NoProfile { diff --git a/vips.h b/vips.h index 0a52b39..4f75627 100644 --- a/vips.h +++ b/vips.h @@ -226,6 +226,15 @@ vips_webpsave_bridge(VipsImage *in, void **buf, size_t *len, int strip, int qual ); } +int +vips_flatten_image(VipsImage *in, VipsImage **out, double background[3]) { + VipsArrayDouble *vipsBackground = vips_array_double_new(background, 3); + return vips_flatten(in, out, + "background", vipsBackground, + NULL + ); +} + int vips_init_image (void *buf, size_t len, int imageType, VipsImage **out) { int code = 1; From 174de89a409cad1ddeecf9c0a0cc4790f0235213 Mon Sep 17 00:00:00 2001 From: Tomas Aparicio Date: Tue, 29 Sep 2015 08:45:02 +0100 Subject: [PATCH 2/2] refactor(#55): minor changes, use proper declarations, unref image --- image.go | 10 +++++----- options.go | 7 ++++++- resize.go | 18 ++++++++++++------ vips.go | 24 +++++++++++++++++------- vips.h | 2 +- 5 files changed, 41 insertions(+), 20 deletions(-) diff --git a/image.go b/image.go index fa02dd3..2836787 100644 --- a/image.go +++ b/image.go @@ -4,6 +4,11 @@ type Image struct { buffer []byte } +// Creates a new image +func NewImage(buf []byte) *Image { + return &Image{buf} +} + // Resize the image to fixed width and height func (i *Image) Resize(width, height int) ([]byte, error) { options := Options{ @@ -190,8 +195,3 @@ func (i *Image) Size() (ImageSize, error) { func (i *Image) Image() []byte { return i.buffer } - -// Creates a new image -func NewImage(buf []byte) *Image { - return &Image{buf} -} diff --git a/options.go b/options.go index 0e7d2e4..8dcc2a9 100644 --- a/options.go +++ b/options.go @@ -80,6 +80,10 @@ type Color struct { R, G, B uint8 } +// Shortcut to black RGB color representation +var ColorBlack = Color{0, 0, 0} + +// Text-based watermark configuration type Watermark struct { Width int DPI int @@ -96,6 +100,7 @@ type GaussianBlur struct { MinAmpl float64 } +// Supported image transformation options type Options struct { Height int Width int @@ -117,11 +122,11 @@ type Options struct { NoProfile bool Interlace bool Rotate Angle + Background Color Gravity Gravity Watermark Watermark Type ImageType Interpolator Interpolator Interpretation Interpretation GaussianBlur GaussianBlur - Background Color } diff --git a/resize.go b/resize.go index 0ca1479..87600c2 100644 --- a/resize.go +++ b/resize.go @@ -103,12 +103,9 @@ func Resize(buf []byte, o Options) ([]byte, error) { } // Flatten image on a background, if necessary - black := Color{0, 0, 0} - if imageType == PNG && o.Background != black { - image, err = vipsFlatten(image, o.Background) - if err != nil { - return nil, err - } + image, err = imageFlatten(image, imageType, o) + if err != nil { + return nil, err } saveOptions := vipsSaveOptions{ @@ -312,6 +309,15 @@ func watermakImage(image *C.VipsImage, w Watermark) (*C.VipsImage, error) { return image, nil } +func imageFlatten(image *C.VipsImage, imageType ImageType, o Options) (*C.VipsImage, error) { + // Only PNG images are supported for now + if imageType != PNG || o.Background == ColorBlack { + return image, nil + } + + return vipsFlattenBackground(image, o.Background) +} + func zoomImage(image *C.VipsImage, zoom int) (*C.VipsImage, error) { if zoom == 0 { return image, nil diff --git a/vips.go b/vips.go index 8454231..f30eb09 100644 --- a/vips.go +++ b/vips.go @@ -252,14 +252,24 @@ func vipsInterpretation(image *C.VipsImage) Interpretation { return Interpretation(C.vips_image_guess_interpretation_bridge(image)) } -func vipsFlatten(image *C.VipsImage, background Color) (*C.VipsImage, error) { +func vipsFlattenBackground(image *C.VipsImage, background Color) (*C.VipsImage, error) { var outImage *C.VipsImage - backgroundC := [3]C.double{C.double(background.R), C.double(background.G), C.double(background.B)} - err := int(C.vips_flatten_image(image, &outImage, (*C.double)(&backgroundC[0]))) - if err != 0 { + + backgroundC := [3]C.double{ + C.double(background.R), + C.double(background.G), + C.double(background.B), + } + + err := C.vips_flatten_background_brigde(image, &outImage, (*C.double)(&backgroundC[0])) + if int(err) != 0 { return nil, catchVipsError() } - return outImage, nil + + C.g_object_unref(C.gpointer(image)) + image = outImage + + return image, nil } func vipsPreSave(image *C.VipsImage, o *vipsSaveOptions) (*C.VipsImage, error) { @@ -277,8 +287,8 @@ func vipsPreSave(image *C.VipsImage, o *vipsSaveOptions) (*C.VipsImage, error) { // Apply the proper colour space var outImage *C.VipsImage if vipsColourspaceIsSupported(image) { - err := int(C.vips_colourspace_bridge(image, &outImage, interpretation)) - if err != 0 { + err := C.vips_colourspace_bridge(image, &outImage, interpretation) + if int(err) != 0 { return nil, catchVipsError() } C.g_object_unref(C.gpointer(image)) diff --git a/vips.h b/vips.h index 4f75627..8685a1c 100644 --- a/vips.h +++ b/vips.h @@ -227,7 +227,7 @@ vips_webpsave_bridge(VipsImage *in, void **buf, size_t *len, int strip, int qual } int -vips_flatten_image(VipsImage *in, VipsImage **out, double background[3]) { +vips_flatten_background_brigde(VipsImage *in, VipsImage **out, double background[3]) { VipsArrayDouble *vipsBackground = vips_array_double_new(background, 3); return vips_flatten(in, out, "background", vipsBackground,