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