--- old/make/sun/cmm/lcms/Makefile 2012-12-27 15:35:10.744040800 +0400 +++ new/make/sun/cmm/lcms/Makefile 2012-12-27 15:35:10.572440500 +0400 @@ -28,6 +28,9 @@ LIBRARY = lcms PRODUCT = sun +# Use highest level of optimization on this library +OPTIMIZATION_LEVEL = HIGHEST + include $(BUILDDIR)/common/Defs.gmk # --- old/makefiles/CompileNativeLibraries.gmk 2012-12-27 15:35:12.116843200 +0400 +++ new/makefiles/CompileNativeLibraries.gmk 2012-12-27 15:35:11.945242900 +0400 @@ -1217,7 +1217,7 @@ 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 \ --- old/src/share/classes/sun/java2d/cmm/lcms/LCMSImageLayout.java 2012-12-27 15:35:13.786046100 +0400 +++ new/src/share/classes/sun/java2d/cmm/lcms/LCMSImageLayout.java 2012-12-27 15:35:13.583245800 +0400 @@ -25,18 +25,12 @@ 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.SampleModel; import sun.awt.image.ByteComponentRaster; import sun.awt.image.ShortComponentRaster; import sun.awt.image.IntegerComponentRaster; @@ -98,6 +92,12 @@ 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; @@ -142,95 +142,161 @@ dataArray = data; } - public LCMSImageLayout(BufferedImage image) { + 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(); + ShortComponentRaster shortRaster; IntegerComponentRaster intRaster; ByteComponentRaster byteRaster; 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; + } + } + + /* Make sure that band order in the raster + * is the natural color order for image's color space. + */ + SampleModel sm = image.getSampleModel(); + if (sm instanceof ComponentSampleModel) { + ComponentSampleModel csm = (ComponentSampleModel) sm; + + if (csm.getTransferType() != DataBuffer.TYPE_BYTE) { + // We may consider to support other data types later. + return null; + } + int[] bandOffsets = csm.getBandOffsets(); + for (int i = 0; i < bandOffsets.length; i++) { + /* Now we accept only natural order of color bands, + * but the reversed order also can be handled with + * SWAP flag in the pixel format descriptor. + */ + if (bandOffsets[i] != i) { + return null; + } + } + } + l.pixelType = CHANNELS_SH(cs.length) | BYTES_SH(1); + byteRaster = (ByteComponentRaster) image.getRaster(); + l.nextRowOffset = byteRaster.getScanlineStride(); + l.offset = byteRaster.getDataOffset(0); + l.dataArray = byteRaster.getDataStorage(); + l.dataType = DT_BYTE; + + l.width = image.getWidth(); + l.height = image.getHeight(); + + if (l.nextRowOffset == l.width * byteRaster.getPixelStride()) { + l.imageAtOnce = true; + } + + return l; + + } else { + 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; + 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; + } break; case BufferedImage.TYPE_3BYTE_BGR: case BufferedImage.TYPE_4BYTE_ABGR: - byteRaster = (ByteComponentRaster)image.getRaster(); - nextRowOffset = byteRaster.getScanlineStride(); + byteRaster = (ByteComponentRaster) image.getRaster(); + l.nextRowOffset = byteRaster.getScanlineStride(); int firstBand = image.getSampleModel().getNumBands() - 1; - offset = byteRaster.getDataOffset(firstBand); - dataArray = byteRaster.getDataStorage(); - dataType = DT_BYTE; + l.offset = byteRaster.getDataOffset(firstBand); + l.dataArray = byteRaster.getDataStorage(); + l.dataType = DT_BYTE; + if (l.nextRowOffset == l.width * byteRaster.getPixelStride()) { + l.imageAtOnce = true; + } break; case BufferedImage.TYPE_BYTE_GRAY: byteRaster = (ByteComponentRaster)image.getRaster(); - nextRowOffset = byteRaster.getScanlineStride(); - offset = byteRaster.getDataOffset(0); - dataArray = byteRaster.getDataStorage(); - dataType = DT_BYTE; + 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; + } 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; + 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; + } break; + default: + return null; } - } - - 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; - } - return false; + return l; } } --- old/src/share/classes/sun/java2d/cmm/lcms/LCMSTransform.java 2012-12-27 15:35:15.205648600 +0400 +++ new/src/share/classes/sun/java2d/cmm/lcms/LCMSTransform.java 2012-12-27 15:35:15.018448300 +0400 @@ -161,13 +161,18 @@ } 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(); --- old/src/share/native/sun/java2d/cmm/lcms/LCMS.c 2012-12-27 15:35:16.734451300 +0400 +++ new/src/share/native/sun/java2d/cmm/lcms/LCMS.c 2012-12-27 15:35:16.516050900 +0400 @@ -117,6 +117,7 @@ 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; @@ -586,6 +587,7 @@ 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 +596,9 @@ 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 +630,14 @@ 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 +679,7 @@ 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");