feat(jdk8): move files to new folder to avoid resources compiled.

This commit is contained in:
2025-09-07 15:25:52 +08:00
parent 3f0047bf6f
commit 8c35cfb1c0
17415 changed files with 217 additions and 213 deletions

View File

@@ -0,0 +1,37 @@
/*
* Copyright (c) 2013, 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
package sun.java2d.cmm;
public abstract class CMMServiceProvider {
public final PCMM getColorManagementModule() {
if (CMSManager.canCreateModule()) {
return getModule();
}
return null;
}
protected abstract PCMM getModule();
}

View File

@@ -0,0 +1,177 @@
/*
* Copyright (c) 2006, 2013, 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
package sun.java2d.cmm;
import java.awt.color.ColorSpace;
import java.awt.color.ICC_Profile;
import java.awt.color.CMMException;
import java.awt.image.BufferedImage;
import java.awt.image.Raster;
import java.awt.image.WritableRaster;
import java.security.AccessController;
import java.security.PrivilegedAction;
import sun.security.action.GetPropertyAction;
import java.util.ServiceLoader;
public class CMSManager {
public static ColorSpace GRAYspace; // These two fields allow access
public static ColorSpace LINEAR_RGBspace; // to java.awt.color.ColorSpace
// private fields from other
// packages. The fields are set
// by java.awt.color.ColorSpace
// and read by
// java.awt.image.ColorModel.
private static PCMM cmmImpl = null;
public static synchronized PCMM getModule() {
if (cmmImpl != null) {
return cmmImpl;
}
CMMServiceProvider spi = AccessController.doPrivileged(
new PrivilegedAction<CMMServiceProvider>() {
public CMMServiceProvider run() {
String cmmClass = System.getProperty(
"sun.java2d.cmm", "sun.java2d.cmm.lcms.LcmsServiceProvider");
ServiceLoader<CMMServiceProvider> cmmLoader
= ServiceLoader.loadInstalled(CMMServiceProvider.class);
CMMServiceProvider spi = null;
for (CMMServiceProvider cmm : cmmLoader) {
spi = cmm;
if (cmm.getClass().getName().equals(cmmClass)) {
break;
}
}
return spi;
}
});
cmmImpl = spi.getColorManagementModule();
if (cmmImpl == null) {
throw new CMMException("Cannot initialize Color Management System."+
"No CM module found");
}
GetPropertyAction gpa = new GetPropertyAction("sun.java2d.cmm.trace");
String cmmTrace = (String)AccessController.doPrivileged(gpa);
if (cmmTrace != null) {
cmmImpl = new CMMTracer(cmmImpl);
}
return cmmImpl;
}
static synchronized boolean canCreateModule() {
return (cmmImpl == null);
}
/* CMM trace routines */
public static class CMMTracer implements PCMM {
PCMM tcmm;
String cName ;
public CMMTracer(PCMM tcmm) {
this.tcmm = tcmm;
cName = tcmm.getClass().getName();
}
public Profile loadProfile(byte[] data) {
System.err.print(cName + ".loadProfile");
Profile p = tcmm.loadProfile(data);
System.err.printf("(ID=%s)\n", p.toString());
return p;
}
public void freeProfile(Profile p) {
System.err.printf(cName + ".freeProfile(ID=%s)\n", p.toString());
tcmm.freeProfile(p);
}
public int getProfileSize(Profile p) {
System.err.print(cName + ".getProfileSize(ID=" + p + ")");
int size = tcmm.getProfileSize(p);
System.err.println("=" + size);
return size;
}
public void getProfileData(Profile p, byte[] data) {
System.err.print(cName + ".getProfileData(ID=" + p + ") ");
System.err.println("requested " + data.length + " byte(s)");
tcmm.getProfileData(p, data);
}
public int getTagSize(Profile p, int tagSignature) {
System.err.printf(cName + ".getTagSize(ID=%x, TagSig=%s)",
p, signatureToString(tagSignature));
int size = tcmm.getTagSize(p, tagSignature);
System.err.println("=" + size);
return size;
}
public void getTagData(Profile p, int tagSignature,
byte[] data) {
System.err.printf(cName + ".getTagData(ID=%x, TagSig=%s)",
p, signatureToString(tagSignature));
System.err.println(" requested " + data.length + " byte(s)");
tcmm.getTagData(p, tagSignature, data);
}
public void setTagData(Profile p, int tagSignature,
byte[] data) {
System.err.print(cName + ".setTagData(ID=" + p +
", TagSig=" + tagSignature + ")");
System.err.println(" sending " + data.length + " byte(s)");
tcmm.setTagData(p, tagSignature, data);
}
/* methods for creating ColorTransforms */
public ColorTransform createTransform(ICC_Profile profile,
int renderType,
int transformType) {
System.err.println(cName + ".createTransform(ICC_Profile,int,int)");
return tcmm.createTransform(profile, renderType, transformType);
}
public ColorTransform createTransform(ColorTransform[] transforms) {
System.err.println(cName + ".createTransform(ColorTransform[])");
return tcmm.createTransform(transforms);
}
private static String signatureToString(int sig) {
return String.format("%c%c%c%c",
(char)(0xff & (sig >> 24)),
(char)(0xff & (sig >> 16)),
(char)(0xff & (sig >> 8)),
(char)(0xff & (sig )));
}
}
}

View File

