提交 dd9d40b3 编写于 作者: B bae

8007675: Improve color conversion

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