📄 colorconvertop.java
字号:
/* * @(#)ColorConvertOp.java 1.37 03/01/23 * * Copyright 2003 Sun Microsystems, Inc. All rights reserved. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. *//********************************************************************** ********************************************************************** ********************************************************************** *** COPYRIGHT (c) Eastman Kodak Company, 1997 *** *** As an unpublished work pursuant to Title 17 of the United *** *** States Code. All rights reserved. *** ********************************************************************** ********************************************************************** **********************************************************************/package java.awt.image;import java.awt.Point;import java.awt.Graphics2D;import java.awt.color.*;import sun.awt.color.ICC_Transform;import sun.awt.color.ProfileDeferralMgr;import java.awt.geom.Rectangle2D;import java.awt.geom.Point2D;import java.awt.RenderingHints;/** * This class performs a pixel-by-pixel color conversion of the data in * the source image. The resulting color values are scaled to the precision * of the destination image. Color conversion can be specified * via an array of ColorSpace objects or an array of ICC_Profile objects. * <p> * If the source is a BufferedImage with premultiplied alpha, the * color components are divided by the alpha component before color conversion. * If the destination is a BufferedImage with premultiplied alpha, the * color components are multiplied by the alpha component after conversion. * Rasters are treated as having no alpha channel, i.e. all bands are * color bands. * <p> * If a RenderingHints object is specified in the constructor, the * color rendering hint and the dithering hint may be used to control * color conversion. * <p> * Note that Source and Destination may be the same object. * <p> * @see java.awt.RenderingHints#KEY_COLOR_RENDERING * @see java.awt.RenderingHints#KEY_DITHERING */public class ColorConvertOp implements BufferedImageOp, RasterOp { ICC_Profile[] profileList; ColorSpace[] CSList; ICC_Transform thisTransform, thisRasterTransform; ICC_Profile thisSrcProfile, thisDestProfile; RenderingHints hints; boolean gotProfiles; float[] srcMinVals, srcMaxVals, dstMinVals, dstMaxVals; /* the class initializer */ static { if (ProfileDeferralMgr.deferring) { ProfileDeferralMgr.activateProfiles(); } } /** * Constructs a new ColorConvertOp which will convert * from a source color space to a destination color space. * The RenderingHints argument may be null. * This Op can be used only with BufferedImages, and will convert * directly from the ColorSpace of the source image to that of the * destination. The destination argument of the filter method * cannot be specified as null. * @param hints the <code>RenderingHints</code> object used to control * the color conversion, or <code>null</code> */ public ColorConvertOp (RenderingHints hints) { profileList = new ICC_Profile [0]; /* 0 length list */ this.hints = hints; } /** * Constructs a new ColorConvertOp from a ColorSpace object. * The RenderingHints argument may be null. This * Op can be used only with BufferedImages, and is primarily useful * when the {@link #filter(BufferedImage, BufferedImage) filter} * method is invoked with a destination argument of null. * In that case, the ColorSpace defines the destination color space * for the destination created by the filter method. Otherwise, the * ColorSpace defines an intermediate space to which the source is * converted before being converted to the destination space. * @param cspace defines the destination <code>ColorSpace</code> or an * intermediate <code>ColorSpace</code> * @param hints the <code>RenderingHints</code> object used to control * the color conversion, or <code>null</code> * @throws NullPointerException if cspace is null */ public ColorConvertOp (ColorSpace cspace, RenderingHints hints) { if (cspace == null) { throw new NullPointerException("ColorSpace cannot be null"); } if (cspace instanceof ICC_ColorSpace) { profileList = new ICC_Profile [1]; /* 1 profile in the list */ profileList [0] = ((ICC_ColorSpace) cspace).getProfile(); } else { CSList = new ColorSpace[1]; /* non-ICC case: 1 ColorSpace in list */ CSList[0] = cspace; } this.hints = hints; } /** * Constructs a new ColorConvertOp from two ColorSpace objects. * The RenderingHints argument may be null. * This Op is primarily useful for calling the filter method on * Rasters, in which case the two ColorSpaces define the operation * to be performed on the Rasters. In that case, the number of bands * in the source Raster must match the number of components in * srcCspace, and the number of bands in the destination Raster * must match the number of components in dstCspace. For BufferedImages, * the two ColorSpaces define intermediate spaces through which the * source is converted before being converted to the destination space. * @param srcCspace the source <code>ColorSpace</code> * @param dstCspace the destination <code>ColorSpace</code> * @param hints the <code>RenderingHints</code> object used to control * the color conversion, or <code>null</code> * @throws NullPointerException if either srcCspace or dstCspace is null */ public ColorConvertOp(ColorSpace srcCspace, ColorSpace dstCspace, RenderingHints hints) { if ((srcCspace == null) || (dstCspace == null)) { throw new NullPointerException("ColorSpaces cannot be null"); } if ((srcCspace instanceof ICC_ColorSpace) && (dstCspace instanceof ICC_ColorSpace)) { profileList = new ICC_Profile [2]; /* 2 profiles in the list */ profileList [0] = ((ICC_ColorSpace) srcCspace).getProfile(); profileList [1] = ((ICC_ColorSpace) dstCspace).getProfile(); getMinMaxValsFromColorSpaces(srcCspace, dstCspace); } else { /* non-ICC case: 2 ColorSpaces in list */ CSList = new ColorSpace[2]; CSList[0] = srcCspace; CSList[1] = dstCspace; } this.hints = hints; } /** * Constructs a new ColorConvertOp from an array of ICC_Profiles. * The RenderingHints argument may be null. * The sequence of profiles may include profiles that represent color * spaces, profiles that represent effects, etc. If the whole sequence * does not represent a well-defined color conversion, an exception is * thrown. * <p>For BufferedImages, if the ColorSpace * of the source BufferedImage does not match the requirements of the * first profile in the array, * the first conversion is to an appropriate ColorSpace. * If the requirements of the last profile in the array are not met * by the ColorSpace of the destination BufferedImage, * the last conversion is to the destination's ColorSpace. * <p>For Rasters, the number of bands in the source Raster must match * the requirements of the first profile in the array, and the * number of bands in the destination Raster must match the requirements * of the last profile in the array. The array must have at least two * elements or calling the filter method for Rasters will throw an * IllegalArgumentException. * @param profiles the array of <code>ICC_Profile</code> objects * @param hints the <code>RenderingHints</code> object used to control * the color conversion, or <code>null</code> * @exception IllegalArgumentException when the profile sequence does not * specify a well-defined color conversion * @exception NullPointerException if profiles is null */ public ColorConvertOp (ICC_Profile[] profiles, RenderingHints hints) { if (profiles == null) { throw new NullPointerException("Profiles cannot be null"); } gotProfiles = true; profileList = new ICC_Profile[profiles.length]; for (int i1 = 0; i1 < profiles.length; i1++) { profileList[i1] = profiles[i1]; } this.hints = hints; } /** * Returns the array of ICC_Profiles used to construct this ColorConvertOp. * Returns null if the ColorConvertOp was not constructed from such an * array. * @return the array of <code>ICC_Profile</code> objects of this * <code>ColorConvertOp</code>, or <code>null</code> if this * <code>ColorConvertOp</code> was not constructed with an * array of <code>ICC_Profile</code> objects. */ public final ICC_Profile[] getICC_Profiles() { if (gotProfiles) { ICC_Profile[] profiles = new ICC_Profile[profileList.length]; for (int i1 = 0; i1 < profileList.length; i1++) { profiles[i1] = profileList[i1]; } return profiles; } return null; } /** * ColorConverts the source BufferedImage. * If the destination image is null, * a BufferedImage will be created with an appropriate ColorModel. * @param src the source <code>BufferedImage</code> to be converted * @param dest the destination <code>BufferedImage</code>, * or <code>null</code> * @return <code>dest</code> color converted from <code>src</code> * or a new, converted <code>BufferedImage</code> * if <code>dest</code> is <code>null</code> * @exception IllegalArgumentException if dest is null and this op was * constructed using the constructor which takes only a * RenderingHints argument, since the operation is ill defined. */ public final BufferedImage filter(BufferedImage src, BufferedImage dest) { ColorSpace srcColorSpace, destColorSpace; BufferedImage savdest = null; if (src.getColorModel() instanceof IndexColorModel) { IndexColorModel icm = (IndexColorModel) src.getColorModel(); src = icm.convertToIntDiscrete(src.getRaster(), true); } srcColorSpace = src.getColorModel().getColorSpace(); if (dest != null) { if (dest.getColorModel() instanceof IndexColorModel) { savdest = dest; dest = null; destColorSpace = null; } else { destColorSpace = dest.getColorModel().getColorSpace(); } } else { destColorSpace = null; } if ((CSList != null) || (!(srcColorSpace instanceof ICC_ColorSpace)) || ((dest != null) && (!(destColorSpace instanceof ICC_ColorSpace)))) { /* non-ICC case */ dest = nonICCBIFilter(src, srcColorSpace, dest, destColorSpace); } else { dest = ICCBIFilter(src, srcColorSpace, dest, destColorSpace); } if (savdest != null) { Graphics2D big = savdest.createGraphics(); try { big.drawImage(dest, 0, 0, null); } finally { big.dispose(); } return savdest; } else { return dest; } } private final BufferedImage ICCBIFilter(BufferedImage src, ColorSpace srcColorSpace, BufferedImage dest, ColorSpace destColorSpace) { int nProfiles = profileList.length; ICC_Profile srcProfile = null, destProfile = null; srcProfile = ((ICC_ColorSpace) srcColorSpace).getProfile(); if (dest == null) { /* last profile in the list defines the output color space */ if (nProfiles == 0) { throw new IllegalArgumentException( "Destination ColorSpace is undefined"); } destProfile = profileList [nProfiles - 1]; dest = createCompatibleDestImage(src, null); } else { if (src.getHeight() != dest.getHeight() || src.getWidth() != dest.getWidth()) { throw new IllegalArgumentException( "Width or height of BufferedImages do not match"); } destProfile = ((ICC_ColorSpace) destColorSpace).getProfile(); } /* make a new transform if needed */ if ((thisTransform == null) || (thisSrcProfile != srcProfile) || (thisDestProfile != destProfile) ) { updateBITransform(srcProfile, destProfile); } /* color convert the image */ thisTransform.colorConvert(src, dest); return dest; } private void updateBITransform(ICC_Profile srcProfile, ICC_Profile destProfile) { ICC_Profile[] theProfiles; int i1, nProfiles, nTransforms, whichTrans, renderState; ICC_Transform[] theTransforms; boolean useSrc = false, useDest = false; nProfiles = profileList.length; nTransforms = nProfiles; if ((nProfiles == 0) || (srcProfile != profileList[0])) { nTransforms += 1; useSrc = true; } if ((nProfiles == 0) || (destProfile != profileList[nProfiles - 1]) || (nTransforms < 2)) { nTransforms += 1; useDest = true; } /* make the profile list */ theProfiles = new ICC_Profile[nTransforms]; /* the list of profiles for this Op */ int idx = 0; if (useSrc) { /* insert source as first profile */ theProfiles[idx++] = srcProfile; } for (i1 = 0; i1 < nProfiles; i1++) { /* insert profiles defined in this Op */ theProfiles[idx++] = profileList [i1]; } if (useDest) { /* insert dest as last profile */ theProfiles[idx] = destProfile; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -