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