Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/java.desktop/share/native/libawt/awt/image/dither.c
41159 views
1
/*
2
* Copyright (c) 2001, 2018, 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 "jni.h"
27
#include "dither.h"
28
29
JNIEXPORT sgn_ordered_dither_array std_img_oda_red;
30
JNIEXPORT sgn_ordered_dither_array std_img_oda_green;
31
JNIEXPORT sgn_ordered_dither_array std_img_oda_blue;
32
JNIEXPORT int std_odas_computed = 0;
33
34
JNIEXPORT void JNICALL
35
initInverseGrayLut(int* prgb, int rgbsize, ColorData *cData) {
36
int *inverse;
37
int lastindex, lastgray, missing, i;
38
39
if (!cData) {
40
return;
41
}
42
43
inverse = calloc(256, sizeof(int));
44
if (!inverse) {
45
return;
46
}
47
cData->pGrayInverseLutData = inverse;
48
49
for (i = 0; i < 256; i++) {
50
inverse[i] = -1;
51
}
52
53
/* First, fill the gray values */
54
for (i = 0; i < rgbsize; i++) {
55
int r, g, b, rgb = prgb[i];
56
if (rgb == 0x0) {
57
/* ignore transparent black */
58
continue;
59
}
60
r = (rgb >> 16) & 0xff;
61
g = (rgb >> 8 ) & 0xff;
62
b = rgb & 0xff;
63
if (b == r && b == g) {
64
inverse[b] = i;
65
}
66
}
67
68
/* fill the missing gaps by taking the valid values
69
* on either side and filling them halfway into the gap
70
*/
71
lastindex = -1;
72
lastgray = -1;
73
missing = 0;
74
for (i = 0; i < 256; i++) {
75
if (inverse[i] < 0) {
76
inverse[i] = lastgray;
77
missing = 1;
78
} else {
79
lastgray = inverse[i];
80
if (missing) {
81
lastindex = lastindex < 0 ? 0 : (i+lastindex)/2;
82
while (lastindex < i) {
83
inverse[lastindex++] = lastgray;
84
}
85
}
86
lastindex = i;
87
missing = 0;
88
}
89
}
90
}
91
92
void freeICMColorData(ColorData *pData) {
93
if (CANFREE(pData)) {
94
if (pData->img_clr_tbl) {
95
free(pData->img_clr_tbl);
96
}
97
if (pData->pGrayInverseLutData) {
98
free(pData->pGrayInverseLutData);
99
}
100
free(pData);
101
}
102
}
103
104
/* REMIND: does not deal well with bifurcation which happens when two
105
* palette entries map to the same cube vertex
106
*/
107
108
static int
109
recurseLevel(CubeStateInfo *priorState) {
110
int i;
111
CubeStateInfo currentState;
112
memcpy(&currentState, priorState, sizeof(CubeStateInfo));
113
114
115
currentState.rgb = (unsigned short *)malloc(6
116
* sizeof(unsigned short)
117
* priorState->activeEntries);
118
if (currentState.rgb == NULL) {
119
return 0;
120
}
121
122
currentState.indices = (unsigned char *)malloc(6
123
* sizeof(unsigned char)
124
* priorState->activeEntries);
125
126
if (currentState.indices == NULL) {
127
free(currentState.rgb);
128
return 0;
129
}
130
131
currentState.depth++;
132
if (currentState.depth > priorState->maxDepth) {
133
priorState->maxDepth = currentState.depth;
134
}
135
currentState.activeEntries = 0;
136
for (i=priorState->activeEntries - 1; i >= 0; i--) {
137
unsigned short rgb = priorState->rgb[i];
138
unsigned char index = priorState->indices[i];
139
ACTIVATE(rgb, 0x7c00, 0x0400, currentState, index);
140
ACTIVATE(rgb, 0x03e0, 0x0020, currentState, index);
141
ACTIVATE(rgb, 0x001f, 0x0001, currentState, index);
142
}
143
if (currentState.activeEntries) {
144
if (!recurseLevel(&currentState)) {
145
free(currentState.rgb);
146
free(currentState.indices);
147
return 0;
148
}
149
}
150
if (currentState.maxDepth > priorState->maxDepth) {
151
priorState->maxDepth = currentState.maxDepth;
152
}
153
154
free(currentState.rgb);
155
free(currentState.indices);
156
return 1;
157
}
158
159
/*
160
* REMIND: take core inversedLUT calculation to the shared tree and
161
* recode the functions (Win32)awt_Image:initCubemap(),
162
* (Win32)awt_Image:make_cubemap(), (Win32)AwtToolkit::GenerateInverseLUT(),
163
* (Solaris)color:initCubemap() to call the shared codes.
164
*/
165
unsigned char*
166
initCubemap(int* cmap,
167
int cmap_len,
168
int cube_dim) {
169
int i;
170
CubeStateInfo currentState;
171
int cubesize = cube_dim * cube_dim * cube_dim;
172
unsigned char *useFlags;
173
unsigned char *newILut = (unsigned char*)malloc(cubesize);
174
int cmap_mid = (cmap_len >> 1) + (cmap_len & 0x1);
175
if (newILut) {
176
177
useFlags = (unsigned char *)calloc(cubesize, 1);
178
179
if (useFlags == 0) {
180
free(newILut);
181
#ifdef DEBUG
182
fprintf(stderr, "Out of memory in color:initCubemap()1\n");
183
#endif
184
return NULL;
185
}
186
187
currentState.depth = 0;
188
currentState.maxDepth = 0;
189
currentState.usedFlags = useFlags;
190
currentState.activeEntries = 0;
191
currentState.iLUT = newILut;
192
193
currentState.rgb = (unsigned short *)
194
malloc(cmap_len * sizeof(unsigned short));
195
if (currentState.rgb == NULL) {
196
free(newILut);
197
free(useFlags);
198
#ifdef DEBUG
199
fprintf(stderr, "Out of memory in color:initCubemap()2\n");
200
#endif
201
return NULL;
202
}
203
204
currentState.indices = (unsigned char *)
205
malloc(cmap_len * sizeof(unsigned char));
206
if (currentState.indices == NULL) {
207
free(currentState.rgb);
208
free(newILut);
209
free(useFlags);
210
#ifdef DEBUG
211
fprintf(stderr, "Out of memory in color:initCubemap()3\n");
212
#endif
213
return NULL;
214
}
215
216
for (i = 0; i < cmap_mid; i++) {
217
unsigned short rgb;
218
int pixel = cmap[i];
219
rgb = (pixel & 0x00f80000) >> 9;
220
rgb |= (pixel & 0x0000f800) >> 6;
221
rgb |= (pixel & 0xf8) >> 3;
222
INSERTNEW(currentState, rgb, i);
223
pixel = cmap[cmap_len - i - 1];
224
rgb = (pixel & 0x00f80000) >> 9;
225
rgb |= (pixel & 0x0000f800) >> 6;
226
rgb |= (pixel & 0xf8) >> 3;
227
INSERTNEW(currentState, rgb, cmap_len - i - 1);
228
}
229
230
if (!recurseLevel(&currentState)) {
231
free(newILut);
232
free(useFlags);
233
free(currentState.rgb);
234
free(currentState.indices);
235
#ifdef DEBUG
236
fprintf(stderr, "Out of memory in color:initCubemap()4\n");
237
#endif
238
return NULL;
239
}
240
241
free(useFlags);
242
free(currentState.rgb);
243
free(currentState.indices);
244
245
return newILut;
246
}
247
248
#ifdef DEBUG
249
fprintf(stderr, "Out of memory in color:initCubemap()5\n");
250
#endif
251
return NULL;
252
}
253
254
void
255
initDitherTables(ColorData* cData) {
256
257
258
if(std_odas_computed) {
259
cData->img_oda_red = &(std_img_oda_red[0][0]);
260
cData->img_oda_green = &(std_img_oda_green[0][0]);
261
cData->img_oda_blue = &(std_img_oda_blue[0][0]);
262
} else {
263
cData->img_oda_red = &(std_img_oda_red[0][0]);
264
cData->img_oda_green = &(std_img_oda_green[0][0]);
265
cData->img_oda_blue = &(std_img_oda_blue[0][0]);
266
make_dither_arrays(256, cData);
267
std_odas_computed = 1;
268
}
269
270
}
271
272
JNIEXPORT void JNICALL
273
make_dither_arrays(int cmapsize, ColorData *cData) {
274
int i, j, k;
275
276
/*
277
* Initialize the per-component ordered dithering arrays
278
* Choose a size based on how far between elements in the
279
* virtual cube. Assume the cube has cuberoot(cmapsize)
280
* elements per axis and those elements are distributed
281
* over 256 colors.
282
* The calculation should really divide by (#comp/axis - 1)
283
* since the first and last elements are at the extremes of
284
* the 256 levels, but in a practical sense this formula
285
* produces a smaller error array which results in smoother
286
* images that have slightly less color fidelity but much
287
* less dithering noise, especially for grayscale images.
288
*/
289
i = (int) (256 / pow(cmapsize, 1.0/3.0));
290
make_sgn_ordered_dither_array(cData->img_oda_red, -i / 2, i / 2);
291
make_sgn_ordered_dither_array(cData->img_oda_green, -i / 2, i / 2);
292
make_sgn_ordered_dither_array(cData->img_oda_blue, -i / 2, i / 2);
293
294
/*
295
* Flip green horizontally and blue vertically so that
296
* the errors don't line up in the 3 primary components.
297
*/
298
for (i = 0; i < 8; i++) {
299
for (j = 0; j < 4; j++) {
300
k = cData->img_oda_green[(i<<3)+j];
301
cData->img_oda_green[(i<<3)+j] = cData->img_oda_green[(i<<3)+7 - j];
302
cData->img_oda_green[(i<<3) + 7 - j] = k;
303
k = cData->img_oda_blue[(j<<3)+i];
304
cData->img_oda_blue[(j<<3)+i] = cData->img_oda_blue[((7 - j)<<3)+i];
305
cData->img_oda_blue[((7 - j)<<3) + i] = k;
306
}
307
}
308
}
309
310