001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017:
018: /* $Id: FormatRed.java 496556 2007-01-16 00:59:48Z cam $ */
019:
020: package org.apache.xmlgraphics.image.rendered;
021:
022: import java.awt.Point;
023: import java.awt.Transparency;
024: import java.awt.color.ColorSpace;
025: import java.awt.image.BufferedImage;
026: import java.awt.image.ColorModel;
027: import java.awt.image.ComponentColorModel;
028: import java.awt.image.ComponentSampleModel;
029: import java.awt.image.DataBuffer;
030: import java.awt.image.DirectColorModel;
031: import java.awt.image.Raster;
032: import java.awt.image.SampleModel;
033: import java.awt.image.SinglePixelPackedSampleModel;
034: import java.awt.image.WritableRaster;
035:
036: import org.apache.xmlgraphics.image.GraphicsUtil;
037:
038: /**
039: * This allows you to specify the ColorModel, Alpha premult and/or
040: * SampleModel to be used for output. If the input image lacks
041: * Alpha and alpha is included in output then it is filled with
042: * alpha=1. In all other cases bands are simply copied.
043: *
044: * @author <a href="mailto:Thomas.DeWeeese@Kodak.com">Thomas DeWeese</a>
045: * @version $Id: FormatRed.java 496556 2007-01-16 00:59:48Z cam $
046: */
047: public class FormatRed extends AbstractRed {
048:
049: public static CachableRed construct(CachableRed src, ColorModel cm) {
050: ColorModel srcCM = src.getColorModel();
051: if ((cm.hasAlpha() != srcCM.hasAlpha())
052: || (cm.isAlphaPremultiplied() != srcCM
053: .isAlphaPremultiplied()))
054: return new FormatRed(src, cm);
055:
056: if (cm.getNumComponents() != srcCM.getNumComponents())
057: throw new IllegalArgumentException(
058: "Incompatible ColorModel given");
059:
060: if ((srcCM instanceof ComponentColorModel)
061: && (cm instanceof ComponentColorModel))
062: return src;
063:
064: if ((srcCM instanceof DirectColorModel)
065: && (cm instanceof DirectColorModel))
066: return src;
067:
068: return new FormatRed(src, cm);
069: }
070:
071: /**
072: * Construct an instance of CachableRed around a BufferedImage.
073: */
074: public FormatRed(CachableRed cr, SampleModel sm) {
075: super (cr, cr.getBounds(), makeColorModel(cr, sm), sm, cr
076: .getTileGridXOffset(), cr.getTileGridYOffset(), null);
077: }
078:
079: public FormatRed(CachableRed cr, ColorModel cm) {
080: super (cr, cr.getBounds(), cm, makeSampleModel(cr, cm), cr
081: .getTileGridXOffset(), cr.getTileGridYOffset(), null);
082: }
083:
084: /**
085: * fetch the source image for this node.
086: */
087: public CachableRed getSource() {
088: return (CachableRed) getSources().get(0);
089: }
090:
091: public Object getProperty(String name) {
092: return getSource().getProperty(name);
093: }
094:
095: public String[] getPropertyNames() {
096: return getSource().getPropertyNames();
097: }
098:
099: public WritableRaster copyData(WritableRaster wr) {
100: ColorModel cm = getColorModel();
101: CachableRed cr = getSource();
102: ColorModel srcCM = cr.getColorModel();
103: SampleModel srcSM = cr.getSampleModel();
104: srcSM = srcSM.createCompatibleSampleModel(wr.getWidth(), wr
105: .getHeight());
106: WritableRaster srcWR;
107: srcWR = Raster.createWritableRaster(srcSM, new Point(wr
108: .getMinX(), wr.getMinY()));
109: getSource().copyData(srcWR);
110:
111: BufferedImage srcBI = new BufferedImage(srcCM, srcWR
112: .createWritableTranslatedChild(0, 0), srcCM
113: .isAlphaPremultiplied(), null);
114: BufferedImage dstBI = new BufferedImage(cm, wr
115: .createWritableTranslatedChild(0, 0), cm
116: .isAlphaPremultiplied(), null);
117:
118: GraphicsUtil.copyData(srcBI, dstBI);
119:
120: return wr;
121: }
122:
123: public static SampleModel makeSampleModel(CachableRed cr,
124: ColorModel cm) {
125: SampleModel srcSM = cr.getSampleModel();
126: return cm.createCompatibleSampleModel(srcSM.getWidth(), srcSM
127: .getHeight());
128: }
129:
130: public static ColorModel makeColorModel(CachableRed cr,
131: SampleModel sm) {
132: ColorModel srcCM = cr.getColorModel();
133: ColorSpace cs = srcCM.getColorSpace();
134:
135: int bands = sm.getNumBands();
136:
137: int bits;
138: int dt = sm.getDataType();
139: switch (dt) {
140: case DataBuffer.TYPE_BYTE:
141: bits = 8;
142: break;
143: case DataBuffer.TYPE_SHORT:
144: bits = 16;
145: break;
146: case DataBuffer.TYPE_USHORT:
147: bits = 16;
148: break;
149: case DataBuffer.TYPE_INT:
150: bits = 32;
151: break;
152: default:
153: throw new IllegalArgumentException(
154: "Unsupported DataBuffer type: " + dt);
155: }
156:
157: boolean hasAlpha = srcCM.hasAlpha();
158: if (hasAlpha) {
159: // if Src has Alpha then our out bands must
160: // either be one less than the source (no out alpha)
161: // or equal (still has alpha)
162: if (bands == srcCM.getNumComponents() - 1)
163: hasAlpha = false;
164: else if (bands != srcCM.getNumComponents())
165: throw new IllegalArgumentException(
166: "Incompatible number of bands in and out");
167: } else {
168: if (bands == srcCM.getNumComponents() + 1)
169: hasAlpha = true;
170: else if (bands != srcCM.getNumComponents())
171: throw new IllegalArgumentException(
172: "Incompatible number of bands in and out");
173: }
174:
175: boolean preMult = srcCM.isAlphaPremultiplied();
176: if (!hasAlpha)
177: preMult = false;
178:
179: if (sm instanceof ComponentSampleModel) {
180: int[] bitsPer = new int[bands];
181: for (int i = 0; i < bands; i++)
182: bitsPer[i] = bits;
183:
184: return new ComponentColorModel(cs, bitsPer, hasAlpha,
185: preMult, hasAlpha ? Transparency.TRANSLUCENT
186: : Transparency.OPAQUE, dt);
187: } else if (sm instanceof SinglePixelPackedSampleModel) {
188: SinglePixelPackedSampleModel sppsm;
189: sppsm = (SinglePixelPackedSampleModel) sm;
190: int[] masks = sppsm.getBitMasks();
191: if (bands == 4)
192: return new DirectColorModel(cs, bits, masks[0],
193: masks[1], masks[2], masks[3], preMult, dt);
194: else if (bands == 3)
195: return new DirectColorModel(cs, bits, masks[0],
196: masks[1], masks[2], 0x0, preMult, dt);
197: else
198: throw new IllegalArgumentException(
199: "Incompatible number of bands out for ColorModel");
200: }
201: throw new IllegalArgumentException(
202: "Unsupported SampleModel Type");
203: }
204: }
|