@@ -0,0 +1,53 @@
/*
* Copyright (c) 2006, 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
package sun.java2d.cmm;
import java.awt.image.BufferedImage;
import java.awt.image.Raster;
import java.awt.image.WritableRaster;
public interface ColorTransform {
public int Any = -1;/* any rendering type, whichever is
available */
/* search order is icPerceptual,
icRelativeColorimetric, icSaturation */
/* Transform types */
public int In = 1;
public int Out = 2;
public int Gamut = 3;
public int Simulation = 4;
public int getNumInComponents();
public int getNumOutComponents();
public void colorConvert(BufferedImage src, BufferedImage dst);
public void colorConvert(Raster src, WritableRaster dst,
float[] srcMinVal, float[]srcMaxVal,
float[] dstMinVal, float[]dstMaxVal);
public void colorConvert(Raster src, WritableRaster dst);
public short[] colorConvert(short[] src, short[] dest);
public byte[] colorConvert (byte[] src, byte[] dest);
}

View File

@@ -0,0 +1,48 @@
/*
* Copyright (c) 2006, 2013, 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
package sun.java2d.cmm;
import java.awt.color.ICC_Profile;
/* Pluggable CMM interface */
public interface PCMM {
/* methods invoked from ICC_Profile */
public Profile loadProfile(byte[] data);
public void freeProfile(Profile p);
public int getProfileSize(Profile p);
public void getProfileData(Profile p, byte[] data);
public void getTagData(Profile p, int tagSignature, byte[] data);
public int getTagSize(Profile p, int tagSignature);
public void setTagData(Profile p, int tagSignature, byte[] data);
/* methods for creating ColorTransforms */
public ColorTransform createTransform(ICC_Profile profile, int renderType,
int transformType);
public ColorTransform createTransform(ColorTransform[] transforms);
}

View File

@@ -0,0 +1,43 @@
/*
* Copyright (c) 2013, 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
package sun.java2d.cmm;
import java.awt.color.CMMException;
public class Profile {
private final long nativePtr;
protected Profile(long ptr) {
nativePtr = ptr;
}
protected final long getNativePtr() {
if (nativePtr == 0L) {
throw new CMMException("Invalid profile: ptr is null");
}
return nativePtr;
}
}

View File

@@ -0,0 +1,41 @@
/*
* Copyright (c) 1998, 2006, 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
package sun.java2d.cmm;
import java.awt.color.ProfileDataException;
/**
* An interface to allow the ProfileDeferralMgr to activate a
* deferred profile.
*/
public interface ProfileActivator {
/**
* Activate a previously deferred ICC_Profile object.
*/
public void activate() throws ProfileDataException;
}

View File

@@ -0,0 +1,114 @@
/*
* Copyright (c) 2013, 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
package sun.java2d.cmm;
public class ProfileDataVerifier {
/**
* Throws an IllegalArgumentException if the data does not correspond
* to a valid ICC Profile.
*
* @param data the specified profile data.
*/
public static void verify(byte[] data) {
if (data == null) {
throw new IllegalArgumentException("Invalid ICC Profile Data");
}
if (data.length < TOC_OFFSET) {
// not enough data for profile header
throw new IllegalArgumentException("Invalid ICC Profile Data");
}
// check profile size
final int size = readInt32(data, 0);
final int tagCount = readInt32(data, HEADER_SIZE);
if (tagCount < 0 || tagCount > MAX_TAG_COUNT) {
throw new IllegalArgumentException("Invalid ICC Profile Data");
}
if (size < (TOC_OFFSET + (tagCount * TOC_RECORD_SIZE)) ||
size > data.length)
{
throw new IllegalArgumentException("Invalid ICC Profile Data");
}
final int sig = readInt32(data, 36);
if (PROFILE_FILE_SIGNATURE != sig) {
throw new IllegalArgumentException("Invalid ICC Profile Data");
}
// verify table of content
for (int i = 0; i < tagCount; i++) {
final int tag_offset = getTagOffset(i, data);
final int tag_size = getTagSize(i, data);
if (tag_offset < TOC_OFFSET || tag_offset > size) {
throw new IllegalArgumentException("Invalid ICC Profile Data");
}
if (tag_size < 0 ||
tag_size > (Integer.MAX_VALUE - tag_offset) ||
tag_size + tag_offset > size)
{
throw new IllegalArgumentException("Invalid ICC Profile Data");
}
}
}
private static int getTagOffset(int idx, byte[] data) {
final int pos = TOC_OFFSET + idx * TOC_RECORD_SIZE + 4;
return readInt32(data, pos);
}
private static int getTagSize(int idx, byte[] data) {
final int pos = TOC_OFFSET + idx * TOC_RECORD_SIZE + 8;
return readInt32(data, pos);
}
private static int readInt32(byte[] data, int off) {
int res = 0;
for (int i = 0; i < 4; i++) {
res = res << 8;
res |= (0xff & data[off++]);
}
return res;
}
/**
* Lcms limit for the number of tags: 100
* Kcms limit for the number of tags: N/A
*/
private static final int MAX_TAG_COUNT = 100;
private static final int HEADER_SIZE = 128;
private static final int TOC_OFFSET = HEADER_SIZE + 4;
private static final int TOC_RECORD_SIZE = 12;
private static final int PROFILE_FILE_SIGNATURE = 0x61637370;
}

View File

