1/*
2    PPImagePixelAlphaPremultiplyTables.m
3
4    Copyright 2013-2018 Josh Freeman
5    http://www.twilightedge.com
6
7    This file is part of PikoPixel for Mac OS X and GNUstep.
8    PikoPixel is a graphical application for drawing & editing pixel-art images.
9
10    PikoPixel is free software: you can redistribute it and/or modify it under
11    the terms of the GNU Affero General Public License as published by the
12    Free Software Foundation, either version 3 of the License, or (at your
13    option) any later version approved for PikoPixel by its copyright holder (or
14    an authorized proxy).
15
16    PikoPixel is distributed in the hope that it will be useful, but WITHOUT ANY
17    WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
18    FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
19    details.
20
21    You should have received a copy of the GNU Affero General Public License
22    along with this program. If not, see <http://www.gnu.org/licenses/>.
23*/
24
25#import "PPImagePixelAlphaPremultiplyTables.h"
26
27
28#define kNumLookupTables    (kMaxImagePixelComponentValue+1)
29#define kSizeOfLookupTable  ((kMaxImagePixelComponentValue+1) * sizeof(PPImagePixelComponent))
30
31
32PPImagePixelComponent *gImageAlphaPremultiplyTables[kNumLookupTables],
33                        *gImageAlphaUnpremultiplyTables[kNumLookupTables];
34
35
36static bool SetupImageAlphaPremultiplyTables(void);
37
38
39@implementation NSObject (PPImagePixelAlphaPremultiplyTables)
40
41+ (void) load
42{
43    SetupImageAlphaPremultiplyTables();
44}
45
46@end
47
48#pragma mark Private functions
49
50static bool SetupImageAlphaPremultiplyTables(void)
51{
52    int tablesBufferSize, alphaValue, colorValue;
53    unsigned char *premultiplyTablesBuffer = NULL, *unpremultiplyTablesBuffer = NULL;
54    PPImagePixelComponent *currentTable;
55
56    tablesBufferSize = kNumLookupTables * kSizeOfLookupTable;
57
58    premultiplyTablesBuffer = (unsigned char *) malloc (tablesBufferSize);
59    unpremultiplyTablesBuffer = (unsigned char *) malloc (tablesBufferSize);
60
61    if (!premultiplyTablesBuffer || !unpremultiplyTablesBuffer)
62    {
63        goto ERROR;
64    }
65
66    // alphaValue=[0] tables
67
68        // premultiply
69
70    currentTable = premultiplyTablesBuffer;
71    premultiplyTablesBuffer += kSizeOfLookupTable;
72
73    memset(currentTable, 0, kSizeOfLookupTable);
74    gImageAlphaPremultiplyTables[0] = currentTable;
75
76        // unpremultiply
77
78    currentTable = unpremultiplyTablesBuffer;
79    unpremultiplyTablesBuffer += kSizeOfLookupTable;
80
81    memset(currentTable, 0, kSizeOfLookupTable);
82    gImageAlphaUnpremultiplyTables[0] = currentTable;
83
84
85    // alphaValue=[1..MAX] tables
86
87    for (alphaValue=1; alphaValue<=kMaxImagePixelComponentValue; alphaValue++)
88    {
89        // premultiply
90
91        currentTable = premultiplyTablesBuffer;
92        premultiplyTablesBuffer += kSizeOfLookupTable;
93
94        currentTable[0] = 0;
95
96        for (colorValue=1; colorValue<=kMaxImagePixelComponentValue; colorValue++)
97        {
98            currentTable[colorValue] =
99                (PPImagePixelComponent) roundf(((float) colorValue)
100                                                * ((float) alphaValue)
101                                                / ((float) kMaxImagePixelComponentValue));
102        }
103
104        gImageAlphaPremultiplyTables[alphaValue] = currentTable;
105
106        // unpremultiply
107
108        currentTable = unpremultiplyTablesBuffer;
109        unpremultiplyTablesBuffer += kSizeOfLookupTable;
110
111        currentTable[0] = 0;
112
113        for (colorValue=1; colorValue<alphaValue; colorValue++)
114        {
115            currentTable[colorValue] =
116                (PPImagePixelComponent) roundf(((float) colorValue)
117                                                * ((float) kMaxImagePixelComponentValue)
118                                                / ((float) alphaValue));
119        }
120
121        while (colorValue <= kMaxImagePixelComponentValue)
122        {
123            currentTable[colorValue] = kMaxImagePixelComponentValue;
124            colorValue++;
125        }
126
127        gImageAlphaUnpremultiplyTables[alphaValue] = currentTable;
128    }
129
130    return YES;
131
132ERROR:
133    if (premultiplyTablesBuffer)
134    {
135        free(premultiplyTablesBuffer);
136    }
137
138    if (unpremultiplyTablesBuffer)
139    {
140        free(unpremultiplyTablesBuffer);
141    }
142
143    return NO;
144}
145