001: /*
002: * $RCSfile: ColorModelProxy.java,v $
003: *
004: * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
005: *
006: * Use is subject to license terms.
007: *
008: * $Revision: 1.1 $
009: * $Date: 2005/02/11 04:56:49 $
010: * $State: Exp $
011: */
012: package com.sun.media.jai.rmi;
013:
014: import java.awt.color.ColorSpace;
015: import java.awt.color.ICC_ColorSpace;
016: import java.awt.color.ICC_Profile;
017: import java.awt.image.ColorModel;
018: import java.awt.image.ComponentColorModel;
019: import java.awt.image.DataBuffer;
020: import java.awt.image.DirectColorModel;
021: import java.awt.image.IndexColorModel;
022: import java.awt.image.SampleModel;
023: import java.io.IOException;
024: import java.io.ObjectInputStream;
025: import java.io.ObjectOutputStream;
026: import java.io.Serializable;
027: import javax.media.jai.FloatDoubleColorModel;
028:
029: /**
030: * This class is a serializable proxy for a ColorModel from which the
031: * ColorModel may be reconstituted.
032: *
033: *
034: * @since EA3
035: */
036: public class ColorModelProxy implements Serializable {
037: /** Flag indicating that the ColorSpace is unknown. */
038: private static final int COLORSPACE_UNKNOWN = 0;
039:
040: /**
041: * Flag indicating that the ColorSpace is one of those of which an
042: * instance may be obtained using ColorSpace.getInstance() with one
043: * of the pre-defined constants ColorSpace.CS_*.
044: */
045: private static final int COLORSPACE_PREDEFINED = 1;
046:
047: /** Flag indicating that the ColorSpace is an ICC_ColorSpace. */
048: private static final int COLORSPACE_ICC = 2;
049:
050: /** Flag indicating that the ColorModel is null. */
051: private static final int COLORMODEL_NULL = 0;
052:
053: /** Flag indicating that the ColorModel is a FloatDoubleColorModel. */
054: private static final int COLORMODEL_FLOAT_DOUBLE_COMPONENT = 1;
055:
056: /** Flag indicating that the ColorModel is a ComponentColorModel. */
057: private static final int COLORMODEL_COMPONENT = 2;
058:
059: /** Flag indicating that the ColorModel is a IndexColorModel. */
060: private static final int COLORMODEL_INDEX = 3;
061:
062: /** Flag indicating that the ColorModel is a DirectColorModel. */
063: private static final int COLORMODEL_DIRECT = 4;
064:
065: /** The ColorModel. */
066: private transient ColorModel colorModel = null;
067:
068: /**
069: * Returns an array of length one containing the pre-defined
070: * ColorSpace.CS_* colorspace which equals the parameter ColorSpace
071: * or null if it does not equal any of the pre-defined ColorSpaces.
072: */
073: private static int[] getPredefinedColorSpace(ColorSpace cs) {
074: // Initialize an array of the pre-defined ColorSpaces.
075: int[] colorSpaces = new int[] { ColorSpace.CS_CIEXYZ,
076: ColorSpace.CS_GRAY, ColorSpace.CS_LINEAR_RGB,
077: ColorSpace.CS_PYCC, ColorSpace.CS_sRGB };
078:
079: // Return the pre-defined index if the parameter is one of these.
080: for (int i = 0; i < colorSpaces.length; i++) {
081: try {
082: if (cs.equals(ColorSpace.getInstance(colorSpaces[i]))) {
083: return new int[] { colorSpaces[i] };
084: }
085: } catch (Throwable e) {
086: // Profile not found ; resilent.
087: }
088: }
089:
090: // Try to find a similar ColorSpace.
091: int numComponents = cs.getNumComponents();
092: int type = cs.getType();
093: if (numComponents == 1 && type == ColorSpace.TYPE_GRAY) {
094: return new int[] { ColorSpace.CS_GRAY };
095: } else if (numComponents == 3) {
096: if (type == ColorSpace.TYPE_RGB) {
097: return new int[] { ColorSpace.CS_sRGB };
098: } else if (type == ColorSpace.TYPE_XYZ) {
099: return new int[] { ColorSpace.CS_CIEXYZ };
100: }
101: }
102:
103: // Unknown type - too bad!
104: return null;
105: }
106:
107: /**
108: * Serialize the parameter ColorSpace object.
109: */
110: private static boolean serializeColorSpace(ColorSpace cs,
111: ObjectOutputStream out) throws IOException {
112: int[] colorSpaceType = null;
113: if (!(cs instanceof ICC_ColorSpace)
114: && (colorSpaceType = getPredefinedColorSpace(cs)) == null) {
115: out.writeInt(COLORSPACE_UNKNOWN);
116: out.writeInt(cs.getNumComponents());
117: return false;
118: }
119:
120: if (cs instanceof ICC_ColorSpace) {
121: out.writeInt(COLORSPACE_ICC);
122: ((ICC_ColorSpace) cs).getProfile().write(out);
123: } else {
124: out.writeInt(COLORSPACE_PREDEFINED);
125: out.writeInt(colorSpaceType[0]);
126: }
127:
128: return true;
129: }
130:
131: /**
132: * Derialize the parameter ColorSpace object.
133: */
134: private static ColorSpace deserializeColorSpace(ObjectInputStream in)
135: throws IOException {
136: ColorSpace cs = null;
137: int colorSpaceType = in.readInt();
138: if (colorSpaceType == COLORSPACE_ICC) {
139: cs = new ICC_ColorSpace(ICC_Profile.getInstance(in));
140: } else if (colorSpaceType == COLORSPACE_PREDEFINED) {
141: cs = ColorSpace.getInstance(in.readInt());
142: } else if (colorSpaceType == COLORSPACE_UNKNOWN) {
143: // Create probable ColorSpaces for 1- and 3-band cases.
144: switch (in.readInt()) {
145: case 1: // gray scale
146: cs = ColorSpace.getInstance(ColorSpace.CS_GRAY);
147: break;
148: case 3: // sRGB
149: cs = ColorSpace.getInstance(ColorSpace.CS_sRGB);
150: break;
151: default: // Unknown
152: cs = null; // to be explicit ...
153: }
154: }
155:
156: return cs;
157: }
158:
159: /**
160: * Constructs a <code>ColorModelProxy</code> from a
161: * <code>ColorModel</code>.
162: *
163: * @param source The <code>ColorModel</code> to be serialized.
164: */
165: public ColorModelProxy(ColorModel source) {
166: colorModel = source;
167: }
168:
169: /**
170: * Retrieves the associated <code>ColorModel</code>.
171: * @return The (perhaps reconstructed) <code>ColorModel</code>.
172: */
173: public ColorModel getColorModel() {
174: return colorModel;
175: }
176:
177: /**
178: * Serialize the <code>ColorModelProxy</code>.
179: *
180: * @param out The <code>ObjectOutputStream</code>.
181: */
182: private void writeObject(ObjectOutputStream out) throws IOException {
183: // Write serialized form to the stream.
184: if (colorModel == null) {
185: out.writeInt(COLORMODEL_NULL);
186: } else if (colorModel instanceof ComponentColorModel) {
187: ComponentColorModel cm = (ComponentColorModel) colorModel;
188: int type = COLORMODEL_COMPONENT;
189: if (colorModel instanceof FloatDoubleColorModel) {
190: type = COLORMODEL_FLOAT_DOUBLE_COMPONENT;
191: }
192: out.writeInt(type);
193: serializeColorSpace(cm.getColorSpace(), out); // ignore return
194: if (type == COLORMODEL_COMPONENT) {
195: out.writeObject(cm.getComponentSize());
196: }
197: out.writeBoolean(cm.hasAlpha());
198: out.writeBoolean(cm.isAlphaPremultiplied());
199: out.writeInt(cm.getTransparency());
200: // Create a SampleModel to get the transferType. This is
201: // absurd but is the only apparent way to retrieve this value.
202: SampleModel sm = cm.createCompatibleSampleModel(1, 1);
203: out.writeInt(sm.getTransferType());
204: } else if (colorModel instanceof IndexColorModel) {
205: IndexColorModel cm = (IndexColorModel) colorModel;
206: out.writeInt(COLORMODEL_INDEX);
207: int size = cm.getMapSize();
208: int[] cmap = new int[size];
209: cm.getRGBs(cmap);
210: out.writeInt(cm.getPixelSize());
211: out.writeInt(size);
212: out.writeObject(cmap);
213: out.writeBoolean(cm.hasAlpha());
214: out.writeInt(cm.getTransparentPixel());
215: // Create a SampleModel to get the transferType. This is
216: // absurd but is the only apparent way to retrieve this value.
217: SampleModel sm = cm.createCompatibleSampleModel(1, 1);
218: out.writeInt(sm.getTransferType());
219: } else if (colorModel instanceof DirectColorModel) {
220: DirectColorModel cm = (DirectColorModel) colorModel;
221: out.writeInt(COLORMODEL_DIRECT);
222: boolean csSerialized = serializeColorSpace(cm
223: .getColorSpace(), out);
224: if (!csSerialized) {
225: out.writeBoolean(cm.hasAlpha());
226: }
227: out.writeInt(cm.getPixelSize());
228: out.writeInt(cm.getRedMask());
229: out.writeInt(cm.getGreenMask());
230: out.writeInt(cm.getBlueMask());
231: if (csSerialized || cm.hasAlpha()) {
232: out.writeInt(cm.getAlphaMask());
233: }
234: if (csSerialized) {
235: out.writeBoolean(cm.isAlphaPremultiplied());
236: // Create a SampleModel to get the transferType. This is
237: // absurd but is the only apparent way to retrieve this
238: // value.
239: SampleModel sm = cm.createCompatibleSampleModel(1, 1);
240: out.writeInt(sm.getTransferType());
241: }
242: } else {
243: throw new RuntimeException(JaiI18N
244: .getString("ColorModelProxy0"));
245: }
246: }
247:
248: /**
249: * Deserialize the <code>ColorModelProxy</code>.
250: *
251: * @param out The <code>ObjectInputStream</code>.
252: */
253: private void readObject(ObjectInputStream in) throws IOException,
254: ClassNotFoundException {
255: // Read serialized form from the stream.
256: ColorSpace cs = null;
257:
258: // Switch on first int which is a flag indicating the class.
259: switch ((int) in.readInt()) {
260: case COLORMODEL_NULL:
261: colorModel = null;
262: break;
263: case COLORMODEL_FLOAT_DOUBLE_COMPONENT:
264: if ((cs = deserializeColorSpace(in)) == null) {
265: colorModel = null;
266: return;
267: }
268: colorModel = new FloatDoubleColorModel(cs,
269: in.readBoolean(), in.readBoolean(), in.readInt(),
270: in.readInt());
271: break;
272: case COLORMODEL_COMPONENT:
273: if ((cs = deserializeColorSpace(in)) == null) {
274: colorModel = null;
275: return;
276: }
277: colorModel = new ComponentColorModel(cs, (int[]) in
278: .readObject(), in.readBoolean(), in.readBoolean(),
279: in.readInt(), in.readInt());
280: break;
281: case COLORMODEL_INDEX:
282: colorModel = new IndexColorModel(in.readInt(),
283: in.readInt(), (int[]) in.readObject(), 0, in
284: .readBoolean(), in.readInt(), in.readInt());
285: break;
286: case COLORMODEL_DIRECT:
287: if ((cs = deserializeColorSpace(in)) != null) {
288: colorModel = new DirectColorModel(cs, in.readInt(), in
289: .readInt(), in.readInt(), in.readInt(), in
290: .readInt(), in.readBoolean(), in.readInt());
291: } else if (in.readBoolean()) {
292: colorModel = new DirectColorModel(in.readInt(), in
293: .readInt(), in.readInt(), in.readInt(), in
294: .readInt());
295: } else {
296: colorModel = new DirectColorModel(in.readInt(), in
297: .readInt(), in.readInt(), in.readInt());
298: }
299: break;
300: default:
301: // NB: Should never get here.
302: throw new RuntimeException(JaiI18N
303: .getString("ColorModelProxy1"));
304: }
305: }
306: }
|