diff --git a/CHANGELOG.md b/CHANGELOG.md index 2064e8c8..80754422 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,7 +11,8 @@ - Speed up generation of video thumbnails with large timestamps. ### Fix -- Fix thumbnails generation of some videos. +- Fix `padding` and `extend` behaior when converting from a fromat without alpha support to one with alpha support +- (pro) Fix thumbnails generation of some videos. ## [2.14.1] - 2020-07-22 ### Fix diff --git a/image_type.go b/image_type.go index 6a0369ea..c5ba5610 100644 --- a/image_type.go +++ b/image_type.go @@ -117,3 +117,7 @@ func (it imageType) ContentDispositionFromURL(imageURL string) string { return it.ContentDisposition(strings.TrimSuffix(filename, filepath.Ext(filename))) } + +func (it imageType) SupportsAlpha() bool { + return it != imageTypeJPEG && it != imageTypeBMP +} diff --git a/process.go b/process.go index 47950b99..861c3a7b 100644 --- a/process.go +++ b/process.go @@ -266,7 +266,7 @@ func prepareWatermark(wm *vipsImage, wmData *imageData, opts *watermarkOptions, left, top := calcPosition(imgWidth, imgHeight, wm.Width(), wm.Height(), &opts.Gravity, true) - return wm.Embed(imgWidth, imgHeight, left, top, rgbColor{0, 0, 0}) + return wm.Embed(imgWidth, imgHeight, left, top, rgbColor{0, 0, 0}, true) } func applyWatermark(img *vipsImage, wmData *imageData, opts *watermarkOptions, framesCount int) error { @@ -430,6 +430,8 @@ func transformImage(ctx context.Context, img *vipsImage, data []byte, po *proces return err } + transparrentBg := po.Format.SupportsAlpha() && !po.Flatten + if hasAlpha && (po.Flatten || po.Format == imageTypeJPEG) { if err = img.Flatten(po.Background); err != nil { return err @@ -456,7 +458,7 @@ func transformImage(ctx context.Context, img *vipsImage, data []byte, po *proces if po.Extend.Enabled && (po.Width > img.Width() || po.Height > img.Height()) { offX, offY := calcPosition(po.Width, po.Height, img.Width(), img.Height(), &po.Extend.Gravity, false) - if err = img.Embed(po.Width, po.Height, offX, offY, po.Background); err != nil { + if err = img.Embed(po.Width, po.Height, offX, offY, po.Background, transparrentBg); err != nil { return err } } @@ -472,6 +474,7 @@ func transformImage(ctx context.Context, img *vipsImage, data []byte, po *proces paddingLeft, paddingTop, po.Background, + transparrentBg, ); err != nil { return err } diff --git a/vips.c b/vips.c index 2879a5d8..b378bc0a 100644 --- a/vips.c +++ b/vips.c @@ -250,6 +250,11 @@ vips_image_hasalpha_go(VipsImage * in) { #endif } +int +vips_addalpha_go(VipsImage *in, VipsImage **out) { + return vips_addalpha(in, out, NULL); +} + int vips_copy_go(VipsImage *in, VipsImage **out) { return vips_copy(in, out, NULL); diff --git a/vips.go b/vips.go index 0a80039d..a1c85767 100644 --- a/vips.go +++ b/vips.go @@ -590,20 +590,30 @@ func (img *vipsImage) Replicate(width, height int) error { return nil } -func (img *vipsImage) Embed(width, height int, offX, offY int, bg rgbColor) error { +func (img *vipsImage) Embed(width, height int, offX, offY int, bg rgbColor, transpBg bool) error { + var tmp *C.VipsImage + if err := img.RgbColourspace(); err != nil { return err } var bgc []C.double - if img.HasAlpha() { + if transpBg { + if !img.HasAlpha() { + if C.vips_addalpha_go(img.VipsImage, &tmp) != 0 { + return vipsError() + } + C.swap_and_clear(&img.VipsImage, tmp) + } + bgc = []C.double{C.double(0)} } else { - bgc = []C.double{C.double(bg.R), C.double(bg.G), C.double(bg.B)} + bgc = []C.double{C.double(bg.R), C.double(bg.G), C.double(bg.B), 1.0} } - var tmp *C.VipsImage - if C.vips_embed_go(img.VipsImage, &tmp, C.int(offX), C.int(offY), C.int(width), C.int(height), &bgc[0], C.int(len(bgc))) != 0 { + bgn := minInt(int(img.VipsImage.Bands), len(bgc)) + + if C.vips_embed_go(img.VipsImage, &tmp, C.int(offX), C.int(offY), C.int(width), C.int(height), &bgc[0], C.int(bgn)) != 0 { return vipsError() } C.swap_and_clear(&img.VipsImage, tmp) diff --git a/vips.h b/vips.h index b5fb10b1..5aa51204 100644 --- a/vips.h +++ b/vips.h @@ -45,7 +45,9 @@ VipsBandFormat vips_band_format(VipsImage *in); gboolean vips_support_webp_animation(); gboolean vips_is_animated(VipsImage * in); + gboolean vips_image_hasalpha_go(VipsImage * in); +int vips_addalpha_go(VipsImage *in, VipsImage **out); int vips_copy_go(VipsImage *in, VipsImage **out);