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(¤tState, 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(¤tState)) { 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(¤tState)) { 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 }