|
9 | 9 | * - match normalised alpha to output type
|
10 | 10 | * 27/2/21 jjonesrs
|
11 | 11 | * - revise range clipping and 1/x, again
|
| 12 | + * 8/8/22 |
| 13 | + * - look for alpha near 0, not just exactly 0 |
12 | 14 | */
|
13 | 15 |
|
14 | 16 | /*
|
@@ -123,6 +125,55 @@ G_DEFINE_TYPE( VipsUnpremultiply, vips_unpremultiply, VIPS_TYPE_CONVERSION );
|
123 | 125 | } \
|
124 | 126 | }
|
125 | 127 |
|
| 128 | +/* For float-style images, we need to check for alpha near zero, or we'll get |
| 129 | + * +/- Inf in the output. |
| 130 | + */ |
| 131 | +#define FUNPRE_MANY( IN, OUT ) { \ |
| 132 | + IN * restrict p = (IN *) in; \ |
| 133 | + OUT * restrict q = (OUT *) out; \ |
| 134 | + \ |
| 135 | + for( x = 0; x < width; x++ ) { \ |
| 136 | + IN alpha = p[alpha_band]; \ |
| 137 | + OUT factor = VIPS_ABS( alpha ) < 0.01 ? 0 : max_alpha / alpha; \ |
| 138 | + \ |
| 139 | + for( i = 0; i < alpha_band; i++ ) \ |
| 140 | + q[i] = factor * p[i]; \ |
| 141 | + q[alpha_band] = VIPS_CLIP( 0, alpha, max_alpha ); \ |
| 142 | + for( i = alpha_band + 1; i < bands; i++ ) \ |
| 143 | + q[i] = p[i]; \ |
| 144 | + \ |
| 145 | + p += bands; \ |
| 146 | + q += bands; \ |
| 147 | + } \ |
| 148 | +} |
| 149 | + |
| 150 | +#define FUNPRE_RGBA( IN, OUT ) { \ |
| 151 | + IN * restrict p = (IN *) in; \ |
| 152 | + OUT * restrict q = (OUT *) out; \ |
| 153 | + \ |
| 154 | + for( x = 0; x < width; x++ ) { \ |
| 155 | + IN alpha = p[3]; \ |
| 156 | + OUT factor = VIPS_ABS( alpha ) < 0.01 ? 0 : max_alpha / alpha; \ |
| 157 | + \ |
| 158 | + q[0] = factor * p[0]; \ |
| 159 | + q[1] = factor * p[1]; \ |
| 160 | + q[2] = factor * p[2]; \ |
| 161 | + q[3] = VIPS_CLIP( 0, alpha, max_alpha ); \ |
| 162 | + \ |
| 163 | + p += 4; \ |
| 164 | + q += 4; \ |
| 165 | + } \ |
| 166 | +} |
| 167 | + |
| 168 | +#define FUNPRE( IN, OUT ) { \ |
| 169 | + if( bands == 4 ) { \ |
| 170 | + FUNPRE_RGBA( IN, OUT ); \ |
| 171 | + } \ |
| 172 | + else { \ |
| 173 | + FUNPRE_MANY( IN, OUT ); \ |
| 174 | + } \ |
| 175 | +} |
| 176 | + |
126 | 177 | static int
|
127 | 178 | vips_unpremultiply_gen( VipsRegion *or, void *vseq, void *a, void *b,
|
128 | 179 | gboolean *stop )
|
@@ -171,11 +222,11 @@ vips_unpremultiply_gen( VipsRegion *or, void *vseq, void *a, void *b,
|
171 | 222 | break;
|
172 | 223 |
|
173 | 224 | case VIPS_FORMAT_FLOAT:
|
174 |
| - UNPRE( float, float ); |
| 225 | + FUNPRE( float, float ); |
175 | 226 | break;
|
176 | 227 |
|
177 | 228 | case VIPS_FORMAT_DOUBLE:
|
178 |
| - UNPRE( double, double ); |
| 229 | + FUNPRE( double, double ); |
179 | 230 | break;
|
180 | 231 |
|
181 | 232 | case VIPS_FORMAT_COMPLEX:
|
|
0 commit comments