Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/native/sun/awt/image/dither.c
38918 views
1
/*
2
* Copyright (c) 2001, Oracle and/or its affiliates. All rights reserved.
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
*
5
* This code is free software; you can redistribute it and/or modify it
6
* under the terms of the GNU General Public License version 2 only, as
7
* published by the Free Software Foundation. Oracle designates this
8
* particular file as subject to the "Classpath" exception as provided
9
* by Oracle in the LICENSE file that accompanied this code.
10
*
11
* This code is distributed in the hope that it will be useful, but WITHOUT
12
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14
* version 2 for more details (a copy is included in the LICENSE file that
15
* accompanied this code).
16
*
17
* You should have received a copy of the GNU General Public License version
18
* 2 along with this work; if not, write to the Free Software Foundation,
19
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20
*
21
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22
* or visit www.oracle.com if you need additional information or have any
23
* questions.
24
*/
25
26
#include "dither.h"
27
28
sgn_ordered_dither_array std_img_oda_red;
29
sgn_ordered_dither_array std_img_oda_green;
30
sgn_ordered_dither_array std_img_oda_blue;
31
int std_odas_computed = 0;
32
33
void initInverseGrayLut(int* prgb, int rgbsize, ColorData *cData) {
34
int *inverse;
35
int lastindex, lastgray, missing, i;
36
37
if (!cData) {
38
return;
39
}
40
41
inverse = calloc(256, sizeof(int));
42
if (!inverse) {
43
return;
44
}
45
cData->pGrayInverseLutData = inverse;
46
47
for (i = 0; i < 256; i++) {
48
inverse[i] = -1;
49
}
50
51
/* First, fill the gray values */
52
for (i = 0; i < rgbsize; i++) {
53
int r, g, b, rgb = prgb[i];
54
if (rgb == 0x0) {
55
/* ignore transparent black */
56
continue;
57
}
58
r = (rgb >> 16) & 0xff;
59
g = (rgb >> 8 ) & 0xff;
60
b = rgb & 0xff;
61
if (b == r && b == g) {
62
inverse[b] = i;
63
}
64
}
65
66
/* fill the missing gaps by taking the valid values
67
* on either side and filling them halfway into the gap
68
*/
69
lastindex = -1;
70
lastgray = -1;
71
missing = 0;
72
for (i = 0; i < 256; i++) {
73
if (inverse[i] < 0) {
74
inverse[i] = lastgray;
75
missing = 1;
76
} else {
77
lastgray = inverse[i];
78
if (missing) {
79
lastindex = lastindex < 0 ? 0 : (i+lastindex)/2;
80
while (lastindex < i) {
81
inverse[lastindex++] = lastgray;
82
}
83
}
84
lastindex = i;
85
missing = 0;
86
}
87
}
88
}
89
90
void freeICMColorData(ColorData *pData) {
91
if (CANFREE(pData)) {
92
if (pData->img_clr_tbl) {
93
free(pData->img_clr_tbl);
94
}
95
if (pData->pGrayInverseLutData) {
96
free(pData->pGrayInverseLutData);
97
}
98
free(pData);
99
}
100
}
101
102
/* REMIND: does not deal well with bifurcation which happens when two
103
* palette entries map to the same cube vertex
104
*/
105
106
static int
107
recurseLevel(CubeStateInfo *priorState) {
108
int i;
109
CubeStateInfo currentState;
110
memcpy(&currentState, priorState, sizeof(CubeStateInfo));
111
112
113
currentState.rgb = (unsigned short *)malloc(6
114
* sizeof(unsigned short)
115
* priorState->activeEntries);
116
if (currentState.rgb == NULL) {
117
return 0;
118
}
119
120
currentState.indices = (unsigned char *)malloc(6
121
* sizeof(unsigned char)
122
* priorState->activeEntries);
123
124
if (currentState.indices == NULL) {
125
free(currentState.rgb);
126
return 0;
127
}
128
129
currentState.depth++;
130
if (currentState.depth > priorState->maxDepth) {
131
priorState->maxDepth = currentState.depth;
132
}
133
currentState.activeEntries = 0;
134
for (i=priorState->activeEntries - 1; i >= 0; i--) {
135
unsigned short rgb = priorState->rgb[i];
136
unsigned char index = priorState->indices[i];
137
ACTIVATE(rgb, 0x7c00, 0x0400, currentState, index);
138
ACTIVATE(rgb, 0x03e0, 0x0020, currentState, index);
139
ACTIVATE(rgb, 0x001f, 0x0001, currentState, index);
140
}
141
if (currentState.activeEntries) {
142
if (!recurseLevel(&currentState)) {
143
free(currentState.rgb);
144
free(currentState.indices);
145
return 0;
146
}
147
}
148
if (currentState.maxDepth > priorState->maxDepth) {
149
priorState->maxDepth = currentState.maxDepth;
150
}
151
152
free(currentState.rgb);
153
free(currentState.indices);
154
return 1;
155
}
156
157
/*
158
* REMIND: take core inversedLUT calculation to the shared tree and
159
* recode the functions (Win32)awt_Image:initCubemap(),
160
* (Win32)awt_Image:make_cubemap(), (Win32)AwtToolkit::GenerateInverseLUT(),
161
* (Solaris)color:initCubemap() to call the shared codes.
162
*/
163
unsigned char*
164
initCubemap(int* cmap,
165
int cmap_len,
166
int cube_dim) {
167
int i;
168
CubeStateInfo currentState;
169
int cubesize = cube_dim * cube_dim * cube_dim;
170
unsigned char *useFlags;
171
unsigned char *newILut = (unsigned char*)malloc(cubesize);
172
int cmap_mid = (cmap_len >> 1) + (cmap_len & 0x1);
173
if (newILut) {
174
175
useFlags = (unsigned char *)calloc(cubesize, 1);
176
177
if (useFlags == 0) {
178
free(newILut);
179
#ifdef DEBUG
180
fprintf(stderr, "Out of memory in color:initCubemap()1\n");
181
#endif
182
return NULL;
183
}
184
185
currentState.depth = 0;
186
currentState.maxDepth = 0;
187
currentState.usedFlags = useFlags;
188
currentState.activeEntries = 0;
189
currentState.iLUT = newILut;
190
191
currentState.rgb = (unsigned short *)
192
malloc(cmap_len * sizeof(unsigned short));
193
if (currentState.rgb == NULL) {
194
free(newILut);
195
free(useFlags);
196
#ifdef DEBUG
197
fprintf(stderr, "Out of memory in color:initCubemap()2\n");
198
#endif
199
return NULL;
200
}
201
202
currentState.indices = (unsigned char *)
203
malloc(cmap_len * sizeof(unsigned char));
204
if (currentState.indices == NULL) {
205
free(currentState.rgb);
206
free(newILut);
207
free(useFlags);
208
#ifdef DEBUG
209
fprintf(stderr, "Out of memory in color:initCubemap()3\n");
210
#endif
211
return NULL;
212
}
213
214
for (i = 0; i < cmap_mid; i++) {
215
unsigned short rgb;
216
int pixel = cmap[i];
217
rgb = (pixel & 0x00f80000) >> 9;
218
rgb |= (pixel & 0x0000f800) >> 6;
219
rgb |= (pixel & 0xf8) >> 3;
220
INSERTNEW(currentState, rgb, i);
221
pixel = cmap[cmap_len - i - 1];
222
rgb = (pixel & 0x00f80000) >> 9;
223
rgb |= (pixel & 0x0000f800) >> 6;
224
rgb |= (pixel & 0xf8) >> 3;
225
INSERTNEW(currentState, rgb, cmap_len - i - 1);
226
}
227
228
if (!recurseLevel(&currentState)) {
229
free(newILut);
230
free(useFlags);
231
free(currentState.rgb);
232
free(currentState.indices);
233
#ifdef DEBUG
234
fprintf(stderr, "Out of memory in color:initCubemap()4\n");
235
#endif
236
return NULL;
237
}
238
239
free(useFlags);
240
free(currentState.rgb);
241
free(currentState.indices);
242
243
return newILut;
244
}
245
246
#ifdef DEBUG
247
fprintf(stderr, "Out of memory in color:initCubemap()5\n");
248
#endif
249
return NULL;
250
}
251
252
void
253
initDitherTables(ColorData* cData) {
254
255
256
if(std_odas_computed) {
257
cData->img_oda_red = &(std_img_oda_red[0][0]);
258
cData->img_oda_green = &(std_img_oda_green[0][0]);
259
cData->img_oda_blue = &(std_img_oda_blue[0][0]);
260
} else {
261
cData->img_oda_red = &(std_img_oda_red[0][0]);
262
cData->img_oda_green = &(std_img_oda_green[0][0]);
263
cData->img_oda_blue = &(std_img_oda_blue[0][0]);
264
make_dither_arrays(256, cData);
265
std_odas_computed = 1;
266
}
267
268
}
269
270
void make_dither_arrays(int cmapsize, ColorData *cData) {
271
int i, j, k;
272
273
/*
274
* Initialize the per-component ordered dithering arrays
275
* Choose a size based on how far between elements in the
276
* virtual cube. Assume the cube has cuberoot(cmapsize)
277
* elements per axis and those elements are distributed
278
* over 256 colors.
279
* The calculation should really divide by (#comp/axis - 1)
280
* since the first and last elements are at the extremes of
281
* the 256 levels, but in a practical sense this formula
282
* produces a smaller error array which results in smoother
283
* images that have slightly less color fidelity but much
284
* less dithering noise, especially for grayscale images.
285
*/
286
i = (int) (256 / pow(cmapsize, 1.0/3.0));
287
make_sgn_ordered_dither_array(cData->img_oda_red, -i / 2, i / 2);
288
make_sgn_ordered_dither_array(cData->img_oda_green, -i / 2, i / 2);
289
make_sgn_ordered_dither_array(cData->img_oda_blue, -i / 2, i / 2);
290
291
/*
292
* Flip green horizontally and blue vertically so that
293
* the errors don't line up in the 3 primary components.
294
*/
295
for (i = 0; i < 8; i++) {
296
for (j = 0; j < 4; j++) {
297
k = cData->img_oda_green[(i<<3)+j];
298
cData->img_oda_green[(i<<3)+j] = cData->img_oda_green[(i<<3)+7 - j];
299
cData->img_oda_green[(i<<3) + 7 - j] = k;
300
k = cData->img_oda_blue[(j<<3)+i];
301
cData->img_oda_blue[(j<<3)+i] = cData->img_oda_blue[((7 - j)<<3)+i];
302
cData->img_oda_blue[((7 - j)<<3) + i] = k;
303
}
304
}
305
}
306
307