@@ -0,0 +1,61 @@
/*
* Copyright (c) 1998, 2006, 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
package sun.java2d.cmm;
import java.io.InputStream;
import java.io.IOException;
/**
* A class to pass information about a profile to be loaded from
* a file to the static getInstance(InputStream) method of
* ICC_Profile. Loading of the profile data and initialization
* of the CMM is to be deferred as long as possible.
*/
public class ProfileDeferralInfo extends InputStream {
public int colorSpaceType, numComponents, profileClass;
public String filename;
public ProfileDeferralInfo(String fn, int type, int ncomp, int pclass) {
super();
filename = fn;
colorSpaceType = type;
numComponents = ncomp;
profileClass = pclass;
}
/**
* Implements the abstract read() method of InputStream.
*/
public int read() throws IOException {
return 0;
}
}

View File

@@ -0,0 +1,119 @@
/*
* Copyright (c) 1998, 2006, 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
package sun.java2d.cmm;
import java.awt.color.ProfileDataException;
import java.util.Vector;
/**
* A class to manage the deferral of CMM initialization of profile
* data for internal ICC_Profile objects - i.e. when we "trust" that
* the profile data is valid and we think it may not be needed. An
* example is the sRGB profile which gets loaded by any program doing
* graphics, but which may not be needed if the program does not need
* high quality color conversion.
*/
public class ProfileDeferralMgr {
public static boolean deferring = true;
private static Vector<ProfileActivator> aVector;
/**
* Records a ProfileActivator object whose activate method will
* be called if the CMM needs to be activated.
*/
public static void registerDeferral(ProfileActivator pa) {
if (!deferring) {
return;
}
if (aVector == null) {
aVector = new Vector<ProfileActivator>(3, 3);
}
aVector.addElement(pa);
return;
}
/**
* Removes a ProfileActivator object from the vector of ProfileActivator
* objects whose activate method will be called if the CMM needs to be
* activated.
*/
public static void unregisterDeferral(ProfileActivator pa) {
if (!deferring) {
return;
}
if (aVector == null) {
return;
}
aVector.removeElement(pa);
return;
}
/**
* Removes a ProfileActivator object from the vector of ProfileActivator
* objects whose activate method will be called if the CMM needs to be
* activated.
*/
public static void activateProfiles() {
int i, n;
deferring = false;
if (aVector == null) {
return;
}
n = aVector.size();
for (ProfileActivator pa : aVector) {
try {
pa.activate();
} catch (ProfileDataException e) {
/*
* Ignore profile activation error for now:
* such exception is pssible due to absence
* or corruption of standard color profile.
* As for now we expect all profiles should
* be shiped with jre and presence of this
* exception is indication of some configuration
* problem in jre installation.
*
* NB: we still are greedy loading deferred profiles
* and load them all if any of them is needed.
* Therefore broken profile (if any) might be never used.
* If there will be attempt to use broken profile then
* it will result in CMMException.
*/
}
}
aVector.removeAllElements();
aVector = null;
return;
}
}

View File

@@ -0,0 +1,221 @@
/*
* Copyright (c) 2007, 2013, 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
package sun.java2d.cmm.lcms;
import java.awt.color.CMMException;
import java.awt.color.ICC_Profile;
import sun.java2d.cmm.ColorTransform;
import sun.java2d.cmm.PCMM;
import sun.java2d.cmm.Profile;
import sun.java2d.cmm.lcms.LCMSProfile.TagData;
public class LCMS implements PCMM {
/* methods invoked from ICC_Profile */
@Override
public Profile loadProfile(byte[] data) {
final Object disposerRef = new Object();
final long ptr = loadProfileNative(data, disposerRef);
if (ptr != 0L) {
return new LCMSProfile(ptr, disposerRef);
}
return null;
}
private native long loadProfileNative(byte[] data, Object ref);
private LCMSProfile getLcmsProfile(Profile p) {
if (p instanceof LCMSProfile) {
return (LCMSProfile)p;
}
throw new CMMException("Invalid profile: " + p);
}
@Override
public void freeProfile(Profile p) {
// we use disposer, so this method does nothing
}
@Override
public int getProfileSize(final Profile p) {
synchronized (p) {
return getProfileSizeNative(getLcmsProfile(p).getLcmsPtr());
}
}
private native int getProfileSizeNative(long ptr);
@Override
public void getProfileData(final Profile p, byte[] data) {
synchronized (p) {
getProfileDataNative(getLcmsProfile(p).getLcmsPtr(), data);
}
}
private native void getProfileDataNative(long ptr, byte[] data);
@Override
public int getTagSize(Profile p, int tagSignature) {
final LCMSProfile profile = getLcmsProfile(p);
synchronized (profile) {
TagData t = profile.getTag(tagSignature);
return t == null ? 0 : t.getSize();
}
}
static native byte[] getTagNative(long profileID, int signature);
@Override
public void getTagData(Profile p, int tagSignature, byte[] data)
{
final LCMSProfile profile = getLcmsProfile(p);
synchronized (profile) {
TagData t = profile.getTag(tagSignature);
if (t != null) {
t.copyDataTo(data);
}
}
}
@Override
public synchronized void setTagData(Profile p, int tagSignature, byte[] data) {
final LCMSProfile profile = getLcmsProfile(p);
synchronized (profile) {
profile.clearTagCache();
// Now we are going to update the profile with new tag data
// In some cases, we may change the pointer to the native
// profile.
//
// If we fail to write tag data for any reason, the old pointer
// should be used.
setTagDataNative(profile.getLcmsPtr(),
tagSignature, data);
}
}
/**
* Writes supplied data as a tag into the profile.
* Destroys old profile, if new one was successfully
* created.
*
* Returns valid pointer to new profile.
*
* Throws CMMException if operation fails, preserve old profile from
* destruction.
*/
private native void setTagDataNative(long ptr, int tagSignature,
byte[] data);
public synchronized static native LCMSProfile getProfileID(ICC_Profile profile);
/* Helper method used from LCMSColorTransfrom */
static long createTransform(
LCMSProfile[] profiles, int renderType,
int inFormatter, boolean isInIntPacked,
int outFormatter, boolean isOutIntPacked,
Object disposerRef)
{
long[] ptrs = new long[profiles.length];
for (int i = 0; i < profiles.length; i++) {
if (profiles[i] == null) throw new CMMException("Unknown profile ID");
ptrs[i] = profiles[i].getLcmsPtr();
}
return createNativeTransform(ptrs, renderType, inFormatter,
isInIntPacked, outFormatter, isOutIntPacked, disposerRef);
}
private static native long createNativeTransform(
long[] profileIDs, int renderType,
int inFormatter, boolean isInIntPacked,
int outFormatter, boolean isOutIntPacked,
Object disposerRef);
/**
* Constructs ColorTransform object corresponding to an ICC_profile
*/
public ColorTransform createTransform(ICC_Profile profile,
int renderType,
int transformType)
{
return new LCMSTransform(profile, renderType, renderType);
}
/**
* Constructs an ColorTransform object from a list of ColorTransform
* objects
*/
public synchronized ColorTransform createTransform(
ColorTransform[] transforms)
{
return new LCMSTransform(transforms);
}
/* methods invoked from LCMSTransform */
public static native void colorConvert(LCMSTransform trans,
LCMSImageLayout src,
LCMSImageLayout dest);
public static native void freeTransform(long ID);
public static native void initLCMS(Class Trans, Class IL, Class Pf);
private LCMS() {};
private static LCMS theLcms = null;
static synchronized PCMM getModule() {
if (theLcms != null) {
return theLcms;
}
java.security.AccessController.doPrivileged(
new java.security.PrivilegedAction() {
public Object run() {
/* We need to load awt here because of usage trace and
* disposer frameworks
*/
System.loadLibrary("awt");
System.loadLibrary("lcms");
return null;
}
});
initLCMS(LCMSTransform.class, LCMSImageLayout.class, ICC_Profile.class);
theLcms = new LCMS();
return theLcms;
}
}

