/* * 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. */ /* Basic unpremultiplier using a 64KB division table. It has the * advantage over the others that it can clamp the result into range * without any cost, so it is safe to pass it superluminant input * pixels. */ #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_lut(uint32_t * restrict dst, uint32_t const * restrict src, size_t n) { size_t i; for (i=0; i> ASHIFT) & 0xFF; uint32_t r = (rgba >> RSHIFT) & 0xFF; uint32_t g = (rgba >> GSHIFT) & 0xFF; uint32_t b = (rgba >> BSHIFT) & 0xFF; r = division_table[a][r]; g = division_table[a][g]; b = division_table[a][b]; dst[i] = (r<