/* * Copyright (c) 2009 M Joonas Pihlaja * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. */ /* An unpremultiplier using a 64KB division table. It specialises * constant runs and solid runs of pixels. It has the advantage over * the others that it can clamp the result into range without any * additional cost so that the output doesn't overflow should there be * superluminant pixels in the input. */ #include #include /* Pixel format config for a 32 bit pixel with 8 bit components. Only * the location of alpha matters. */ #ifndef ASHIFT # define ASHIFT 24 #endif #define RSHIFT ((24 + ASHIFT) % 32) #define GSHIFT ((16 + ASHIFT) % 32) #define BSHIFT (( 8 + ASHIFT) % 32) #define AMASK (255U << ASHIFT) #define RMASK (255U << RSHIFT) #define GMASK (255U << GSHIFT) #define BMASK (255U << BSHIFT) /* The function to tabulate in the lookup table. Could be anything * really. */ #define div_func(a,b) (255*(a) / (b)) #define clamp(x) ((x) > 255 ? 255 : (x)) /* The entries division_table[a][b] are defined by * * 0 when b = 0 * min(255, ceil(255*a / b)) when b > 0 * */ static uint8_t const division_table[256][256] = { #define R(a,b) ((b) > 0 ? clamp(div_func((a),(b))) : 0) #define R1(a,i) R(a, i), R(a+1, i), R(a+2, i), R(a+3, i) #define R2(a,i) R1(a, i), R1(a+4, i), R1(a+8, i), R1(a+12, i) #define R3(a,i) R2(a, i), R2(a+16, i), R2(a+32, i), R2(a+48, i) #define S(b) { R3(0, b), R3(64, b), R3(128, b), R3(192, b) } #define S1(b) S(b), S(b+1), S(b+2), S(b+3) #define S2(b) S1(b), S1(b+4), S1(b+8), S1(b+12) #define S3(b) S2(b), S2(b+16), S2(b+32), S2(b+48) S3(0), S3(64), S3(128), S3(192) }; void unpremultiply_with_lutb( uint32_t * restrict dst, uint32_t const * restrict src, size_t num_pixels) { size_t i = 0; while (i < num_pixels) { uint32_t const_in, const_out; uint32_t accu = -2*255; uint32_t diff; { uint32_t rgba, r, g, b, a; rgba = const_in = src[i]; a = (rgba >> ASHIFT) & 0xFF; accu = a; r = (rgba >> RSHIFT) & 0xFF; g = (rgba >> GSHIFT) & 0xFF; b = (rgba >> BSHIFT) & 0xFF; r = division_table[a][r]; g = division_table[a][g]; b = division_table[a][b]; dst[i] = const_out = (r<= num_pixels) return; { uint32_t rgba, r, g, b, a; rgba = src[i+1]; a = (rgba >> ASHIFT) & 0xFF; accu += a; r = (rgba >> RSHIFT) & 0xFF; g = (rgba >> GSHIFT) & 0xFF; b = (rgba >> BSHIFT) & 0xFF; diff = const_in ^ rgba; r = division_table[a][r]; g = division_table[a][g]; b = division_table[a][b]; dst[i+1] = (r<