start to add more blend modes

This commit is contained in:
John Cupitt 2017-09-27 22:34:05 +01:00
parent 7e2dbdf5fb
commit 62bc9b7e1d
3 changed files with 79 additions and 2 deletions

View File

@ -61,7 +61,12 @@
/** /**
* VipsBlendMode: * VipsBlendMode:
* VIPS_BLEND_MODE_CLEAR:
* VIPS_BLEND_MODE_SOURCE:
* VIPS_BLEND_MODE_OVER: * VIPS_BLEND_MODE_OVER:
* VIPS_BLEND_MODE_IN:
* VIPS_BLEND_MODE_OUT:
* VIPS_BLEND_MODE_ATOP:
* *
* The various Porter-Duff blend modes. See vips_composite(), for example. * The various Porter-Duff blend modes. See vips_composite(), for example.
*/ */
@ -72,6 +77,8 @@
* *
* https://en.wikipedia.org/wiki/Alpha_compositing * https://en.wikipedia.org/wiki/Alpha_compositing
* *
* https://www.cairographics.org/operators/
*
* Benchmark: * Benchmark:
* *
* vips replicate PNG_transparency_demonstration_1.png x.png 15 15 * vips replicate PNG_transparency_demonstration_1.png x.png 15 15
@ -127,8 +134,8 @@ G_DEFINE_TYPE( VipsComposite, vips_composite, VIPS_TYPE_CONVERSION );
/* Cairo naming conventions: /* Cairo naming conventions:
* *
* aR alpha of result * aR alpha of result
* aA alpha of source A * aA alpha of source A (the new pixel)
* aB alpha of source B * aB alpha of source B (the thing we accumulate)
* xR colour channel of result * xR colour channel of result
* xA colour channel of source A * xA colour channel of source A
* xB colour channel of source B * xB colour channel of source B
@ -136,10 +143,30 @@ G_DEFINE_TYPE( VipsComposite, vips_composite, VIPS_TYPE_CONVERSION );
#define ALPHA( MODE, aR, aA, aB ) { \ #define ALPHA( MODE, aR, aA, aB ) { \
switch( MODE ) { \ switch( MODE ) { \
case VIPS_BLEND_MODE_CLEAR: \
aR = 1 - aA; \
break; \
\
case VIPS_BLEND_MODE_SOURCE: \
aR = aA; \
break; \
\
case VIPS_BLEND_MODE_OVER: \ case VIPS_BLEND_MODE_OVER: \
aR = aA + aB * (1.0 - aA); \ aR = aA + aB * (1.0 - aA); \
break; \ break; \
\ \
case VIPS_BLEND_MODE_IN: \
aR = aA * aB; \
break; \
\
case VIPS_BLEND_MODE_OUT: \
aR = aA * (1 - aB); \
break; \
\
case VIPS_BLEND_MODE_ATOP: \
aR = aB; \
break; \
\
default: \ default: \
aR = 0; \ aR = 0; \
g_assert_not_reached(); \ g_assert_not_reached(); \
@ -148,10 +175,30 @@ G_DEFINE_TYPE( VipsComposite, vips_composite, VIPS_TYPE_CONVERSION );
#define BLEND_PREMULTIPLIED( MODE, xR, xA, aA, xB, aB ) { \ #define BLEND_PREMULTIPLIED( MODE, xR, xA, aA, xB, aB ) { \
switch( MODE ) { \ switch( MODE ) { \
case VIPS_BLEND_MODE_CLEAR: \
xR = 1 - aA; \
break; \
\
case VIPS_BLEND_MODE_SOURCE: \
aR = xA; \
break; \
\
case VIPS_BLEND_MODE_OVER: \ case VIPS_BLEND_MODE_OVER: \
xR = xA + xB * (1 - aA); \ xR = xA + xB * (1 - aA); \
break; \ break; \
\ \
case VIPS_BLEND_MODE_IN: \
xR = xA; \
break; \
\
case VIPS_BLEND_MODE_OUT: \
xR = xA; \
break; \
\
case VIPS_BLEND_MODE_ATOP: \
xR = xA + xB * (1 - aA); \
break; \
\
default: \ default: \
xR = 0; \ xR = 0; \
g_assert_not_reached(); \ g_assert_not_reached(); \
@ -160,10 +207,30 @@ G_DEFINE_TYPE( VipsComposite, vips_composite, VIPS_TYPE_CONVERSION );
#define BLEND_MULTIPLY( MODE, xR, aR, xA, aA, xB, aB ) { \ #define BLEND_MULTIPLY( MODE, xR, aR, xA, aA, xB, aB ) { \
switch( MODE ) { \ switch( MODE ) { \
case VIPS_BLEND_MODE_CLEAR: \
xR = 1 - aA; \
break; \
\
case VIPS_BLEND_MODE_SOURCE: \
aR = xA; \
break; \
\
case VIPS_BLEND_MODE_OVER: \ case VIPS_BLEND_MODE_OVER: \
xR = (aA * xA + aB * xB * (1 - aA)) / aR; \ xR = (aA * xA + aB * xB * (1 - aA)) / aR; \
break; \ break; \
\ \
case VIPS_BLEND_MODE_IN: \
xR = xA; \
break; \
\
case VIPS_BLEND_MODE_OUT: \
xR = xA; \
break; \
\
case VIPS_BLEND_MODE_ATOP: \
xR = aA * xA + xB * (1 - aA); \
break; \
\
default: \ default: \
xR = 0; \ xR = 0; \
g_assert_not_reached(); \ g_assert_not_reached(); \

View File

@ -90,7 +90,12 @@ typedef enum {
} VipsInteresting; } VipsInteresting;
typedef enum { typedef enum {
VIPS_BLEND_MODE_CLEAR,
VIPS_BLEND_MODE_SOURCE,
VIPS_BLEND_MODE_OVER, VIPS_BLEND_MODE_OVER,
VIPS_BLEND_MODE_IN,
VIPS_BLEND_MODE_OUT,
VIPS_BLEND_MODE_ATOP,
VIPS_BLEND_MODE_LAST VIPS_BLEND_MODE_LAST
} VipsBlendMode; } VipsBlendMode;

View File

@ -355,7 +355,12 @@ vips_blend_mode_get_type( void )
if( etype == 0 ) { if( etype == 0 ) {
static const GEnumValue values[] = { static const GEnumValue values[] = {
{VIPS_BLEND_MODE_CLEAR, "VIPS_BLEND_MODE_CLEAR", "clear"},
{VIPS_BLEND_MODE_SOURCE, "VIPS_BLEND_MODE_SOURCE", "source"},
{VIPS_BLEND_MODE_OVER, "VIPS_BLEND_MODE_OVER", "over"}, {VIPS_BLEND_MODE_OVER, "VIPS_BLEND_MODE_OVER", "over"},
{VIPS_BLEND_MODE_IN, "VIPS_BLEND_MODE_IN", "in"},
{VIPS_BLEND_MODE_OUT, "VIPS_BLEND_MODE_OUT", "out"},
{VIPS_BLEND_MODE_ATOP, "VIPS_BLEND_MODE_ATOP", "atop"},
{VIPS_BLEND_MODE_LAST, "VIPS_BLEND_MODE_LAST", "last"}, {VIPS_BLEND_MODE_LAST, "VIPS_BLEND_MODE_LAST", "last"},
{0, NULL, NULL} {0, NULL, NULL}
}; };