Created
May 29, 2016 09:18
-
-
Save jcupitt/15324d7cec7ece0c63439c518b191baa to your computer and use it in GitHub Desktop.
combine two alpha channels with vips
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* compile with | |
* | |
* g++ trans.cpp `pkg-config vips-cpp --cflags --libs` | |
*/ | |
#include <vips/vips8> | |
using namespace vips; | |
/* Return the image alpha maximum. Useful for combining alpha bands. scRGB | |
* images are 0 - 1 for image data, but the alpha is 0 - 255. | |
*/ | |
int | |
image_alpha_max( VipsInterpretation interpretation ) | |
{ | |
if( interpretation == VIPS_INTERPRETATION_RGB16 || | |
interpretation == VIPS_INTERPRETATION_GREY16 ) | |
return( 65535 ); | |
else | |
return( 255 ); | |
} | |
/* Split an image to pixels plus an optional alpha. An image can be mono, rgb | |
* or cmyk, each with an optional alpha as the final band. | |
*/ | |
VImage | |
image_split( VImage in, VImage &alpha, bool &has_alpha ) | |
{ | |
VImage image; | |
if( in.bands() == 2 || | |
(in.bands() == 4 && | |
in.interpretation() != VIPS_INTERPRETATION_CMYK ) || | |
(in.bands() == 5 && | |
in.interpretation() == VIPS_INTERPRETATION_CMYK ) ) { | |
has_alpha = TRUE; | |
image = in.extract_band( 0, | |
VImage::option()->set( "n", in.bands() - 1 ) ); | |
alpha = in.extract_band( in.bands() - 1, | |
VImage::option()->set( "n", 1 ) ); | |
} | |
else { | |
has_alpha = FALSE; | |
image = in; | |
} | |
return( image ); | |
} | |
int | |
main( int argc, char **argv ) | |
{ | |
if( VIPS_INIT( argv[0] ) ) | |
vips_error_exit( NULL ); | |
// load the main image ... it can optionally have an alpha | |
VImage in = VImage::new_from_file( argv[1] ); | |
VImage image_alpha; | |
bool image_has_alpha; | |
VImage image = image_split( in, image_alpha, image_has_alpha ); | |
// load the mask image | |
VImage in2 = VImage::new_from_file( argv[2] ); | |
VImage mask_alpha; | |
bool mask_has_alpha; | |
VImage mask = image_split( in2, mask_alpha, mask_has_alpha ); | |
// we use the mask alpha, or if the mask only has one band, use that | |
if( mask_has_alpha ) | |
mask = mask_alpha; | |
else if( mask.bands() > 1 ) | |
vips_error_exit( "mask has no alpha or more than one band" ); | |
// the range of the mask and the image need to match .. one could be | |
// 16-bit, one 8-bit | |
int image_max = image_alpha_max( image.interpretation() ); | |
int mask_max = image_alpha_max( mask.interpretation() ); | |
if( image_has_alpha ) | |
// combine the new mask and the existing alpha ... there are | |
// many ways of doing this, mult is the simplest | |
mask = image_max * | |
((mask / mask_max) * (image_alpha / image_max)); | |
else if( image_max != mask_max ) | |
// adjust the range of the mask to match the image | |
mask = image_max * (mask / mask_max); | |
// append the mask to the image data ... the mask might be float now, | |
// we must cast the format down to match the image data | |
VImage out = image.bandjoin( mask.cast( image.format() ) ); | |
out.write_to_file( argv[3] ); | |
return( 0 ); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment