7116979: Unexpected pixel colour when converting images to TYPE_BYTE_INDEXED

Unexpected pixel colour when converting images to TYPE_BYTE_INDEXED

Reviewed-by: prr, flar
This commit is contained in:
Jayathirth D V 2016-05-06 06:52:13 +00:00
parent b58e171061
commit e6a2c0dc1e
10 changed files with 196 additions and 5 deletions

View File

@ -206,7 +206,8 @@ ColorData.img_oda_green 28
ColorData.img_oda_blue 32
ColorData.pGrayInverseLutData 36
ColorData.screendata 40
ColorData 44
ColorData.representsPrimaries 44
ColorData 48
XFontStruct.ext_data 0
XFontStruct.fid 4
XFontStruct.direction 8

View File

@ -206,6 +206,7 @@ ColorData.img_oda_green 56
ColorData.img_oda_blue 64
ColorData.pGrayInverseLutData 72
ColorData.screendata 80
ColorData.representsPrimaries 84
ColorData 88
XFontStruct.ext_data 0
XFontStruct.fid 8

View File

@ -206,6 +206,7 @@ ColorData.img_oda_green 56
ColorData.img_oda_blue 64
ColorData.pGrayInverseLutData 72
ColorData.screendata 80
ColorData.representsPrimaries 84
ColorData 88
XFontStruct.ext_data 0
XFontStruct.fid 8

View File

@ -749,6 +749,7 @@ ColorData
img_oda_blue pointer byte
pGrayInverseLutData pointer int
screendata int
representsPrimaries int
AwtGraphicsConfigData
awt_depth int

View File

