提交 49e01df9 编写于 作者: B bae

8005530: [lcms] Improve performance of ColorConverOp for default destinations

Reviewed-by: prr, jgodinez
上级 0484b9e8
......@@ -28,6 +28,9 @@ PACKAGE = sun.java2d.cmm.lcms
LIBRARY = lcms
PRODUCT = sun
# Use highest level of optimization on this library
OPTIMIZATION_LEVEL = HIGHEST
include $(BUILDDIR)/common/Defs.gmk
#
......
......@@ -27,13 +27,12 @@
SUNWprivate_1.1 {
global:
Java_sun_java2d_cmm_lcms_LCMS_loadProfile;
Java_sun_java2d_cmm_lcms_LCMS_freeProfile;
Java_sun_java2d_cmm_lcms_LCMS_loadProfileNative;
Java_sun_java2d_cmm_lcms_LCMS_freeProfileNative;
Java_sun_java2d_cmm_lcms_LCMS_getProfileSize;
Java_sun_java2d_cmm_lcms_LCMS_getProfileData;
Java_sun_java2d_cmm_lcms_LCMS_getTagSize;
Java_sun_java2d_cmm_lcms_LCMS_getTagData;
Java_sun_java2d_cmm_lcms_LCMS_setTagData;
Java_sun_java2d_cmm_lcms_LCMS_getTagNative;
Java_sun_java2d_cmm_lcms_LCMS_setTagDataNative;
Java_sun_java2d_cmm_lcms_LCMS_colorConvert;
Java_sun_java2d_cmm_lcms_LCMS_getProfileID;
Java_sun_java2d_cmm_lcms_LCMS_initLCMS;
......
......@@ -1218,7 +1218,7 @@ ifdef OPENJDK
OUTPUT_DIR:=$(INSTALL_LIBRARIES_HERE),\
SRC:=$(JDK_TOPDIR)/src/share/native/sun/java2d/cmm/lcms,\
LANG:=C,\
OPTIMIZATION:=LOW, \
OPTIMIZATION:=HIGHEST, \
CFLAGS:=$(filter-out -xc99=%none,$(CFLAGS_JDKLIB)) \
$(SHARED_LIBRARY_FLAGS) \
-I$(JDK_TOPDIR)/src/share/native/sun/java2d \
......
......@@ -27,13 +27,12 @@
SUNWprivate_1.1 {
global:
Java_sun_java2d_cmm_lcms_LCMS_loadProfile;
Java_sun_java2d_cmm_lcms_LCMS_freeProfile;
Java_sun_java2d_cmm_lcms_LCMS_loadProfileNative;
Java_sun_java2d_cmm_lcms_LCMS_freeProfileNative;
Java_sun_java2d_cmm_lcms_LCMS_getProfileSize;
Java_sun_java2d_cmm_lcms_LCMS_getProfileData;
Java_sun_java2d_cmm_lcms_LCMS_getTagSize;
Java_sun_java2d_cmm_lcms_LCMS_getTagData;
Java_sun_java2d_cmm_lcms_LCMS_setTagData;
Java_sun_java2d_cmm_lcms_LCMS_getTagNative;
Java_sun_java2d_cmm_lcms_LCMS_setTagDataNative;
Java_sun_java2d_cmm_lcms_LCMS_colorConvert;
Java_sun_java2d_cmm_lcms_LCMS_getProfileID;
Java_sun_java2d_cmm_lcms_LCMS_initLCMS;
......
......@@ -25,29 +25,91 @@
package sun.java2d.cmm.lcms;
import java.awt.color.ColorSpace;
import java.awt.color.ICC_Profile;
import java.awt.color.CMMException;
import java.util.Arrays;
import java.util.HashMap;
import sun.java2d.cmm.ColorTransform;
import sun.java2d.cmm.PCMM;
import sun.java2d.cmm.lcms.LCMS;
import sun.java2d.cmm.lcms.LCMSTransform;
public class LCMS implements PCMM {
/* methods invoked from ICC_Profile */
public native long loadProfile(byte[] data);
@Override
public long loadProfile(byte[] data) {
long id = loadProfileNative(data);
public native void freeProfile(long profileID);
if (id != 0L) {
if (profiles == null) {
profiles = new HashMap<>();
}
profiles.put(id, new TagCache(id));
}
return id;
}
private native long loadProfileNative(byte[] data);
@Override
public void freeProfile(long profileID) {
TagCache c = profiles.remove(profileID);
if (c != null) {
c.clear();
}
if (profiles.isEmpty()) {
profiles = null;
}
freeProfileNative(profileID);
}
private native void freeProfileNative(long profileID);
public native synchronized int getProfileSize(long profileID);
public native synchronized void getProfileData(long profileID, byte[] data);
public native synchronized int getTagSize(long profileID, int tagSignature);
public native synchronized void getTagData(long profileID, int tagSignature,
byte[] data);
public native synchronized void setTagData(long profileID, int tagSignature,
@Override
public synchronized int getTagSize(long profileID, int tagSignature) {
TagCache cache = profiles.get(profileID);
if (cache == null) {
cache = new TagCache(profileID);
profiles.put(profileID, cache);
}
TagData t = cache.getTag(tagSignature);
return t == null ? 0 : t.getSize();
}
private static native byte[] getTagNative(long profileID, int signature);
@Override
public synchronized void getTagData(long profileID, int tagSignature,
byte[] data)
{
TagCache cache = profiles.get(profileID);
if (cache == null) {
cache = new TagCache(profileID);
profiles.put(profileID, cache);
}
TagData t = cache.getTag(tagSignature);
if (t != null) {
t.copyDataTo(data);
}
}
@Override
public synchronized void setTagData(long profileID, int tagSignature, byte[] data) {
TagCache cache = profiles.get(profileID);
if (cache != null) {
cache.clear();
}
setTagDataNative(profileID, tagSignature, data);
}
private native synchronized void setTagDataNative(long profileID, int tagSignature,
byte[] data);
public static native long getProfileID(ICC_Profile profile);
......@@ -103,4 +165,59 @@ public class LCMS implements PCMM {
initLCMS(LCMSTransform.class, LCMSImageLayout.class, ICC_Profile.class);
}
private static class TagData {
private int signature;
private byte[] data;
TagData(int sig, byte[] data) {
this.signature = sig;
this.data = data;
}
int getSize() {
return data.length;
}
byte[] getData() {
return Arrays.copyOf(data, data.length);
}
void copyDataTo(byte[] dst) {
System.arraycopy(data, 0, dst, 0, data.length);
}
int getSignature() {
return signature;
}
}
private static class TagCache {
private long profileID;
private HashMap<Integer, TagData> tags;
TagCache(long id) {
profileID = id;
tags = new HashMap<>();
}
TagData getTag(int sig) {
TagData t = tags.get(sig);
if (t == null) {
byte[] tagData = getTagNative(profileID, sig);
if (tagData != null) {
t = new TagData(sig, tagData);
tags.put(sig, t);
}
}
return t;
}
void clear() {
tags.clear();
}
}
private static HashMap<Long, TagCache> profiles;
}
......@@ -22,26 +22,19 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.java2d.cmm.lcms;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.awt.image.ComponentColorModel;
import java.awt.image.Raster;
import java.awt.image.WritableRaster;
import java.awt.image.SinglePixelPackedSampleModel;
import java.awt.image.ComponentSampleModel;
import java.awt.image.DataBuffer;
import java.awt.image.DataBufferByte;
import java.awt.image.DataBufferUShort;
import java.awt.image.DataBufferInt;
import java.awt.image.ColorModel;
import java.awt.image.Raster;
import java.awt.image.SampleModel;
import sun.awt.image.ByteComponentRaster;
import sun.awt.image.ShortComponentRaster;
import sun.awt.image.IntegerComponentRaster;
class LCMSImageLayout {
public static int BYTES_SH(int x) {
......@@ -49,47 +42,34 @@ class LCMSImageLayout {
}
public static int EXTRA_SH(int x) {
return x<<7;
return x << 7;
}
public static int CHANNELS_SH(int x) {
return x<<3;
return x << 3;
}
public static final int SWAPFIRST = 1<<14;
public static final int DOSWAP = 1<<10;
public static final int SWAPFIRST = 1 << 14;
public static final int DOSWAP = 1 << 10;
public static final int PT_RGB_8 =
CHANNELS_SH(3) | BYTES_SH(1);
CHANNELS_SH(3) | BYTES_SH(1);
public static final int PT_GRAY_8 =
CHANNELS_SH(1) | BYTES_SH(1);
CHANNELS_SH(1) | BYTES_SH(1);
public static final int PT_GRAY_16 =
CHANNELS_SH(1) | BYTES_SH(2);
CHANNELS_SH(1) | BYTES_SH(2);
public static final int PT_RGBA_8 =
EXTRA_SH(1) | CHANNELS_SH(3) | BYTES_SH(1);
EXTRA_SH(1) | CHANNELS_SH(3) | BYTES_SH(1);
public static final int PT_ARGB_8 =
EXTRA_SH(1) | CHANNELS_SH(3) | BYTES_SH(1) | SWAPFIRST;
EXTRA_SH(1) | CHANNELS_SH(3) | BYTES_SH(1) | SWAPFIRST;
public static final int PT_BGR_8 =
DOSWAP | CHANNELS_SH(3) | BYTES_SH(1);
DOSWAP | CHANNELS_SH(3) | BYTES_SH(1);
public static final int PT_ABGR_8 =
DOSWAP | EXTRA_SH(1) | CHANNELS_SH(3) | BYTES_SH(1);
public static final int PT_BGRA_8 = EXTRA_SH(1) | CHANNELS_SH(3) |
BYTES_SH(1) | DOSWAP | SWAPFIRST;
public static final int DT_BYTE = 0;
public static final int DT_SHORT = 1;
public static final int DT_INT = 2;
public static final int DT_DOUBLE = 3;
DOSWAP | EXTRA_SH(1) | CHANNELS_SH(3) | BYTES_SH(1);
public static final int PT_BGRA_8 = EXTRA_SH(1) | CHANNELS_SH(3)
| BYTES_SH(1) | DOSWAP | SWAPFIRST;
public static final int DT_BYTE = 0;
public static final int DT_SHORT = 1;
public static final int DT_INT = 2;
public static final int DT_DOUBLE = 3;
boolean isIntPacked = false;
int pixelType;
int dataType;
......@@ -98,25 +78,30 @@ class LCMSImageLayout {
int nextRowOffset;
int offset;
/* This flag indicates whether the image can be processed
* at once by doTransfrom() native call. Otherwise, the
* image is processed scan by scan.
*/
private boolean imageAtOnce = false;
Object dataArray;
private LCMSImageLayout(int np, int pixelType, int pixelSize) {
this.pixelType = pixelType;
width = np;
height = 1;
nextRowOffset = np*pixelSize;
nextRowOffset = np * pixelSize;
offset = 0;
}
private LCMSImageLayout(int width, int height, int pixelType,
int pixelSize) {
int pixelSize) {
this.pixelType = pixelType;
this.width = width;
this.height = height;
nextRowOffset = width*pixelSize;
nextRowOffset = width * pixelSize;
offset = 0;
}
public LCMSImageLayout(byte[] data, int np, int pixelType, int pixelSize) {
this(np, pixelType, pixelSize);
dataType = DT_BYTE;
......@@ -135,102 +120,218 @@ class LCMSImageLayout {
dataArray = data;
}
public LCMSImageLayout(double[] data, int np, int pixelType, int pixelSize)
{
public LCMSImageLayout(double[] data, int np, int pixelType, int pixelSize) {
this(np, pixelType, pixelSize);
dataType = DT_DOUBLE;
dataArray = data;
}
public LCMSImageLayout(BufferedImage image) {
ShortComponentRaster shortRaster;
IntegerComponentRaster intRaster;
ByteComponentRaster byteRaster;
private LCMSImageLayout() {
}
/* This method creates a layout object for given image.
* Returns null if the image is not supported by current implementation.
*/
public static LCMSImageLayout createImageLayout(BufferedImage image) {
LCMSImageLayout l = new LCMSImageLayout();
switch (image.getType()) {
case BufferedImage.TYPE_INT_RGB:
pixelType = PT_ARGB_8;
isIntPacked = true;
l.pixelType = PT_ARGB_8;
l.isIntPacked = true;
break;
case BufferedImage.TYPE_INT_ARGB:
pixelType = PT_ARGB_8;
isIntPacked = true;
l.pixelType = PT_ARGB_8;
l.isIntPacked = true;
break;
case BufferedImage.TYPE_INT_BGR:
pixelType = PT_ABGR_8;
isIntPacked = true;
l.pixelType = PT_ABGR_8;
l.isIntPacked = true;
break;
case BufferedImage.TYPE_3BYTE_BGR:
pixelType = PT_BGR_8;
l.pixelType = PT_BGR_8;
break;
case BufferedImage.TYPE_4BYTE_ABGR:
pixelType = PT_ABGR_8;
l.pixelType = PT_ABGR_8;
break;
case BufferedImage.TYPE_BYTE_GRAY:
pixelType = PT_GRAY_8;
l.pixelType = PT_GRAY_8;
break;
case BufferedImage.TYPE_USHORT_GRAY:
pixelType = PT_GRAY_16;
l.pixelType = PT_GRAY_16;
break;
default:
// TODO: Add support for some images having
// SinglePixelPackedModel and ComponentSampleModel
throw new IllegalArgumentException(
"CMMImageLayout - bad image type passed to constructor");
/* ColorConvertOp creates component images as
* default destination, so this kind of images
* has to be supported.
*/
ColorModel cm = image.getColorModel();
if (cm instanceof ComponentColorModel) {
ComponentColorModel ccm = (ComponentColorModel) cm;
// verify whether the component size is fine
int[] cs = ccm.getComponentSize();
for (int s : cs) {
if (s != 8) {
return null;
}
}
return createImageLayout(image.getRaster());
}
return null;
}
width = image.getWidth();
height = image.getHeight();
l.width = image.getWidth();
l.height = image.getHeight();
switch (image.getType()) {
case BufferedImage.TYPE_INT_RGB:
case BufferedImage.TYPE_INT_ARGB:
case BufferedImage.TYPE_INT_BGR:
intRaster = (IntegerComponentRaster)image.getRaster();
nextRowOffset = intRaster.getScanlineStride()*4;
offset = intRaster.getDataOffset(0)*4;
dataArray = intRaster.getDataStorage();
dataType = DT_INT;
do {
IntegerComponentRaster intRaster = (IntegerComponentRaster)
image.getRaster();
l.nextRowOffset = intRaster.getScanlineStride() * 4;
l.offset = intRaster.getDataOffset(0) * 4;
l.dataArray = intRaster.getDataStorage();
l.dataType = DT_INT;
if (l.nextRowOffset == l.width * 4 * intRaster.getPixelStride()) {
l.imageAtOnce = true;
}
} while (false);
break;
case BufferedImage.TYPE_3BYTE_BGR:
case BufferedImage.TYPE_4BYTE_ABGR:
byteRaster = (ByteComponentRaster)image.getRaster();
nextRowOffset = byteRaster.getScanlineStride();
int firstBand = image.getSampleModel().getNumBands() - 1;
offset = byteRaster.getDataOffset(firstBand);
dataArray = byteRaster.getDataStorage();
dataType = DT_BYTE;
do {
ByteComponentRaster byteRaster = (ByteComponentRaster)
image.getRaster();
l.nextRowOffset = byteRaster.getScanlineStride();
int firstBand = image.getSampleModel().getNumBands() - 1;
l.offset = byteRaster.getDataOffset(firstBand);
l.dataArray = byteRaster.getDataStorage();
l.dataType = DT_BYTE;
if (l.nextRowOffset == l.width * byteRaster.getPixelStride()) {
l.imageAtOnce = true;
}
} while (false);
break;
case BufferedImage.TYPE_BYTE_GRAY:
byteRaster = (ByteComponentRaster)image.getRaster();
nextRowOffset = byteRaster.getScanlineStride();
offset = byteRaster.getDataOffset(0);
dataArray = byteRaster.getDataStorage();
dataType = DT_BYTE;
do {
ByteComponentRaster byteRaster = (ByteComponentRaster)
image.getRaster();
l.nextRowOffset = byteRaster.getScanlineStride();
l.offset = byteRaster.getDataOffset(0);
l.dataArray = byteRaster.getDataStorage();
l.dataType = DT_BYTE;
if (l.nextRowOffset == l.width * byteRaster.getPixelStride()) {
l.imageAtOnce = true;
}
} while (false);
break;
case BufferedImage.TYPE_USHORT_GRAY:
shortRaster = (ShortComponentRaster)image.getRaster();
nextRowOffset = shortRaster.getScanlineStride()*2;
offset = shortRaster.getDataOffset(0) * 2;
dataArray = shortRaster.getDataStorage();
dataType = DT_SHORT;
do {
ShortComponentRaster shortRaster = (ShortComponentRaster)
image.getRaster();
l.nextRowOffset = shortRaster.getScanlineStride() * 2;
l.offset = shortRaster.getDataOffset(0) * 2;
l.dataArray = shortRaster.getDataStorage();
l.dataType = DT_SHORT;
if (l.nextRowOffset == l.width * 2 * shortRaster.getPixelStride()) {
l.imageAtOnce = true;
}
} while (false);
break;
default:
return null;
}
return l;
}
public static boolean isSupported(BufferedImage image) {
switch (image.getType()) {
case BufferedImage.TYPE_INT_RGB:
case BufferedImage.TYPE_INT_ARGB:
case BufferedImage.TYPE_INT_BGR:
case BufferedImage.TYPE_3BYTE_BGR:
case BufferedImage.TYPE_4BYTE_ABGR:
case BufferedImage.TYPE_BYTE_GRAY:
case BufferedImage.TYPE_USHORT_GRAY:
return true;
private static enum BandOrder {
DIRECT,
INVERTED,
ARBITRARY,
UNKNOWN;
public static BandOrder getBandOrder(int[] bandOffsets) {
BandOrder order = UNKNOWN;
int numBands = bandOffsets.length;
for (int i = 0; (order != ARBITRARY) && (i < bandOffsets.length); i++) {
switch (order) {
case UNKNOWN:
if (bandOffsets[i] == i) {
order = DIRECT;
} else if (bandOffsets[i] == (numBands - 1 - i)) {
order = INVERTED;
} else {
order = ARBITRARY;
}
break;
case DIRECT:
if (bandOffsets[i] != i) {
order = ARBITRARY;
}
break;
case INVERTED:
if (bandOffsets[i] != (numBands - 1 - i)) {
order = ARBITRARY;
}
break;
}
}
return order;
}
}
public static LCMSImageLayout createImageLayout(Raster r) {
LCMSImageLayout l = new LCMSImageLayout();
if (r instanceof ByteComponentRaster) {
ByteComponentRaster br = (ByteComponentRaster)r;
ComponentSampleModel csm = (ComponentSampleModel)r.getSampleModel();
l.pixelType = CHANNELS_SH(br.getNumBands()) | BYTES_SH(1);
int[] bandOffsets = csm.getBandOffsets();
BandOrder order = BandOrder.getBandOrder(bandOffsets);
int firstBand = 0;
switch (order) {
case INVERTED:
l.pixelType |= DOSWAP;
firstBand = csm.getNumBands() - 1;
break;
case DIRECT:
// do nothing
break;
default:
// unable to create the image layout;
return null;
}
l.nextRowOffset = br.getScanlineStride();
l.offset = br.getDataOffset(firstBand);
l.dataArray = br.getDataStorage();
l.dataType = DT_BYTE;
l.width = br.getWidth();
l.height = br.getHeight();
if (l.nextRowOffset == l.width * br.getPixelStride()) {
l.imageAtOnce = true;
}
return l;
}
return false;
return null;
}
}
......@@ -161,13 +161,18 @@ public class LCMSTransform implements ColorTransform {
}
public void colorConvert(BufferedImage src, BufferedImage dst) {
if (LCMSImageLayout.isSupported(src) &&
LCMSImageLayout.isSupported(dst))
{
doTransform(new LCMSImageLayout(src), new LCMSImageLayout(dst));
return;
}
LCMSImageLayout srcIL, dstIL;
dstIL = LCMSImageLayout.createImageLayout(dst);
if (dstIL != null) {
srcIL = LCMSImageLayout.createImageLayout(src);
if (srcIL != null) {
doTransform(srcIL, dstIL);
return;
}
}
Raster srcRas = src.getRaster();
WritableRaster dstRas = dst.getRaster();
ColorModel srcCM = src.getColorModel();
......@@ -439,6 +444,14 @@ public class LCMSTransform implements ColorTransform {
public void colorConvert(Raster src, WritableRaster dst) {
LCMSImageLayout srcIL, dstIL;
dstIL = LCMSImageLayout.createImageLayout(dst);
if (dstIL != null) {
srcIL = LCMSImageLayout.createImageLayout(src);
if (srcIL != null) {
doTransform(srcIL, dstIL);
return;
}
}
// Can't pass src and dst directly to CMM, so process per scanline
SampleModel srcSM = src.getSampleModel();
SampleModel dstSM = dst.getSampleModel();
......
......@@ -52,7 +52,7 @@
<javac debug="flase" source="1.5" target="1.5" srcdir="${src}" destdir="${build}"/>
</target>
<target name="run" depends="dist"
<target name="run" depends="dist"
description="run J2DBench" >
<java jar="${dist}/J2DBench.jar"
fork="true"
......@@ -60,7 +60,7 @@
</java>
</target>
<target name="analyze" depends="dist"
<target name="analyze" depends="dist"
description="run J2DAnalyzer" >
<java jar="${dist}/J2DAnalyzer.jar"
fork="true"
......@@ -80,6 +80,10 @@
<copy todir="${build}/j2dbench/tests/iio/images">
<fileset dir="${resources}/images" />
</copy>
<mkdir dir="${build}/j2dbench/tests/cmm/images"/>
<copy todir="${build}/j2dbench/tests/cmm/images">
<fileset dir="${resources}/cmm_images" />
</copy>
</target>
<target name="dist" depends="compile, resources"
......@@ -88,14 +92,14 @@
<mkdir dir="${dist}"/>
<!-- Put everything in ${build} into the J2DBench.jar file -->
<jar jarfile="${dist}/J2DBench.jar" basedir="${build}"
<jar jarfile="${dist}/J2DBench.jar" basedir="${build}"
excludes="j2dbench/report/**" >
<manifest>
<attribute name="Built-By" value="${user.name}"/>
<attribute name="Main-Class" value="j2dbench.J2DBench"/>
</manifest>
</jar>
<jar jarfile="${dist}/J2DAnalyzer.jar" basedir="${build}"
<jar jarfile="${dist}/J2DAnalyzer.jar" basedir="${build}"
includes="j2dbench/report/**" >
<manifest>
<attribute name="Built-By" value="${user.name}"/>
......
......@@ -51,6 +51,7 @@ public class ColorConversionTests extends CMMTests {
DataConversionTests.init();
ColorConvertOpTests.init();
EmbeddedProfileTests.init();
}
protected ColorConversionTests(Group parent, String nodeName, String description) {
......
/*
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* This source code is provided to illustrate the usage of a given feature
* or technique and has been deliberately simplified. Additional steps
* required for a production-quality application, such as security checks,
* input validation and proper error handling, might not be present in
* this sample code.
*/
package j2dbench.tests.cmm;
import j2dbench.Group;
import j2dbench.Option;
import j2dbench.Result;
import j2dbench.TestEnvironment;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URL;
import javax.imageio.ImageIO;
import javax.imageio.ImageReader;
import javax.imageio.stream.ImageInputStream;
/* This benchmark verifies how changes in cmm library affects image decoding */
public class EmbeddedProfileTests extends ColorConversionTests {
protected static Group grpRoot;
protected static Group grpOptionsRoot;
protected static Option inputImages;
public static void init() {
grpRoot = new Group(colorConvRoot, "embed", "Embedded Profile Tests");
grpOptionsRoot = new Group(grpRoot, "embedOptions", "Options");
inputImages = createImageList();
new ReadImageTest();
}
private static enum IccImageResource {
SMALL("images/img_icc_small.jpg", "512x512", "Small: 512x512"),
MEDIUM("images/img_icc_medium.jpg", "2048x2048", "Medium: 2048x2048"),
LARGE("images/img_icc_large.jpg", "4096x4096", "Large: 4096x4096");
private IccImageResource(String file, String name, String description) {
this.url = CMMTests.class.getResource(file);
this.abbrev = name;
this.description = description;
}
public final URL url;
public final String abbrev;
public final String description;
}
private static Option createImageList() {
IccImageResource[] images = IccImageResource.values();
int num = images.length;
String[] names = new String[num];
String[] abbrev = new String[num];
String[] descr = new String[num];
for (int i = 0; i < num; i++) {
names[i] = images[i].toString();
abbrev[i] = images[i].abbrev;
descr[i] = images[i].description;
}
Option list = new Option.ObjectList(grpOptionsRoot,
"Images", "Input Images",
names, images, abbrev, descr, 1);
return list;
}
public EmbeddedProfileTests(Group parent, String nodeName, String description) {
super(parent, nodeName, description);
addDependencies(grpOptionsRoot, true);
}
private static class Context {
URL input;
public Context(TestEnvironment env, Result res) {
IccImageResource icc_input = (IccImageResource)
env.getModifier(inputImages);
input = icc_input.url;
}
}
public Object initTest(TestEnvironment env, Result res) {
return new Context(env, res);
}
public void cleanupTest(TestEnvironment env, Object o) {
Context ctx = (Context)o;
ctx.input = null;
}
private static class ReadImageTest extends EmbeddedProfileTests {
public ReadImageTest() {
super(grpRoot, "embd_img_read", "ImageReader.read()");
}
public void runTest(Object octx, int numReps) {
final Context ctx = (Context)octx;
final URL url = ctx.input;
ImageInputStream iis = null;
ImageReader reader = null;
try {
iis = ImageIO.createImageInputStream(url.openStream());
reader = ImageIO.getImageReaders(iis).next();
} catch (IOException e) {
throw new RuntimeException("Unable to run the becnhmark", e);
}
do {
try {
reader.setInput(iis);
BufferedImage img = reader.read(0);
reader.reset();
iis = ImageIO.createImageInputStream(url.openStream());
} catch (Exception e) {
e.printStackTrace();
}
} while (--numReps >= 0);
}
}
}
......@@ -117,6 +117,7 @@ static jfieldID IL_offset_fID;
static jfieldID IL_nextRowOffset_fID;
static jfieldID IL_width_fID;
static jfieldID IL_height_fID;
static jfieldID IL_imageAtOnce_fID;
static jfieldID PF_ID_fID;
JavaVM *javaVM;
......@@ -237,7 +238,7 @@ JNIEXPORT jlong JNICALL Java_sun_java2d_cmm_lcms_LCMS_createNativeTransform
* Method: loadProfile
* Signature: ([B)J
*/
JNIEXPORT jlong JNICALL Java_sun_java2d_cmm_lcms_LCMS_loadProfile
JNIEXPORT jlong JNICALL Java_sun_java2d_cmm_lcms_LCMS_loadProfileNative
(JNIEnv *env, jobject obj, jbyteArray data)
{
jbyte* dataArray;
......@@ -284,7 +285,7 @@ JNIEXPORT jlong JNICALL Java_sun_java2d_cmm_lcms_LCMS_loadProfile
* Method: freeProfile
* Signature: (J)V
*/
JNIEXPORT void JNICALL Java_sun_java2d_cmm_lcms_LCMS_freeProfile
JNIEXPORT void JNICALL Java_sun_java2d_cmm_lcms_LCMS_freeProfileNative
(JNIEnv *env, jobject obj, jlong id)
{
storeID_t sProf;
......@@ -369,48 +370,22 @@ static cmsBool _getHeaderInfo(cmsHPROFILE pf, jbyte* pBuffer, jint bufferSize);
static cmsBool _setHeaderInfo(cmsHPROFILE pf, jbyte* pBuffer, jint bufferSize);
static cmsBool _writeCookedTag(cmsHPROFILE pfTarget, cmsTagSignature sig, jbyte *pData, jint size);
/*
* Class: sun_java2d_cmm_lcms_LCMS
* Method: getTagSize
* Signature: (JI)I
*/
JNIEXPORT jint JNICALL Java_sun_java2d_cmm_lcms_LCMS_getTagSize
(JNIEnv *env, jobject obj, jlong id, jint tagSig)
{
storeID_t sProf;
TagSignature_t sig;
jint result = -1;
sProf.j = id;
sig.j = tagSig;
if (tagSig == SigHead) {
result = sizeof(cmsICCHeader);
} else {
if (cmsIsTag(sProf.pf, sig.cms)) {
result = cmsReadRawTag(sProf.pf, sig.cms, NULL, 0);
} else {
JNU_ThrowByName(env, "java/awt/color/CMMException",
"ICC profile tag not found");
}
}
return result;
}
/*
* Class: sun_java2d_cmm_lcms_LCMS
* Method: getTagData
* Signature: (JI[B)V
*/
JNIEXPORT void JNICALL Java_sun_java2d_cmm_lcms_LCMS_getTagData
(JNIEnv *env, jobject obj, jlong id, jint tagSig, jbyteArray data)
JNIEXPORT jbyteArray JNICALL Java_sun_java2d_cmm_lcms_LCMS_getTagNative
(JNIEnv *env, jobject obj, jlong id, jint tagSig)
{
storeID_t sProf;
TagSignature_t sig;
cmsInt32Number tagSize;
jbyte* dataArray;
jbyte* dataArray = NULL;
jbyteArray data = NULL;
jint bufSize;
sProf.j = id;
......@@ -419,12 +394,14 @@ JNIEXPORT void JNICALL Java_sun_java2d_cmm_lcms_LCMS_getTagData
if (tagSig == SigHead) {
cmsBool status;
bufSize =(*env)->GetArrayLength(env, data);
// allocate java array
bufSize = sizeof(cmsICCHeader);
data = (*env)->NewByteArray(env, bufSize);
if (bufSize < sizeof(cmsICCHeader)) {
JNU_ThrowByName(env, "java/awt/color/CMMException",
"Insufficient buffer capacity");
return;
if (data == NULL) {
JNU_ThrowByName(env, "java/awt/color/CMMException",
"Unable to allocate buffer");
return NULL;
}
dataArray = (*env)->GetByteArrayElements (env, data, 0);
......@@ -432,7 +409,7 @@ JNIEXPORT void JNICALL Java_sun_java2d_cmm_lcms_LCMS_getTagData
if (dataArray == NULL) {
JNU_ThrowByName(env, "java/awt/color/CMMException",
"Unable to get buffer");
return;
return NULL;
}
status = _getHeaderInfo(sProf.pf, dataArray, bufSize);
......@@ -442,9 +419,10 @@ JNIEXPORT void JNICALL Java_sun_java2d_cmm_lcms_LCMS_getTagData
if (!status) {
JNU_ThrowByName(env, "java/awt/color/CMMException",
"ICC Profile header not found");
return NULL;
}
return;
return data;
}
if (cmsIsTag(sProf.pf, sig.cms)) {
......@@ -452,16 +430,15 @@ JNIEXPORT void JNICALL Java_sun_java2d_cmm_lcms_LCMS_getTagData
} else {
JNU_ThrowByName(env, "java/awt/color/CMMException",
"ICC profile tag not found");
return;
return NULL;
}
// verify data buffer capacity
bufSize = (*env)->GetArrayLength(env, data);
if (tagSize < 0 || 0 > bufSize || tagSize > bufSize) {
// allocate java array
data = (*env)->NewByteArray(env, tagSize);
if (data == NULL) {
JNU_ThrowByName(env, "java/awt/color/CMMException",
"Insufficient buffer capacity.");
return;
"Unable to allocate buffer");
return NULL;
}
dataArray = (*env)->GetByteArrayElements (env, data, 0);
......@@ -469,7 +446,7 @@ JNIEXPORT void JNICALL Java_sun_java2d_cmm_lcms_LCMS_getTagData
if (dataArray == NULL) {
JNU_ThrowByName(env, "java/awt/color/CMMException",
"Unable to get buffer");
return;
return NULL;
}
bufSize = cmsReadRawTag(sProf.pf, sig.cms, dataArray, tagSize);
......@@ -479,8 +456,9 @@ JNIEXPORT void JNICALL Java_sun_java2d_cmm_lcms_LCMS_getTagData
if (bufSize != tagSize) {
JNU_ThrowByName(env, "java/awt/color/CMMException",
"Can not get tag data.");
return NULL;
}
return;
return data;
}
/*
......@@ -488,7 +466,7 @@ JNIEXPORT void JNICALL Java_sun_java2d_cmm_lcms_LCMS_getTagData
* Method: setTagData
* Signature: (JI[B)V
*/
JNIEXPORT void JNICALL Java_sun_java2d_cmm_lcms_LCMS_setTagData
JNIEXPORT void JNICALL Java_sun_java2d_cmm_lcms_LCMS_setTagDataNative
(JNIEnv *env, jobject obj, jlong id, jint tagSig, jbyteArray data)
{
storeID_t sProf;
......@@ -586,6 +564,7 @@ JNIEXPORT void JNICALL Java_sun_java2d_cmm_lcms_LCMS_colorConvert
char* inputRow;
char* outputRow;
jobject srcData, dstData;
jboolean srcAtOnce = JNI_FALSE, dstAtOnce = JNI_FALSE;
srcOffset = (*env)->GetIntField (env, src, IL_offset_fID);
srcNextRowOffset = (*env)->GetIntField (env, src, IL_nextRowOffset_fID);
......@@ -594,6 +573,9 @@ JNIEXPORT void JNICALL Java_sun_java2d_cmm_lcms_LCMS_colorConvert
width = (*env)->GetIntField (env, src, IL_width_fID);
height = (*env)->GetIntField (env, src, IL_height_fID);
srcAtOnce = (*env)->GetBooleanField(env, src, IL_imageAtOnce_fID);
dstAtOnce = (*env)->GetBooleanField(env, dst, IL_imageAtOnce_fID);
sTrans.j = (*env)->GetLongField (env, trans, Trans_ID_fID);
if (sTrans.xf == NULL) {
......@@ -625,10 +607,14 @@ JNIEXPORT void JNICALL Java_sun_java2d_cmm_lcms_LCMS_colorConvert
inputRow = (char*)inputBuffer + srcOffset;
outputRow = (char*)outputBuffer + dstOffset;
for (i = 0; i < height; i++) {
cmsDoTransform(sTrans.xf, inputRow, outputRow, width);
inputRow += srcNextRowOffset;
outputRow += dstNextRowOffset;
if (srcAtOnce && dstAtOnce) {
cmsDoTransform(sTrans.xf, inputRow, outputRow, width * height);
} else {
for (i = 0; i < height; i++) {
cmsDoTransform(sTrans.xf, inputRow, outputRow, width);
inputRow += srcNextRowOffset;
outputRow += dstNextRowOffset;
}
}
releaseILData(env, inputBuffer, srcDType, srcData);
......@@ -670,6 +656,7 @@ JNIEXPORT void JNICALL Java_sun_java2d_cmm_lcms_LCMS_initLCMS
IL_width_fID = (*env)->GetFieldID (env, IL, "width", "I");
IL_height_fID = (*env)->GetFieldID (env, IL, "height", "I");
IL_offset_fID = (*env)->GetFieldID (env, IL, "offset", "I");
IL_imageAtOnce_fID = (*env)->GetFieldID (env, IL, "imageAtOnce", "Z");
IL_nextRowOffset_fID = (*env)->GetFieldID (env, IL, "nextRowOffset", "I");
PF_ID_fID = (*env)->GetFieldID (env, Pf, "ID", "J");
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册