提交 dd9d40b3 编写于 作者: B bae

8007675: Improve color conversion

Reviewed-by: prr, mschoene, jgodinez
上级 0484b9e8
......@@ -99,50 +99,75 @@ class LCMSImageLayout {
int offset;
Object dataArray;
private LCMSImageLayout(int np, int pixelType, int pixelSize) {
private int dataArrayLength; /* in bytes */
private LCMSImageLayout(int np, int pixelType, int pixelSize)
throws ImageLayoutException
{
this.pixelType = pixelType;
width = np;
height = 1;
nextRowOffset = np*pixelSize;
nextRowOffset = safeMult(pixelSize, np);
offset = 0;
}
private LCMSImageLayout(int width, int height, int pixelType,
int pixelSize) {
int pixelSize)
throws ImageLayoutException
{
this.pixelType = pixelType;
this.width = width;
this.height = height;
nextRowOffset = width*pixelSize;
nextRowOffset = safeMult(pixelSize, width);
offset = 0;
}
public LCMSImageLayout(byte[] data, int np, int pixelType, int pixelSize) {
public LCMSImageLayout(byte[] data, int np, int pixelType, int pixelSize)
throws ImageLayoutException
{
this(np, pixelType, pixelSize);
dataType = DT_BYTE;
dataArray = data;
dataArrayLength = data.length;
verify();
}
public LCMSImageLayout(short[] data, int np, int pixelType, int pixelSize) {
public LCMSImageLayout(short[] data, int np, int pixelType, int pixelSize)
throws ImageLayoutException
{
this(np, pixelType, pixelSize);
dataType = DT_SHORT;
dataArray = data;
dataArrayLength = 2 * data.length;
verify();
}
public LCMSImageLayout(int[] data, int np, int pixelType, int pixelSize) {
public LCMSImageLayout(int[] data, int np, int pixelType, int pixelSize)
throws ImageLayoutException
{
this(np, pixelType, pixelSize);
dataType = DT_INT;
dataArray = data;
dataArrayLength = 4 * data.length;
verify();
}
public LCMSImageLayout(double[] data, int np, int pixelType, int pixelSize)
throws ImageLayoutException
{
this(np, pixelType, pixelSize);
dataType = DT_DOUBLE;
dataArray = data;
dataArrayLength = 8 * data.length;
verify();
}
public LCMSImageLayout(BufferedImage image) {
public LCMSImageLayout(BufferedImage image) throws ImageLayoutException {
ShortComponentRaster shortRaster;
IntegerComponentRaster intRaster;
ByteComponentRaster byteRaster;
......@@ -186,9 +211,13 @@ class LCMSImageLayout {
case BufferedImage.TYPE_INT_ARGB:
case BufferedImage.TYPE_INT_BGR:
intRaster = (IntegerComponentRaster)image.getRaster();
nextRowOffset = intRaster.getScanlineStride()*4;
offset = intRaster.getDataOffset(0)*4;
nextRowOffset = safeMult(4, intRaster.getScanlineStride());
offset = safeMult(4, intRaster.getDataOffset(0));
dataArray = intRaster.getDataStorage();
dataArrayLength = 4 * intRaster.getDataStorage().length;
dataType = DT_INT;
break;
......@@ -199,6 +228,7 @@ class LCMSImageLayout {
int firstBand = image.getSampleModel().getNumBands() - 1;
offset = byteRaster.getDataOffset(firstBand);
dataArray = byteRaster.getDataStorage();
dataArrayLength = byteRaster.getDataStorage().length;
dataType = DT_BYTE;
break;
......@@ -207,17 +237,20 @@ class LCMSImageLayout {
nextRowOffset = byteRaster.getScanlineStride();
offset = byteRaster.getDataOffset(0);
dataArray = byteRaster.getDataStorage();
dataArrayLength = byteRaster.getDataStorage().length;
dataType = DT_BYTE;
break;
case BufferedImage.TYPE_USHORT_GRAY:
shortRaster = (ShortComponentRaster)image.getRaster();
nextRowOffset = shortRaster.getScanlineStride()*2;
offset = shortRaster.getDataOffset(0) * 2;
nextRowOffset = safeMult(2, shortRaster.getScanlineStride());
offset = safeMult(2, shortRaster.getDataOffset(0));
dataArray = shortRaster.getDataStorage();
dataArrayLength = 2 * shortRaster.getDataStorage().length;
dataType = DT_SHORT;
break;
}
verify();
}
public static boolean isSupported(BufferedImage image) {
......@@ -233,4 +266,45 @@ class LCMSImageLayout {
}
return false;
}
private void verify() throws ImageLayoutException {
if (offset < 0 || offset >= dataArrayLength) {
throw new ImageLayoutException("Invalid image layout");
}
int lastPixelOffset = safeMult(nextRowOffset, (height - 1));
lastPixelOffset = safeAdd(lastPixelOffset, (width - 1));
int off = safeAdd(offset, lastPixelOffset);
if (off < 0 || off >= dataArrayLength) {
throw new ImageLayoutException("Invalid image layout");
}
}
static int safeAdd(int a, int b) throws ImageLayoutException {
long res = a;
res += b;
if (res < Integer.MIN_VALUE || res > Integer.MAX_VALUE) {
throw new ImageLayoutException("Invalid image layout");
}
return (int)res;
}
static int safeMult(int a, int b) throws ImageLayoutException {
long res = a;
res *= b;
if (res < Integer.MIN_VALUE || res > Integer.MAX_VALUE) {
throw new ImageLayoutException("Invalid image layout");
}
return (int)res;
}
public static class ImageLayoutException extends Exception {
public ImageLayoutException(String message) {
super(message);
}
}
}
......@@ -51,6 +51,7 @@ import java.awt.image.SinglePixelPackedSampleModel;
import java.awt.image.ComponentSampleModel;
import sun.java2d.cmm.*;
import sun.java2d.cmm.lcms.*;
import static sun.java2d.cmm.lcms.LCMSImageLayout.ImageLayoutException;
public class LCMSTransform implements ColorTransform {
......@@ -164,8 +165,12 @@ public class LCMSTransform implements ColorTransform {
if (LCMSImageLayout.isSupported(src) &&
LCMSImageLayout.isSupported(dst))
{
doTransform(new LCMSImageLayout(src), new LCMSImageLayout(dst));
return;
try {
doTransform(new LCMSImageLayout(src), new LCMSImageLayout(dst));
return;
} catch (ImageLayoutException e) {
throw new CMMException("Unable to convert images");
}
}
LCMSImageLayout srcIL, dstIL;
Raster srcRas = src.getRaster();
......@@ -223,14 +228,18 @@ public class LCMSTransform implements ColorTransform {
}
int idx;
// TODO check for src npixels = dst npixels
srcIL = new LCMSImageLayout(
srcLine, srcLine.length/getNumInComponents(),
LCMSImageLayout.CHANNELS_SH(getNumInComponents()) |
LCMSImageLayout.BYTES_SH(1), getNumInComponents());
dstIL = new LCMSImageLayout(
dstLine, dstLine.length/getNumOutComponents(),
LCMSImageLayout.CHANNELS_SH(getNumOutComponents()) |
LCMSImageLayout.BYTES_SH(1), getNumOutComponents());
try {
srcIL = new LCMSImageLayout(
srcLine, srcLine.length/getNumInComponents(),
LCMSImageLayout.CHANNELS_SH(getNumInComponents()) |
LCMSImageLayout.BYTES_SH(1), getNumInComponents());
dstIL = new LCMSImageLayout(
dstLine, dstLine.length/getNumOutComponents(),
LCMSImageLayout.CHANNELS_SH(getNumOutComponents()) |
LCMSImageLayout.BYTES_SH(1), getNumOutComponents());
} catch (ImageLayoutException e) {
throw new CMMException("Unable to convert images");
}
// process each scanline
for (int y = 0; y < h; y++) {
// convert src scanline
......@@ -279,16 +288,19 @@ public class LCMSTransform implements ColorTransform {
alpha = new float[w];
}
int idx;
srcIL = new LCMSImageLayout(
srcLine, srcLine.length/getNumInComponents(),
LCMSImageLayout.CHANNELS_SH(getNumInComponents()) |
LCMSImageLayout.BYTES_SH(2), getNumInComponents()*2);
dstIL = new LCMSImageLayout(
dstLine, dstLine.length/getNumOutComponents(),
LCMSImageLayout.CHANNELS_SH(getNumOutComponents()) |
LCMSImageLayout.BYTES_SH(2), getNumOutComponents()*2);
try {
srcIL = new LCMSImageLayout(
srcLine, srcLine.length/getNumInComponents(),
LCMSImageLayout.CHANNELS_SH(getNumInComponents()) |
LCMSImageLayout.BYTES_SH(2), getNumInComponents()*2);
dstIL = new LCMSImageLayout(
dstLine, dstLine.length/getNumOutComponents(),
LCMSImageLayout.CHANNELS_SH(getNumOutComponents()) |
LCMSImageLayout.BYTES_SH(2), getNumOutComponents()*2);
} catch (ImageLayoutException e) {
throw new CMMException("Unable to convert images");
}
// process each scanline
for (int y = 0; y < h; y++) {
// convert src scanline
......@@ -397,16 +409,19 @@ public class LCMSTransform implements ColorTransform {
short[] srcLine = new short[w * srcNumBands];
short[] dstLine = new short[w * dstNumBands];
int idx;
srcIL = new LCMSImageLayout(
srcLine, srcLine.length/getNumInComponents(),
LCMSImageLayout.CHANNELS_SH(getNumInComponents()) |
LCMSImageLayout.BYTES_SH(2), getNumInComponents()*2);
dstIL = new LCMSImageLayout(
dstLine, dstLine.length/getNumOutComponents(),
LCMSImageLayout.CHANNELS_SH(getNumOutComponents()) |
LCMSImageLayout.BYTES_SH(2), getNumOutComponents()*2);
try {
srcIL = new LCMSImageLayout(
srcLine, srcLine.length/getNumInComponents(),
LCMSImageLayout.CHANNELS_SH(getNumInComponents()) |
LCMSImageLayout.BYTES_SH(2), getNumInComponents()*2);
dstIL = new LCMSImageLayout(
dstLine, dstLine.length/getNumOutComponents(),
LCMSImageLayout.CHANNELS_SH(getNumOutComponents()) |
LCMSImageLayout.BYTES_SH(2), getNumOutComponents()*2);
} catch (ImageLayoutException e) {
throw new CMMException("Unable to convert rasters");
}
// process each scanline
for (int y = 0; y < h; y++, ys++, yd++) {
// get src scanline
......@@ -489,15 +504,18 @@ public class LCMSTransform implements ColorTransform {
byte[] dstLine = new byte[w * dstNumBands];
int idx;
// TODO check for src npixels = dst npixels
srcIL = new LCMSImageLayout(
srcLine, srcLine.length/getNumInComponents(),
LCMSImageLayout.CHANNELS_SH(getNumInComponents()) |
LCMSImageLayout.BYTES_SH(1), getNumInComponents());
dstIL = new LCMSImageLayout(
dstLine, dstLine.length/getNumOutComponents(),
LCMSImageLayout.CHANNELS_SH(getNumOutComponents()) |
LCMSImageLayout.BYTES_SH(1), getNumOutComponents());
try {
srcIL = new LCMSImageLayout(
srcLine, srcLine.length/getNumInComponents(),
LCMSImageLayout.CHANNELS_SH(getNumInComponents()) |
LCMSImageLayout.BYTES_SH(1), getNumInComponents());
dstIL = new LCMSImageLayout(
dstLine, dstLine.length/getNumOutComponents(),
LCMSImageLayout.CHANNELS_SH(getNumOutComponents()) |
LCMSImageLayout.BYTES_SH(1), getNumOutComponents());
} catch (ImageLayoutException e) {
throw new CMMException("Unable to convert rasters");
}
// process each scanline
for (int y = 0; y < h; y++, ys++, yd++) {
// get src scanline
......@@ -529,16 +547,20 @@ public class LCMSTransform implements ColorTransform {
short[] srcLine = new short[w * srcNumBands];
short[] dstLine = new short[w * dstNumBands];
int idx;
srcIL = new LCMSImageLayout(
srcLine, srcLine.length/getNumInComponents(),
LCMSImageLayout.CHANNELS_SH(getNumInComponents()) |
LCMSImageLayout.BYTES_SH(2), getNumInComponents()*2);
dstIL = new LCMSImageLayout(
dstLine, dstLine.length/getNumOutComponents(),
LCMSImageLayout.CHANNELS_SH(getNumOutComponents()) |
LCMSImageLayout.BYTES_SH(2), getNumOutComponents()*2);
try {
srcIL = new LCMSImageLayout(
srcLine, srcLine.length/getNumInComponents(),
LCMSImageLayout.CHANNELS_SH(getNumInComponents()) |
LCMSImageLayout.BYTES_SH(2), getNumInComponents()*2);
dstIL = new LCMSImageLayout(
dstLine, dstLine.length/getNumOutComponents(),
LCMSImageLayout.CHANNELS_SH(getNumOutComponents()) |
LCMSImageLayout.BYTES_SH(2), getNumOutComponents()*2);
} catch (ImageLayoutException e) {
throw new CMMException("Unable to convert rasters");
}
// process each scanline
for (int y = 0; y < h; y++, ys++, yd++) {
// get src scanline
......@@ -579,19 +601,23 @@ public class LCMSTransform implements ColorTransform {
dst = new short [(src.length/getNumInComponents())*getNumOutComponents()];
}
LCMSImageLayout srcIL = new LCMSImageLayout(
src, src.length/getNumInComponents(),
LCMSImageLayout.CHANNELS_SH(getNumInComponents()) |
LCMSImageLayout.BYTES_SH(2), getNumInComponents()*2);
try {
LCMSImageLayout srcIL = new LCMSImageLayout(
src, src.length/getNumInComponents(),
LCMSImageLayout.CHANNELS_SH(getNumInComponents()) |
LCMSImageLayout.BYTES_SH(2), getNumInComponents()*2);
LCMSImageLayout dstIL = new LCMSImageLayout(
dst, dst.length/getNumOutComponents(),
LCMSImageLayout.CHANNELS_SH(getNumOutComponents()) |
LCMSImageLayout.BYTES_SH(2), getNumOutComponents()*2);
LCMSImageLayout dstIL = new LCMSImageLayout(
dst, dst.length/getNumOutComponents(),
LCMSImageLayout.CHANNELS_SH(getNumOutComponents()) |
LCMSImageLayout.BYTES_SH(2), getNumOutComponents()*2);
doTransform(srcIL, dstIL);
doTransform(srcIL, dstIL);
return dst;
return dst;
} catch (ImageLayoutException e) {
throw new CMMException("Unable to convert data");
}
}
public byte[] colorConvert(byte[] src, byte[] dst) {
......@@ -599,18 +625,22 @@ public class LCMSTransform implements ColorTransform {
dst = new byte [(src.length/getNumInComponents())*getNumOutComponents()];
}
LCMSImageLayout srcIL = new LCMSImageLayout(
src, src.length/getNumInComponents(),
LCMSImageLayout.CHANNELS_SH(getNumInComponents()) |
LCMSImageLayout.BYTES_SH(1), getNumInComponents());
try {
LCMSImageLayout srcIL = new LCMSImageLayout(
src, src.length/getNumInComponents(),
LCMSImageLayout.CHANNELS_SH(getNumInComponents()) |
LCMSImageLayout.BYTES_SH(1), getNumInComponents());
LCMSImageLayout dstIL = new LCMSImageLayout(
dst, dst.length/getNumOutComponents(),
LCMSImageLayout.CHANNELS_SH(getNumOutComponents()) |
LCMSImageLayout.BYTES_SH(1), getNumOutComponents());
LCMSImageLayout dstIL = new LCMSImageLayout(
dst, dst.length/getNumOutComponents(),
LCMSImageLayout.CHANNELS_SH(getNumOutComponents()) |
LCMSImageLayout.BYTES_SH(1), getNumOutComponents());
doTransform(srcIL, dstIL);
doTransform(srcIL, dstIL);
return dst;
return dst;
} catch (ImageLayoutException e) {
throw new CMMException("Unable to convert data");
}
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册