@ -231,12 +231,14 @@ static void BufImg_GetRasInfo(JNIEnv *env,
pRasInfo->redErrTable = NULL;
pRasInfo->grnErrTable = NULL;
pRasInfo->bluErrTable = NULL;
pRasInfo->representsPrimaries = 0;
} else {
pRasInfo->invColorTable = bipriv->cData->img_clr_tbl;
pRasInfo->redErrTable = bipriv->cData->img_oda_red;
pRasInfo->grnErrTable = bipriv->cData->img_oda_green;
pRasInfo->bluErrTable = bipriv->cData->img_oda_blue;
pRasInfo->invGrayTable = bipriv->cData->pGrayInverseLutData;
pRasInfo->representsPrimaries = bipriv->cData->representsPrimaries;
}
}
@ -259,6 +261,59 @@ static void BufImg_Release(JNIEnv *env,
}
}
static int calculatePrimaryColorsApproximation(int* cmap, unsigned char* cube, int cube_size) {
int i, j, k;
int index, value, color;
// values calculated from cmap
int r, g, b;
// maximum positive/negative variation allowed for r, g, b values for primary colors
int delta = 5;
// get the primary color cmap indices from corner of inverse color table
for (i = 0; i < cube_size; i += (cube_size - 1)) {
for (j = 0; j < cube_size; j += (cube_size - 1)) {
for (k = 0; k < cube_size; k += (cube_size - 1)) {
// calculate inverse color table index
index = i + cube_size * (j + cube_size * k);
// get value present in corners of inverse color table
value = cube[index];
// use the corner values as index for cmap
color = cmap[value];
// extract r,g,b values from cmap value
r = ((color) >> 16) & 0xff;
g = ((color) >> 8) & 0xff;
b = color & 0xff;
/*
* If i/j/k value is 0 optimum value of b/g/r should be 0 but we allow
* maximum positive variation of 5. If i/j/k value is 31 optimum value
* of b/g/r should be 255 but we allow maximum negative variation of 5.
*/
if (i == 0) {
if (b > delta)
return 0;
} else {
if (b < (255 - delta))
return 0;
}
if (j == 0) {
if (g > delta)
return 0;
} else {
if (g < (255 - delta))
return 0;
}
if (k == 0) {
if (r > delta)
return 0;
} else {
if (r < (255 - delta))
return 0;
}
}
}
}
return 1;
}
static ColorData *BufImg_SetupICM(JNIEnv *env,
BufImgSDOps *bisdo)
{
@ -298,6 +353,7 @@ static ColorData *BufImg_SetupICM(JNIEnv *env,
}
cData->img_clr_tbl = initCubemap(pRgb, bisdo->lutsize, 32);
cData->representsPrimaries = calculatePrimaryColorsApproximation(pRgb, cData->img_clr_tbl, 32);
if (allGray == JNI_TRUE) {
initInverseGrayLut(pRgb, bisdo->lutsize, cData);
}

View File

@ -163,6 +163,7 @@ typedef struct {
char *grnErrTable; /* Green ordered dither table */
char *bluErrTable; /* Blue ordered dither table */
int *invGrayTable; /* Inverse gray table */
int representsPrimaries; /* whether cmap represents primary colors */
union {
void *align; /* ensures strict alignment */
char data[SD_RASINFO_PRIVATE_SIZE];

View File

@ -43,7 +43,7 @@ typedef jubyte ByteIndexedDataType;
jint *PREFIX ## Lut;
#define DeclareByteIndexedStoreVars(PREFIX) \
int PREFIX ## XDither, PREFIX ## YDither; \
int PREFIX ## XDither, PREFIX ## YDither, PREFIX ## RepPrims; \
char *PREFIX ## rerr, *PREFIX ## gerr, *PREFIX ## berr; \
unsigned char *PREFIX ## InvLut;
@ -70,6 +70,7 @@ typedef jubyte ByteIndexedDataType;
do { \
SetByteIndexedStoreVarsYPos(PREFIX, pRasInfo, (pRasInfo)->bounds.y1); \
PREFIX ## InvLut = (pRasInfo)->invColorTable; \
PREFIX ## RepPrims = (pRasInfo)->representsPrimaries; \
} while (0)
#define InitByteIndexedStoreVarsX(PREFIX, pRasInfo) \
@ -168,9 +169,14 @@ typedef jubyte ByteIndexedBmDataType;
#define StoreByteIndexedFrom3ByteRgb(pRas, PREFIX, x, r, g, b) \
do { \
r += PREFIX ## rerr[PREFIX ## XDither]; \
g += PREFIX ## gerr[PREFIX ## XDither]; \
b += PREFIX ## berr[PREFIX ## XDither]; \
if (!(((r == 0) || (r == 255)) && \
((g == 0) || (g == 255)) && \
((b == 0) || (b == 255)) && \
PREFIX ## RepPrims)) { \
r += PREFIX ## rerr[PREFIX ## XDither]; \
g += PREFIX ## gerr[PREFIX ## XDither]; \
b += PREFIX ## berr[PREFIX ## XDither]; \
} \
ByteClamp3Components(r, g, b); \
(pRas)[x] = SurfaceData_InvColorMap(PREFIX ## InvLut, r, g, b); \
} while (0)

View File

@ -44,6 +44,7 @@ typedef struct _ColorData {
char* img_oda_blue;
int *pGrayInverseLutData;
int screendata;
int representsPrimaries;
} ColorData;

View File

@ -33,6 +33,7 @@ typedef struct _ColorData {
char* img_oda_blue;
unsigned char* img_clr_tbl;
int *pGrayInverseLutData;
int representsPrimaries;
} ColorData;
#define CANFREE(pData) (pData)

View File

@ -0,0 +1,122 @@
/*
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test
* @bug 7116979
* @summary Test verifies whether BufferedImage with primary colors are
* stored properly when we draw into ByteIndexed BufferedImage.
* @run main ConvertToByteIndexedTest
*/
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.util.HashMap;
public class ConvertToByteIndexedTest {
static final int[] SRC_TYPES = new int[] {
BufferedImage.TYPE_INT_RGB,
BufferedImage.TYPE_INT_ARGB,
BufferedImage.TYPE_INT_ARGB_PRE,
BufferedImage.TYPE_INT_BGR,
BufferedImage.TYPE_3BYTE_BGR,
BufferedImage.TYPE_4BYTE_ABGR,
BufferedImage.TYPE_4BYTE_ABGR_PRE,
BufferedImage.TYPE_USHORT_565_RGB,
BufferedImage.TYPE_USHORT_555_RGB,
BufferedImage.TYPE_BYTE_INDEXED};
static final String[] TYPE_NAME = new String[] {
"INT_RGB",
"INT_ARGB",
"INT_ARGB_PRE",
"INT_BGR",
"3BYTE_BGR",
"4BYTE_ABGR",
"4BYTE_ABGR_PRE",
"USHORT_565_RGB",
"USHORT_555_RGB",
"BYTE_INDEXED"};
static final Color[] COLORS = new Color[] {
//Color.WHITE,
Color.BLACK,
Color.RED,
Color.YELLOW,
Color.GREEN,
Color.MAGENTA,
Color.CYAN,
Color.BLUE};
static final HashMap<Integer,String> TYPE_TABLE =
new HashMap<Integer,String>();
static {
for (int i = 0; i < SRC_TYPES.length; i++) {
TYPE_TABLE.put(new Integer(SRC_TYPES[i]), TYPE_NAME[i]);
}
}
static int width = 50;
static int height = 50;
public static void ConvertToByteIndexed(Color color, int srcType) {
// setup source image and graphics for conversion.
BufferedImage srcImage = new BufferedImage(width, height, srcType);
Graphics2D srcG2D = srcImage.createGraphics();
srcG2D.setColor(color);
srcG2D.fillRect(0, 0, width, height);
// setup destination image and graphics for conversion.
int dstType = BufferedImage.TYPE_BYTE_INDEXED;
BufferedImage dstImage = new BufferedImage(width, height, dstType);
Graphics2D dstG2D = (Graphics2D)dstImage.getGraphics();
// draw source image into Byte Indexed destination
dstG2D.drawImage(srcImage, 0, 0, null);
// draw into ARGB image to verify individual pixel value.
BufferedImage argbImage = new BufferedImage(width, height,
BufferedImage.TYPE_INT_ARGB);
Graphics2D argbG2D = (Graphics2D)argbImage.getGraphics();
argbG2D.drawImage(dstImage, 0, 0, null);
for (int i = 0; i < width; i++) {
for (int j = 0; j < height; j++) {
if (color.getRGB() != argbImage.getRGB(i, j)) {
throw new RuntimeException("Conversion from " +
TYPE_TABLE.get(srcType) + " to BYTE_INDEXED is not"
+ " done properly for " + color);
}
}
}
}
public static void main(String args[]) {
for (int srcType : SRC_TYPES) {
for (Color color : COLORS) {
ConvertToByteIndexed(color, srcType);
}
}
}
}