Libvips: Insert PNG with transparent Background on JPEG - Getting White Background

Created on 25 Oct 2017  ·  4Comments  ·  Source: libvips/libvips

I have a JPEG:

tile

I want to Insert the PNG:

pin

On Position 128x128 on the JPEG.

When doing

vips insert tile.jpg pin.png newimage.jpg 128 128

It gives me Error Output: insert: images must have the same number of bands, or one must be single-band since pin.jpg has an Alpha Channel and tile.jpg not.

So I convert the jpg to png:

convert tile.jpg png32:tile.png    

Now I have a tile.png with Alpha Channel:
tile

But when I now call:

vips insert tile.png pin.png newimage.png 128 128

I get the following:
inserted

The background of the inserted pin.png is white.

I checked vips insert --help-all but didn't really find a helpful command line parameter. Both images have an alpha channel. My questions:

  • Does libvips insert command support transparent background?
  • If yes: Can someone point me out on how to use this feature then?
  • ... or maybe am I doing something wrong here?

LG
codecitizen

question

Most helpful comment

You can enlarge the overlay to match the large image, then compose:

width=$(vipsheader -f width background.jpg)
height=$(vipsheader -f height background.jpg)
vips embed marker.png overlay.png 128 128 $width $height
vips composite "background.jpg overlay.png" final.jpg 2

Or cut out part of the background, compose, then insert back (as above).

This seems like a common thing to want to do, perhaps there should be an option to specify the position.

All 4 comments

Hello @codecitizen,

insert is a very low-level operation: it just puts one image on top of another, it does not do any blending.

In current libvips you need to use ifthenelse with the blend option. It's pretty horrible:

# get the alpha channel from the overlay
vips extract_band marker.png alpha.png 3 --n 1

# get RGB from the overlay
vips extract_band marker.png rgb.png 0 --n 3

# find the size of the overlay
width=$(vipsheader -f width marker.png)
height=$(vipsheader -f height marker.png)

# cut out an area the size of marker from the background
vips extract_area background.jpg bg.png 128 128 $width $height

# blend the marker on top of the chunk of background
vips ifthenelse alpha.png rgb.png bg.png blended.png --blend

# insert the blended image back into the background
vips insert background.jpg blended.png final.jpg 128 128 

To generate this:

final

libvips 8.6 has a fancy new composite operator which can do all the usual blending modes. You can do:

vips composite "background.jpg marker.png" final.jpg 2

2 means over blend mode. It supports all the PDF blend modes. It should be out in a week or so.

@jcupitt Hey, thanks. I installed libvips 8.6 and vips composite worked great. I'm just not sure how to specify a location of the second image, if possible.

You can enlarge the overlay to match the large image, then compose:

width=$(vipsheader -f width background.jpg)
height=$(vipsheader -f height background.jpg)
vips embed marker.png overlay.png 128 128 $width $height
vips composite "background.jpg overlay.png" final.jpg 2

Or cut out part of the background, compose, then insert back (as above).

This seems like a common thing to want to do, perhaps there should be an option to specify the position.

Awesome! Thanks very much for the quick help!

Was this page helpful?
0 / 5 - 0 ratings