Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/native/sun/awt/image/dither.c
38918 views
/*1* Copyright (c) 2001, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425#include "dither.h"2627sgn_ordered_dither_array std_img_oda_red;28sgn_ordered_dither_array std_img_oda_green;29sgn_ordered_dither_array std_img_oda_blue;30int std_odas_computed = 0;3132void initInverseGrayLut(int* prgb, int rgbsize, ColorData *cData) {33int *inverse;34int lastindex, lastgray, missing, i;3536if (!cData) {37return;38}3940inverse = calloc(256, sizeof(int));41if (!inverse) {42return;43}44cData->pGrayInverseLutData = inverse;4546for (i = 0; i < 256; i++) {47inverse[i] = -1;48}4950/* First, fill the gray values */51for (i = 0; i < rgbsize; i++) {52int r, g, b, rgb = prgb[i];53if (rgb == 0x0) {54/* ignore transparent black */55continue;56}57r = (rgb >> 16) & 0xff;58g = (rgb >> 8 ) & 0xff;59b = rgb & 0xff;60if (b == r && b == g) {61inverse[b] = i;62}63}6465/* fill the missing gaps by taking the valid values66* on either side and filling them halfway into the gap67*/68lastindex = -1;69lastgray = -1;70missing = 0;71for (i = 0; i < 256; i++) {72if (inverse[i] < 0) {73inverse[i] = lastgray;74missing = 1;75} else {76lastgray = inverse[i];77if (missing) {78lastindex = lastindex < 0 ? 0 : (i+lastindex)/2;79while (lastindex < i) {80inverse[lastindex++] = lastgray;81}82}83lastindex = i;84missing = 0;85}86}87}8889void freeICMColorData(ColorData *pData) {90if (CANFREE(pData)) {91if (pData->img_clr_tbl) {92free(pData->img_clr_tbl);93}94if (pData->pGrayInverseLutData) {95free(pData->pGrayInverseLutData);96}97free(pData);98}99}100101/* REMIND: does not deal well with bifurcation which happens when two102* palette entries map to the same cube vertex103*/104105static int106recurseLevel(CubeStateInfo *priorState) {107int i;108CubeStateInfo currentState;109memcpy(¤tState, priorState, sizeof(CubeStateInfo));110111112currentState.rgb = (unsigned short *)malloc(6113* sizeof(unsigned short)114* priorState->activeEntries);115if (currentState.rgb == NULL) {116return 0;117}118119currentState.indices = (unsigned char *)malloc(6120* sizeof(unsigned char)121* priorState->activeEntries);122123if (currentState.indices == NULL) {124free(currentState.rgb);125return 0;126}127128currentState.depth++;129if (currentState.depth > priorState->maxDepth) {130priorState->maxDepth = currentState.depth;131}132currentState.activeEntries = 0;133for (i=priorState->activeEntries - 1; i >= 0; i--) {134unsigned short rgb = priorState->rgb[i];135unsigned char index = priorState->indices[i];136ACTIVATE(rgb, 0x7c00, 0x0400, currentState, index);137ACTIVATE(rgb, 0x03e0, 0x0020, currentState, index);138ACTIVATE(rgb, 0x001f, 0x0001, currentState, index);139}140if (currentState.activeEntries) {141if (!recurseLevel(¤tState)) {142free(currentState.rgb);143free(currentState.indices);144return 0;145}146}147if (currentState.maxDepth > priorState->maxDepth) {148priorState->maxDepth = currentState.maxDepth;149}150151free(currentState.rgb);152free(currentState.indices);153return 1;154}155156/*157* REMIND: take core inversedLUT calculation to the shared tree and158* recode the functions (Win32)awt_Image:initCubemap(),159* (Win32)awt_Image:make_cubemap(), (Win32)AwtToolkit::GenerateInverseLUT(),160* (Solaris)color:initCubemap() to call the shared codes.161*/162unsigned char*163initCubemap(int* cmap,164int cmap_len,165int cube_dim) {166int i;167CubeStateInfo currentState;168int cubesize = cube_dim * cube_dim * cube_dim;169unsigned char *useFlags;170unsigned char *newILut = (unsigned char*)malloc(cubesize);171int cmap_mid = (cmap_len >> 1) + (cmap_len & 0x1);172if (newILut) {173174useFlags = (unsigned char *)calloc(cubesize, 1);175176if (useFlags == 0) {177free(newILut);178#ifdef DEBUG179fprintf(stderr, "Out of memory in color:initCubemap()1\n");180#endif181return NULL;182}183184currentState.depth = 0;185currentState.maxDepth = 0;186currentState.usedFlags = useFlags;187currentState.activeEntries = 0;188currentState.iLUT = newILut;189190currentState.rgb = (unsigned short *)191malloc(cmap_len * sizeof(unsigned short));192if (currentState.rgb == NULL) {193free(newILut);194free(useFlags);195#ifdef DEBUG196fprintf(stderr, "Out of memory in color:initCubemap()2\n");197#endif198return NULL;199}200201currentState.indices = (unsigned char *)202malloc(cmap_len * sizeof(unsigned char));203if (currentState.indices == NULL) {204free(currentState.rgb);205free(newILut);206free(useFlags);207#ifdef DEBUG208fprintf(stderr, "Out of memory in color:initCubemap()3\n");209#endif210return NULL;211}212213for (i = 0; i < cmap_mid; i++) {214unsigned short rgb;215int pixel = cmap[i];216rgb = (pixel & 0x00f80000) >> 9;217rgb |= (pixel & 0x0000f800) >> 6;218rgb |= (pixel & 0xf8) >> 3;219INSERTNEW(currentState, rgb, i);220pixel = cmap[cmap_len - i - 1];221rgb = (pixel & 0x00f80000) >> 9;222rgb |= (pixel & 0x0000f800) >> 6;223rgb |= (pixel & 0xf8) >> 3;224INSERTNEW(currentState, rgb, cmap_len - i - 1);225}226227if (!recurseLevel(¤tState)) {228free(newILut);229free(useFlags);230free(currentState.rgb);231free(currentState.indices);232#ifdef DEBUG233fprintf(stderr, "Out of memory in color:initCubemap()4\n");234#endif235return NULL;236}237238free(useFlags);239free(currentState.rgb);240free(currentState.indices);241242return newILut;243}244245#ifdef DEBUG246fprintf(stderr, "Out of memory in color:initCubemap()5\n");247#endif248return NULL;249}250251void252initDitherTables(ColorData* cData) {253254255if(std_odas_computed) {256cData->img_oda_red = &(std_img_oda_red[0][0]);257cData->img_oda_green = &(std_img_oda_green[0][0]);258cData->img_oda_blue = &(std_img_oda_blue[0][0]);259} else {260cData->img_oda_red = &(std_img_oda_red[0][0]);261cData->img_oda_green = &(std_img_oda_green[0][0]);262cData->img_oda_blue = &(std_img_oda_blue[0][0]);263make_dither_arrays(256, cData);264std_odas_computed = 1;265}266267}268269void make_dither_arrays(int cmapsize, ColorData *cData) {270int i, j, k;271272/*273* Initialize the per-component ordered dithering arrays274* Choose a size based on how far between elements in the275* virtual cube. Assume the cube has cuberoot(cmapsize)276* elements per axis and those elements are distributed277* over 256 colors.278* The calculation should really divide by (#comp/axis - 1)279* since the first and last elements are at the extremes of280* the 256 levels, but in a practical sense this formula281* produces a smaller error array which results in smoother282* images that have slightly less color fidelity but much283* less dithering noise, especially for grayscale images.284*/285i = (int) (256 / pow(cmapsize, 1.0/3.0));286make_sgn_ordered_dither_array(cData->img_oda_red, -i / 2, i / 2);287make_sgn_ordered_dither_array(cData->img_oda_green, -i / 2, i / 2);288make_sgn_ordered_dither_array(cData->img_oda_blue, -i / 2, i / 2);289290/*291* Flip green horizontally and blue vertically so that292* the errors don't line up in the 3 primary components.293*/294for (i = 0; i < 8; i++) {295for (j = 0; j < 4; j++) {296k = cData->img_oda_green[(i<<3)+j];297cData->img_oda_green[(i<<3)+j] = cData->img_oda_green[(i<<3)+7 - j];298cData->img_oda_green[(i<<3) + 7 - j] = k;299k = cData->img_oda_blue[(j<<3)+i];300cData->img_oda_blue[(j<<3)+i] = cData->img_oda_blue[((7 - j)<<3)+i];301cData->img_oda_blue[((7 - j)<<3) + i] = k;302}303}304}305306307