View File

@@ -0,0 +1,449 @@
/*
* Copyright (c) 2007, 2013, 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
package sun.java2d.cmm.lcms;
import java.awt.image.BufferedImage;
import java.awt.image.ComponentColorModel;
import java.awt.image.ComponentSampleModel;
import java.awt.image.DataBuffer;
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) {
return x;
}
public static int EXTRA_SH(int x) {
return x << 7;
}
public static int CHANNELS_SH(int x) {
return x << 3;
}
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);
public static final int PT_GRAY_8 =
CHANNELS_SH(1) | BYTES_SH(1);
public static final int PT_GRAY_16 =
CHANNELS_SH(1) | BYTES_SH(2);
public static final int PT_RGBA_8 =
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;
public static final int PT_BGR_8 =
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;
boolean isIntPacked = false;
int pixelType;
int dataType;
int width;
int height;
int nextRowOffset;
private int nextPixelOffset;
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 int dataArrayLength; /* in bytes */
private LCMSImageLayout(int np, int pixelType, int pixelSize)
throws ImageLayoutException
{
this.pixelType = pixelType;
width = np;
height = 1;
nextPixelOffset = pixelSize;
nextRowOffset = safeMult(pixelSize, np);
offset = 0;
}
private LCMSImageLayout(int width, int height, int pixelType,
int pixelSize)
throws ImageLayoutException
{
this.pixelType = pixelType;
this.width = width;
this.height = height;
nextPixelOffset = pixelSize;
nextRowOffset = safeMult(pixelSize, width);
offset = 0;
}
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)
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)
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();
}
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) throws ImageLayoutException {
LCMSImageLayout l = new LCMSImageLayout();
switch (image.getType()) {
case BufferedImage.TYPE_INT_RGB:
l.pixelType = PT_ARGB_8;
l.isIntPacked = true;
break;
case BufferedImage.TYPE_INT_ARGB:
l.pixelType = PT_ARGB_8;
l.isIntPacked = true;
break;
case BufferedImage.TYPE_INT_BGR:
l.pixelType = PT_ABGR_8;
l.isIntPacked = true;
break;
case BufferedImage.TYPE_3BYTE_BGR:
l.pixelType = PT_BGR_8;
break;
case BufferedImage.TYPE_4BYTE_ABGR:
l.pixelType = PT_ABGR_8;
break;
case BufferedImage.TYPE_BYTE_GRAY:
l.pixelType = PT_GRAY_8;
break;
case BufferedImage.TYPE_USHORT_GRAY:
l.pixelType = PT_GRAY_16;
break;
default:
/* 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;
}
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:
do {
IntegerComponentRaster intRaster = (IntegerComponentRaster)
image.getRaster();
l.nextRowOffset = safeMult(4, intRaster.getScanlineStride());
l.nextPixelOffset = safeMult(4, intRaster.getPixelStride());
l.offset = safeMult(4, intRaster.getDataOffset(0));
l.dataArray = intRaster.getDataStorage();
l.dataArrayLength = 4 * intRaster.getDataStorage().length;
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:
do {
ByteComponentRaster byteRaster = (ByteComponentRaster)
image.getRaster();
l.nextRowOffset = byteRaster.getScanlineStride();
l.nextPixelOffset = byteRaster.getPixelStride();
int firstBand = image.getSampleModel().getNumBands() - 1;
l.offset = byteRaster.getDataOffset(firstBand);
l.dataArray = byteRaster.getDataStorage();
l.dataArrayLength = byteRaster.getDataStorage().length;
l.dataType = DT_BYTE;
if (l.nextRowOffset == l.width * byteRaster.getPixelStride()) {
l.imageAtOnce = true;
}
} while (false);
break;
case BufferedImage.TYPE_BYTE_GRAY:
do {
ByteComponentRaster byteRaster = (ByteComponentRaster)
image.getRaster();
l.nextRowOffset = byteRaster.getScanlineStride();
l.nextPixelOffset = byteRaster.getPixelStride();
l.dataArrayLength = byteRaster.getDataStorage().length;
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:
do {
ShortComponentRaster shortRaster = (ShortComponentRaster)
image.getRaster();
l.nextRowOffset = safeMult(2, shortRaster.getScanlineStride());
l.nextPixelOffset = safeMult(2, shortRaster.getPixelStride());
l.offset = safeMult(2, shortRaster.getDataOffset(0));
l.dataArray = shortRaster.getDataStorage();
l.dataArrayLength = 2 * shortRaster.getDataStorage().length;
l.dataType = DT_SHORT;
if (l.nextRowOffset == l.width * 2 * shortRaster.getPixelStride()) {
l.imageAtOnce = true;
}
} while (false);
break;
default:
return null;
}
l.verify();
return l;
}
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;
}
}
private void verify() throws ImageLayoutException {
if (offset < 0 || offset >= dataArrayLength) {
throw new ImageLayoutException("Invalid image layout");
}
if (nextPixelOffset != getBytesPerPixel(pixelType)) {
throw new ImageLayoutException("Invalid image layout");
}
int lastScanOffset = safeMult(nextRowOffset, (height - 1));
int lastPixelOffset = safeMult(nextPixelOffset, (width -1 ));
lastPixelOffset = safeAdd(lastPixelOffset, lastScanOffset);
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);
}
}
public static LCMSImageLayout createImageLayout(Raster r) {
LCMSImageLayout l = new LCMSImageLayout();
if (r instanceof ByteComponentRaster &&
r.getSampleModel() instanceof ComponentSampleModel) {
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.nextPixelOffset = br.getPixelStride();
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 null;
}
/**
* Derives number of bytes per pixel from the pixel format.
* Following bit fields are used here:
* [0..2] - bytes per sample
* [3..6] - number of color samples per pixel
* [7..9] - number of non-color samples per pixel
*
* A complete description of the pixel format can be found
* here: lcms2.h, lines 651 - 667.
*
* @param pixelType pixel format in lcms2 notation.
* @return number of bytes per pixel for given pixel format.
*/
private static int getBytesPerPixel(int pixelType) {
int bytesPerSample = (0x7 & pixelType);
int colorSamplesPerPixel = 0xF & (pixelType >> 3);
int extraSamplesPerPixel = 0x7 & (pixelType >> 7);
return bytesPerSample * (colorSamplesPerPixel + extraSamplesPerPixel);
}
}

View File

@@ -0,0 +1,109 @@
/*
* Copyright (c) 2013, 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
package sun.java2d.cmm.lcms;
import java.awt.color.CMMException;
import java.util.Arrays;
import java.util.HashMap;
import sun.java2d.cmm.Profile;
final class LCMSProfile extends Profile {
private final TagCache tagCache;
private final Object disposerReferent;
LCMSProfile(long ptr, Object ref) {
super(ptr);
disposerReferent = ref;
tagCache = new TagCache(this);
}
final long getLcmsPtr() {
return this.getNativePtr();
}
TagData getTag(int sig) {
return tagCache.getTag(sig);
}
void clearTagCache() {
tagCache.clear();
}
static class TagCache {
final LCMSProfile profile;
private HashMap<Integer, TagData> tags;
TagCache(LCMSProfile p) {
profile = p;
tags = new HashMap<>();
}
TagData getTag(int sig) {
TagData t = tags.get(sig);
if (t == null) {
byte[] tagData = LCMS.getTagNative(profile.getNativePtr(), sig);
if (tagData != null) {
t = new TagData(sig, tagData);
tags.put(sig, t);
}
}
return t;
}
void clear() {
tags.clear();
}
}
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;
}
}
}

View File

@@ -0,0 +1,660 @@
/*
* Copyright (c) 2007, 2013, 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
/**********************************************************************
**********************************************************************
**********************************************************************
*** COPYRIGHT (c) Eastman Kodak Company, 1997 ***
*** As an unpublished work pursuant to Title 17 of the United ***
*** States Code. All rights reserved. ***
**********************************************************************
**********************************************************************
**********************************************************************/
package sun.java2d.cmm.lcms;
import java.awt.color.ICC_Profile;
import java.awt.color.ProfileDataException;
import java.awt.color.CMMException;
import java.awt.color.ColorSpace;
import java.awt.image.BufferedImage;
import java.awt.image.Raster;
import java.awt.image.WritableRaster;
import java.awt.image.ColorModel;
import java.awt.image.DirectColorModel;
import java.awt.image.ComponentColorModel;
import java.awt.image.SampleModel;
import java.awt.image.DataBuffer;
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 {
long ID;
private int inFormatter = 0;
private boolean isInIntPacked = false;
private int outFormatter = 0;
private boolean isOutIntPacked = false;
ICC_Profile[] profiles;
LCMSProfile[] lcmsProfiles;
int renderType;
int transformType;
private int numInComponents = -1;
private int numOutComponents = -1;
private Object disposerReferent = new Object();
/* the class initializer */
static {
if (ProfileDeferralMgr.deferring) {
ProfileDeferralMgr.activateProfiles();
}
}
public LCMSTransform(ICC_Profile profile, int renderType,
int transformType)
{
/* Actually, it is not a complete transform but just part of it */
profiles = new ICC_Profile[1];
profiles[0] = profile;
lcmsProfiles = new LCMSProfile[1];
lcmsProfiles[0] = LCMS.getProfileID(profile);
this.renderType = (renderType == ColorTransform.Any)?
ICC_Profile.icPerceptual : renderType;
this.transformType = transformType;
/* Note that ICC_Profile.getNumComponents() is quite expensive
* (it may results in a reading of the profile header).
* So, here we cache the number of components of input and
* output profiles for further usage.
*/
numInComponents = profiles[0].getNumComponents();
numOutComponents = profiles[profiles.length - 1].getNumComponents();
}
public LCMSTransform (ColorTransform[] transforms) {
int size = 0;
for (int i=0; i < transforms.length; i++) {
size+=((LCMSTransform)transforms[i]).profiles.length;
}
profiles = new ICC_Profile[size];
lcmsProfiles = new LCMSProfile[size];
int j = 0;
for (int i=0; i < transforms.length; i++) {
LCMSTransform curTrans = (LCMSTransform)transforms[i];
System.arraycopy(curTrans.profiles, 0, profiles, j,
curTrans.profiles.length);
System.arraycopy(curTrans.lcmsProfiles, 0, lcmsProfiles, j,
curTrans.lcmsProfiles.length);
j += curTrans.profiles.length;
}
renderType = ((LCMSTransform)transforms[0]).renderType;
/* Note that ICC_Profile.getNumComponents() is quite expensive
* (it may results in a reading of the profile header).
* So, here we cache the number of components of input and
* output profiles for further usage.
*/
numInComponents = profiles[0].getNumComponents();
numOutComponents = profiles[profiles.length - 1].getNumComponents();
}
public int getNumInComponents() {
return numInComponents;
}
public int getNumOutComponents() {
return numOutComponents;
}
private synchronized void doTransform(LCMSImageLayout in,
LCMSImageLayout out) {
// update native transfrom if needed
if (ID == 0L ||
inFormatter != in.pixelType || isInIntPacked != in.isIntPacked ||
outFormatter != out.pixelType || isOutIntPacked != out.isIntPacked)
{
if (ID != 0L) {
// Disposer will destroy forgotten transform
disposerReferent = new Object();
}
inFormatter = in.pixelType;
isInIntPacked = in.isIntPacked;
outFormatter = out.pixelType;
isOutIntPacked = out.isIntPacked;
ID = LCMS.createTransform(lcmsProfiles, renderType,
inFormatter, isInIntPacked,
outFormatter, isOutIntPacked,
disposerReferent);
}
LCMS.colorConvert(this, in, out);
}
public void colorConvert(BufferedImage src, BufferedImage dst) {
LCMSImageLayout srcIL, dstIL;
try {
if (!dst.getColorModel().hasAlpha()) {
dstIL = LCMSImageLayout.createImageLayout(dst);
if (dstIL != null) {
srcIL = LCMSImageLayout.createImageLayout(src);
if (srcIL != null) {
doTransform(srcIL, dstIL);
return;
}
}
}
} catch (ImageLayoutException e) {
throw new CMMException("Unable to convert images");
}
Raster srcRas = src.getRaster();
WritableRaster dstRas = dst.getRaster();
ColorModel srcCM = src.getColorModel();
ColorModel dstCM = dst.getColorModel();
int w = src.getWidth();
int h = src.getHeight();
int srcNumComp = srcCM.getNumColorComponents();
int dstNumComp = dstCM.getNumColorComponents();
int precision = 8;
float maxNum = 255.0f;
for (int i = 0; i < srcNumComp; i++) {
if (srcCM.getComponentSize(i) > 8) {
precision = 16;
maxNum = 65535.0f;
}
}
for (int i = 0; i < dstNumComp; i++) {
if (dstCM.getComponentSize(i) > 8) {
precision = 16;
maxNum = 65535.0f;
}
}
float[] srcMinVal = new float[srcNumComp];
float[] srcInvDiffMinMax = new float[srcNumComp];
ColorSpace cs = srcCM.getColorSpace();
for (int i = 0; i < srcNumComp; i++) {
srcMinVal[i] = cs.getMinValue(i);
srcInvDiffMinMax[i] = maxNum / (cs.getMaxValue(i) - srcMinVal[i]);
}
cs = dstCM.getColorSpace();
float[] dstMinVal = new float[dstNumComp];
float[] dstDiffMinMax = new float[dstNumComp];
for (int i = 0; i < dstNumComp; i++) {
dstMinVal[i] = cs.getMinValue(i);
dstDiffMinMax[i] = (cs.getMaxValue(i) - dstMinVal[i]) / maxNum;
}
boolean dstHasAlpha = dstCM.hasAlpha();
boolean needSrcAlpha = srcCM.hasAlpha() && dstHasAlpha;
float[] dstColor;
if (dstHasAlpha) {
dstColor = new float[dstNumComp + 1];
} else {
dstColor = new float[dstNumComp];
}
if (precision == 8) {
byte[] srcLine = new byte[w * srcNumComp];
byte[] dstLine = new byte[w * dstNumComp];
Object pixel;
float[] color;
float[] alpha = null;
if (needSrcAlpha) {
alpha = new float[w];
}
int idx;
// TODO check for src npixels = dst npixels
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
pixel = null;
color = null;
idx = 0;
for (int x = 0; x < w; x++) {
pixel = srcRas.getDataElements(x, y, pixel);
color = srcCM.getNormalizedComponents(pixel, color, 0);
for (int i = 0; i < srcNumComp; i++) {
srcLine[idx++] = (byte)
((color[i] - srcMinVal[i]) * srcInvDiffMinMax[i] +
0.5f);
}
if (needSrcAlpha) {
alpha[x] = color[srcNumComp];
}
}
// color convert srcLine to dstLine
doTransform(srcIL, dstIL);
// convert dst scanline
pixel = null;
idx = 0;
for (int x = 0; x < w; x++) {
for (int i = 0; i < dstNumComp; i++) {
dstColor[i] = ((float) (dstLine[idx++] & 0xff)) *
dstDiffMinMax[i] + dstMinVal[i];
}
if (needSrcAlpha) {
dstColor[dstNumComp] = alpha[x];
} else if (dstHasAlpha) {
dstColor[dstNumComp] = 1.0f;
}
pixel = dstCM.getDataElements(dstColor, 0, pixel);
dstRas.setDataElements(x, y, pixel);
}
}
} else {
short[] srcLine = new short[w * srcNumComp];
short[] dstLine = new short[w * dstNumComp];
Object pixel;
float[] color;
float[] alpha = null;
if (needSrcAlpha) {
alpha = new float[w];
}
int idx;
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
pixel = null;
color = null;
idx = 0;
for (int x = 0; x < w; x++) {
pixel = srcRas.getDataElements(x, y, pixel);
color = srcCM.getNormalizedComponents(pixel, color, 0);
for (int i = 0; i < srcNumComp; i++) {
srcLine[idx++] = (short)
((color[i] - srcMinVal[i]) * srcInvDiffMinMax[i] +
0.5f);
}
if (needSrcAlpha) {
alpha[x] = color[srcNumComp];
}
}
// color convert srcLine to dstLine
doTransform(srcIL, dstIL);
// convert dst scanline
pixel = null;
idx = 0;
for (int x = 0; x < w; x++) {
for (int i = 0; i < dstNumComp; i++) {
dstColor[i] = ((float) (dstLine[idx++] & 0xffff)) *
dstDiffMinMax[i] + dstMinVal[i];
}
if (needSrcAlpha) {
dstColor[dstNumComp] = alpha[x];
} else if (dstHasAlpha) {
dstColor[dstNumComp] = 1.0f;
}
pixel = dstCM.getDataElements(dstColor, 0, pixel);
dstRas.setDataElements(x, y, pixel);
}
}
}
}
public void colorConvert(Raster src, WritableRaster dst,
float[] srcMinVal, float[]srcMaxVal,
float[] dstMinVal, float[]dstMaxVal) {
LCMSImageLayout srcIL, dstIL;
// Can't pass src and dst directly to CMM, so process per scanline
SampleModel srcSM = src.getSampleModel();
SampleModel dstSM = dst.getSampleModel();
int srcTransferType = src.getTransferType();
int dstTransferType = dst.getTransferType();
boolean srcIsFloat, dstIsFloat;
if ((srcTransferType == DataBuffer.TYPE_FLOAT) ||
(srcTransferType == DataBuffer.TYPE_DOUBLE)) {
srcIsFloat = true;
} else {
srcIsFloat = false;
}
if ((dstTransferType == DataBuffer.TYPE_FLOAT) ||
(dstTransferType == DataBuffer.TYPE_DOUBLE)) {
dstIsFloat = true;
} else {
dstIsFloat = false;
}
int w = src.getWidth();
int h = src.getHeight();
int srcNumBands = src.getNumBands();
int dstNumBands = dst.getNumBands();
float[] srcScaleFactor = new float[srcNumBands];
float[] dstScaleFactor = new float[dstNumBands];
float[] srcUseMinVal = new float[srcNumBands];
float[] dstUseMinVal = new float[dstNumBands];
for (int i = 0; i < srcNumBands; i++) {
if (srcIsFloat) {
srcScaleFactor[i] = 65535.0f / (srcMaxVal[i] - srcMinVal[i]);
srcUseMinVal[i] = srcMinVal[i];
} else {
if (srcTransferType == DataBuffer.TYPE_SHORT) {
srcScaleFactor[i] = 65535.0f / 32767.0f;
} else {
srcScaleFactor[i] = 65535.0f /
((float) ((1 << srcSM.getSampleSize(i)) - 1));
}
srcUseMinVal[i] = 0.0f;
}
}
for (int i = 0; i < dstNumBands; i++) {
if (dstIsFloat) {
dstScaleFactor[i] = (dstMaxVal[i] - dstMinVal[i]) / 65535.0f;
dstUseMinVal[i] = dstMinVal[i];
} else {
if (dstTransferType == DataBuffer.TYPE_SHORT) {
dstScaleFactor[i] = 32767.0f / 65535.0f;
} else {
dstScaleFactor[i] =
((float) ((1 << dstSM.getSampleSize(i)) - 1)) /
65535.0f;
}
dstUseMinVal[i] = 0.0f;
}
}
int ys = src.getMinY();
int yd = dst.getMinY();
int xs, xd;
float sample;
short[] srcLine = new short[w * srcNumBands];
short[] dstLine = new short[w * dstNumBands];
int idx;
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
xs = src.getMinX();
idx = 0;
for (int x = 0; x < w; x++, xs++) {
for (int i = 0; i < srcNumBands; i++) {
sample = src.getSampleFloat(xs, ys, i);
srcLine[idx++] = (short)
((sample - srcUseMinVal[i]) * srcScaleFactor[i] + 0.5f);
}
}
// color convert srcLine to dstLine
doTransform(srcIL, dstIL);
// store dst scanline
xd = dst.getMinX();
idx = 0;
for (int x = 0; x < w; x++, xd++) {
for (int i = 0; i < dstNumBands; i++) {
sample = ((dstLine[idx++] & 0xffff) * dstScaleFactor[i]) +
dstUseMinVal[i];
dst.setSample(xd, yd, i, sample);
}
}
}
}
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();
int srcTransferType = src.getTransferType();
int dstTransferType = dst.getTransferType();
int w = src.getWidth();
int h = src.getHeight();
int srcNumBands = src.getNumBands();
int dstNumBands = dst.getNumBands();
int precision = 8;
float maxNum = 255.0f;
for (int i = 0; i < srcNumBands; i++) {
if (srcSM.getSampleSize(i) > 8) {
precision = 16;
maxNum = 65535.0f;
}
}
for (int i = 0; i < dstNumBands; i++) {
if (dstSM.getSampleSize(i) > 8) {
precision = 16;
maxNum = 65535.0f;
}
}
float[] srcScaleFactor = new float[srcNumBands];
float[] dstScaleFactor = new float[dstNumBands];
for (int i = 0; i < srcNumBands; i++) {
if (srcTransferType == DataBuffer.TYPE_SHORT) {
srcScaleFactor[i] = maxNum / 32767.0f;
} else {
srcScaleFactor[i] = maxNum /
((float) ((1 << srcSM.getSampleSize(i)) - 1));
}
}
for (int i = 0; i < dstNumBands; i++) {
if (dstTransferType == DataBuffer.TYPE_SHORT) {
dstScaleFactor[i] = 32767.0f / maxNum;
} else {
dstScaleFactor[i] =
((float) ((1 << dstSM.getSampleSize(i)) - 1)) / maxNum;
}
}
int ys = src.getMinY();
int yd = dst.getMinY();
int xs, xd;
int sample;
if (precision == 8) {
byte[] srcLine = new byte[w * srcNumBands];
byte[] dstLine = new byte[w * dstNumBands];
int idx;
// TODO check for src npixels = dst npixels
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
xs = src.getMinX();
idx = 0;
for (int x = 0; x < w; x++, xs++) {
for (int i = 0; i < srcNumBands; i++) {
sample = src.getSample(xs, ys, i);
srcLine[idx++] = (byte)
((sample * srcScaleFactor[i]) + 0.5f);
}
}
// color convert srcLine to dstLine
doTransform(srcIL, dstIL);
// store dst scanline
xd = dst.getMinX();
idx = 0;
for (int x = 0; x < w; x++, xd++) {
for (int i = 0; i < dstNumBands; i++) {
sample = (int) (((dstLine[idx++] & 0xff) *
dstScaleFactor[i]) + 0.5f);
dst.setSample(xd, yd, i, sample);
}
}
}
} else {
short[] srcLine = new short[w * srcNumBands];
short[] dstLine = new short[w * dstNumBands];
int idx;
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
xs = src.getMinX();
idx = 0;
for (int x = 0; x < w; x++, xs++) {
for (int i = 0; i < srcNumBands; i++) {
sample = src.getSample(xs, ys, i);
srcLine[idx++] = (short)
((sample * srcScaleFactor[i]) + 0.5f);
}
}
// color convert srcLine to dstLine
doTransform(srcIL, dstIL);
// store dst scanline
xd = dst.getMinX();
idx = 0;
for (int x = 0; x < w; x++, xd++) {
for (int i = 0; i < dstNumBands; i++) {
sample = (int) (((dstLine[idx++] & 0xffff) *
dstScaleFactor[i]) + 0.5f);
dst.setSample(xd, yd, i, sample);
}
}
}
}
}
/* convert an array of colors in short format */
/* each color is a contiguous set of array elements */
/* the number of colors is (size of the array) / (number of input/output
components */
public short[] colorConvert(short[] src, short[] dst) {
if (dst == null) {
dst = new short [(src.length/getNumInComponents())*getNumOutComponents()];
}
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);
doTransform(srcIL, dstIL);
return dst;
} catch (ImageLayoutException e) {
throw new CMMException("Unable to convert data");
}
}
public byte[] colorConvert(byte[] src, byte[] dst) {
if (dst == null) {
dst = new byte [(src.length/getNumInComponents())*getNumOutComponents()];
}
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());
doTransform(srcIL, dstIL);
return dst;
} catch (ImageLayoutException e) {
throw new CMMException("Unable to convert data");
}
}
}

View File

@@ -0,0 +1,36 @@
/*
* Copyright (c) 2013, 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
package sun.java2d.cmm.lcms;
import sun.java2d.cmm.CMMServiceProvider;
import sun.java2d.cmm.PCMM;
public final class LcmsServiceProvider extends CMMServiceProvider {
@Override
protected PCMM getModule() {
return LCMS.getModule();
}
}