001: /*
002: * $RCSfile: RawImageInputStream.java,v $
003: *
004: *
005: * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved.
006: *
007: * Redistribution and use in source and binary forms, with or without
008: * modification, are permitted provided that the following conditions
009: * are met:
010: *
011: * - Redistribution of source code must retain the above copyright
012: * notice, this list of conditions and the following disclaimer.
013: *
014: * - Redistribution in binary form must reproduce the above copyright
015: * notice, this list of conditions and the following disclaimer in
016: * the documentation and/or other materials provided with the
017: * distribution.
018: *
019: * Neither the name of Sun Microsystems, Inc. or the names of
020: * contributors may be used to endorse or promote products derived
021: * from this software without specific prior written permission.
022: *
023: * This software is provided "AS IS," without a warranty of any
024: * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND
025: * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY,
026: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY
027: * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL
028: * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF
029: * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
030: * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR
031: * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL,
032: * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND
033: * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR
034: * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE
035: * POSSIBILITY OF SUCH DAMAGES.
036: *
037: * You acknowledge that this software is not designed or intended for
038: * use in the design, construction, operation or maintenance of any
039: * nuclear facility.
040: *
041: * $Revision: 1.1 $
042: * $Date: 2005/02/11 05:01:20 $
043: * $State: Exp $
044: */
045: package com.sun.media.imageio.stream;
046:
047: import java.awt.Dimension;
048: import java.awt.Transparency;
049: import java.awt.color.ColorSpace;
050: import java.awt.color.ICC_ColorSpace;
051: import java.awt.color.ICC_Profile;
052: import java.awt.image.ColorModel;
053: import java.awt.image.ComponentColorModel;
054: import java.awt.image.ComponentSampleModel;
055: import java.awt.image.DirectColorModel;
056: import java.awt.image.IndexColorModel;
057: import java.awt.image.MultiPixelPackedSampleModel;
058: import java.awt.image.SampleModel;
059: import java.awt.image.SinglePixelPackedSampleModel;
060:
061: import java.io.IOException;
062: import java.io.InputStream;
063: import java.net.URL;
064: import java.nio.ByteOrder;
065: import java.util.StringTokenizer;
066:
067: import javax.imageio.ImageTypeSpecifier;
068: import javax.imageio.stream.*;
069: import javax.xml.parsers.DocumentBuilder;
070: import javax.xml.parsers.DocumentBuilderFactory;
071: import javax.xml.parsers.ParserConfigurationException;
072:
073: import org.w3c.dom.Document;
074: import org.w3c.dom.NamedNodeMap;
075: import org.w3c.dom.Node;
076: import org.w3c.dom.NodeList;
077: import org.xml.sax.InputSource;
078: import org.xml.sax.SAXException;
079:
080: import com.sun.media.imageioimpl.common.ImageUtil;
081:
082: /**
083: * This class defines the content of the <code>ImageInputStream</code>
084: * containing several raw images with the same image type: the number of
085: * the images, the image type, the offset for the first sample of each image,
086: * and the image size information.
087: *
088: * <p><code>ImageInputStream</code> methods are not commented individually.
089: * These methods merely forward the call to the <code>ImageInputStream</code>
090: * specified when the <code>RawImageInputStream</code> is constructed.</p>
091: */
092: public class RawImageInputStream implements ImageInputStream {
093: private static final String[] preDefinedColorSpaces = new String[] {
094: "GRAY", "sRGB", "LINEAR_RGB", "PYCC", "CIEXYZ" };
095:
096: private static final int[] preDefinedTypes = new int[] {
097: ColorSpace.CS_GRAY, ColorSpace.CS_sRGB,
098: ColorSpace.CS_LINEAR_RGB, ColorSpace.CS_PYCC,
099: ColorSpace.CS_CIEXYZ };
100:
101: /** Gets the attribute from the node. */
102: private static String getAttribute(Node node, String name) {
103: NamedNodeMap map = node.getAttributes();
104: node = map.getNamedItem(name);
105: return (node != null) ? node.getNodeValue() : null;
106: }
107:
108: /** Gets the boolean type attribute. */
109: private static boolean getBoolean(Node node, String name) {
110: String s = getAttribute(node, name);
111: return (s == null) ? false : (new Boolean(s)).booleanValue();
112: }
113:
114: /** Gets the integer type attribute. */
115: private static int getInt(Node node, String name) {
116: String s = getAttribute(node, name);
117: return (s == null) ? 0 : (new Integer(s)).intValue();
118: }
119:
120: /** Gets the integer type attribute. */
121: private static byte[] getByteArray(Node node, String name) {
122: String s = getAttribute(node, name);
123: if (s == null)
124: return null;
125: StringTokenizer token = new StringTokenizer(s);
126: int count = token.countTokens();
127: if (count == 0)
128: return null;
129:
130: byte[] buf = new byte[count];
131: int i = 0;
132: while (token.hasMoreElements()) {
133: buf[i++] = new Byte(token.nextToken()).byteValue();
134: }
135: return buf;
136: }
137:
138: /** Gets the integer type attribute. */
139: private static int[] getIntArray(Node node, String name) {
140: String s = getAttribute(node, name);
141: if (s == null)
142: return null;
143:
144: StringTokenizer token = new StringTokenizer(s);
145: int count = token.countTokens();
146: if (count == 0)
147: return null;
148:
149: int[] buf = new int[count];
150: int i = 0;
151: while (token.hasMoreElements()) {
152: buf[i++] = new Integer(token.nextToken()).intValue();
153: }
154: return buf;
155: }
156:
157: private static int getTransparency(String s) {
158: if ("BITMASK".equals(s))
159: return Transparency.BITMASK;
160: else if ("OPAQUE".equals(s))
161: return Transparency.OPAQUE;
162: else if ("TRANSLUCENT".equals(s))
163: return Transparency.TRANSLUCENT;
164: else
165: return 0;
166: }
167:
168: private static ColorSpace getColorSpace(Node node)
169: throws IOException {
170: NodeList nodes = node.getChildNodes();
171: for (int i = 0; i < nodes.getLength(); i++) {
172: Node child = nodes.item(i);
173: if ("colorSpace".equals(child.getNodeName())) {
174: String s = child.getNodeValue();
175: for (int j = 0; j < preDefinedColorSpaces.length; j++) {
176: if (preDefinedColorSpaces[j].equals(s))
177: return ColorSpace
178: .getInstance(preDefinedTypes[j]);
179: }
180:
181: InputStream stm = new URL(s).openStream();
182:
183: ColorSpace cp = new ICC_ColorSpace(ICC_Profile
184: .getInstance(stm));
185: stm.close();
186: return cp;
187: }
188: }
189: return null;
190: }
191:
192: /** The wrapperred <code>ImageInputStream</code>. */
193: private ImageInputStream source;
194:
195: /** The image type for all the images in the stream. */
196: private ImageTypeSpecifier type;
197:
198: /** The position of the first sample for each image. */
199: private long[] imageOffsets;
200:
201: /** The image sizes. */
202: private Dimension[] imageDimensions;
203:
204: /** Constructor.
205: * @param source The <code>ImageInputStream</code> containing all the raw
206: * images.
207: * @param type The <code>ImageTypeSpecifier</code> for all the images
208: * in the stream.
209: * @param imageOffsets The position of the first sample for each image
210: * in the stream.
211: * @param imageDimensions The image size for each image in the stream.
212: *
213: * @throws IllegalArgumentException If the sizes of
214: * <code>imageOffsets</code>
215: * and <code>imageDimensions</code> are different or if
216: * either array is null.
217: */
218: public RawImageInputStream(ImageInputStream source,
219: ImageTypeSpecifier type, long[] imageOffsets,
220: Dimension[] imageDimensions) {
221: if (imageOffsets == null || imageDimensions == null
222: || imageOffsets.length != imageDimensions.length) {
223: throw new IllegalArgumentException(I18N
224: .getString("RawImageInputStream0"));
225: }
226:
227: this .source = source;
228: this .type = type;
229: this .imageOffsets = imageOffsets;
230: this .imageDimensions = imageDimensions;
231: }
232:
233: /**
234: * Constructor.
235: *
236: * <p>This constructor is the same as
237: * {@link #RawImageInputStream(ImageInputStream,ImageTypeSpecifier,
238: * long[],Dimension[])} except that a <code>SampleModel</code> is
239: * supplied instead of an <code>ImageTypeSpecifier</code>. This
240: * constructor creates a <code>ColorModel</code> for the supplied
241: * <code>SampleModel</code> and then creates an
242: * <code>ImageTypeSpecifier</code>.</p>
243: *
244: * <p>Suitable <code>ColorModel</code>s are guaranteed to exist
245: * for all instances of <code>ComponentSampleModel</code>.
246: * For 1- and 3- banded <code>SampleModel</code>s, the
247: * <code>ColorModel</code> will be opaque. For 2- and 4-banded
248: * <code>SampleModel</code>s, the output will use alpha transparency
249: * which is not premultiplied. 1- and 2-banded data will use a
250: * grayscale <code>ColorSpace</code>, and 3- and 4-banded data a sRGB
251: * <code>ColorSpace</code>. Data with 5 or more bands will use a
252: * <code>ColorSpace</code> which satisfies compatibility constraints
253: * but is merely a placeholder and <i>does not perform correct color
254: * conversion to and from the C.I.E. XYZ and sRGB color spaces</i>.</p>
255: *
256: * <p>An instance of <code>DirectColorModel</code> will be created for
257: * instances of <code>SinglePixelPackedSampleModel</code> with no more
258: * than 4 bands.</p>
259: *
260: * <p>An instance of <code>IndexColorModel</code> will be created for
261: * instances of <code>MultiPixelPackedSampleModel</code>. The colormap
262: * will be a grayscale ramp with <code>1 << numberOfBits</code>
263: * entries ranging from zero to at most 255.</p>
264: *
265: * @param source The <code>ImageInputStream</code> containing all the raw
266: * images.
267: * @param sampleModel The <code>SampleModel</code> for all the images
268: * in the stream.
269: * @param imageOffsets The position of the first sample for each image
270: * in the stream.
271: * @param imageDimensions The image size for each image in the stream.
272: *
273: * @throws IllegalArgumentException If <code>sampleModel</code> is null.
274: * @throws IllegalArgumentException If the sizes of
275: * <code>imageOffsets</code>
276: * and <code>imageDimensions</code> are different or if
277: * either array is null.
278: * @throws IllegalArgumentException If it is not possible to create a
279: * <code>ColorModel</code> from the supplied
280: * <code>SampleModel</code>.
281: */
282: public RawImageInputStream(ImageInputStream source,
283: SampleModel sampleModel, long[] imageOffsets,
284: Dimension[] imageDimensions) {
285: if (imageOffsets == null || imageDimensions == null
286: || imageOffsets.length != imageDimensions.length) {
287: throw new IllegalArgumentException(I18N
288: .getString("RawImageInputStream0"));
289: }
290:
291: this .source = source;
292: ColorModel colorModel = ImageUtil.createColorModel(sampleModel);
293: if (colorModel == null) {
294: throw new IllegalArgumentException(I18N
295: .getString("RawImageInputStream4"));
296: }
297: this .type = new ImageTypeSpecifier(colorModel, sampleModel);
298: this .imageOffsets = imageOffsets;
299: this .imageDimensions = imageDimensions;
300: }
301:
302: /**
303: * Constructor.
304: *
305: * The <code>xmlSource</code> must adhere to the following DTD:
306: *
307: *<pre>
308: *<!DOCTYPE "com_sun_media_imageio_stream_raw_1.0" [
309: *
310: * <!ELEMENT com_sun_media_imageio_stream_raw_1.0
311: * (byteOrder?, offset?, width?, height?,
312: * (ComponentSampleModel |
313: * MultiPixelPackedSampleModel |
314: * SinglePixelPackedSampleModel),
315: * (ComponentColorModel |
316: * DirectColorModel |
317: * IndexColorModel)?)>
318: *
319: * <!ATTLIST com_sun_media_imageio_stream_raw_1.0
320: * xmlns CDATA #FIXED "http://com/sun/media/imageio">
321: *
322: * <!ELEMENT byteOrder (#PCDATA)>
323: * <!-- Byte order of data stream -->
324: * <!-- Either "NETWORK" or "REVERSE" -->
325: * <!-- Data type: String -->
326: *
327: * <!ELEMENT offset (#PCDATA)>
328: * <!-- Byte offset to the image data in the stream -->
329: * <!-- Data type: long -->
330: *
331: * <!ELEMENT width (#PCDATA)>
332: * <!-- Image width; default value is SampleModel width -->
333: * <!-- Data type: int -->
334: *
335: * <!ELEMENT height (#PCDATA)>
336: * <!-- Image height; default value is SampleModel height -->
337: * <!-- Data type: int -->
338: *
339: * <!ELEMENT ComponentSampleModel EMPTY>
340: * <!-- ComponentSampleModel -->
341: *
342: * <!ATTLIST ComponentSampleModel
343: * dataType (BYTE | USHORT | SHORT | INT | FLOAT | DOUBLE) #REQUIRED
344: * <!-- Data type: String -->
345: * w CDATA #REQUIRED
346: * <!-- SampleModel width -->
347: * <!-- Data type: int -->
348: * h CDATA #REQUIRED
349: * <!-- SampleModel height -->
350: * <!-- Data type: int -->
351: * pixelStride CDATA "1"
352: * <!-- SampleModel pixel stride -->
353: * <!-- Data type: int -->
354: * scanlineStride CDATA #REQUIRED
355: * <!-- SampleModel line stride -->
356: * <!-- Data type: int -->
357: * bankIndices CDATA #IMPLIED
358: * <!-- SampleModel bank indices -->
359: * <!-- Data type: int array -->
360: * bandOffsets CDATA #REQUIRED>
361: * <!-- SampleModel band offsets -->
362: * <!-- Data type: int array -->
363: *
364: * <!ELEMENT MultiPixelPackedSampleModel EMPTY>
365: * <!-- MultiPixelPackedSampleModel -->
366: *
367: * <!ATTLIST MultiPixelPackedSampleModel
368: * dataType (BYTE | USHORT | INT) #REQUIRED
369: * <!-- Data type: String -->
370: * w CDATA #REQUIRED
371: * <!-- SampleModel width -->
372: * <!-- Data type: int -->
373: * h CDATA #REQUIRED
374: * <!-- SampleModel height -->
375: * <!-- Data type: int -->
376: * numberOfBits CDATA #REQUIRED
377: * <!-- Number of bits per pixel -->
378: * <!-- Data type: int -->
379: * scanlineStride CDATA #REQUIRED
380: * <!-- SampleModel line stride -->
381: * <!-- Data type: int -->
382: * dataBitOffset CDATA "0">
383: * <!-- Offset to first valid bit in a line -->
384: * <!-- Data type: int -->
385: *
386: * <!ELEMENT SinglePixelPackedSampleModel EMPTY>
387: * <!-- SinglePixelPackedSampleModel -->
388: *
389: * <!ATTLIST SinglePixelPackedSampleModel
390: * dataType (BYTE | USHORT | INT) #REQUIRED
391: * <!-- Data type: String -->
392: * w CDATA #REQUIRED
393: * <!-- SampleModel width -->
394: * <!-- Data type: int -->
395: * h CDATA #REQUIRED
396: * <!-- SampleModel height -->
397: * <!-- Data type: int -->
398: * scanlineStride CDATA #REQUIRED
399: * <!-- SampleModel line stride -->
400: * <!-- Data type: int -->
401: * bitMasks CDATA #REQUIRED>
402: * <!-- Masks indicating RGBA positions -->
403: * <!-- Data type: int -->
404: *
405: * <!ELEMENT ComponentColorModel EMPTY>
406: * <!-- ComponentColorModel -->
407: *
408: * <!ATTLIST ComponentColorModel
409: * colorSpace (CIEXYZ | GRAY | LINEAR_RGB | PYCC | sRGB | URL)
410: * #REQUIRED
411: * <!-- A string representing a predefined ColorSpace or a URI
412: * representing the location of any ICC profile from which
413: * a ColorSpace may be created. -->
414: * <!-- Data type: String -->
415: * bits CDATA #IMPLIED
416: * <!-- Number of bits per color component -->
417: * <!-- Data type: int -->
418: * hasAlpha (true | false) #REQUIRED
419: * <!-- Whether an alpha channel is present -->
420: * <!-- Data type: boolean -->
421: * isAlphaPremultiplied (true | false) #REQUIRED
422: * <!-- Whether any alpha channel is premultiplied -->
423: * <!-- Data type: boolean -->
424: * transparency (BITMASK | OPAQUE | TRANSLUCENT) #REQUIRED
425: * <!-- The type of transparency -->
426: * transferType (BYTE | USHORT | SHORT | INT | FLOAT | DOUBLE)
427: * #REQUIRED>
428: * <!-- The data transfer type -->
429: *
430: * <!ELEMENT DirectColorModel EMPTY>
431: * <!-- DirectColorModel -->
432: *
433: * <!ATTLIST DirectColorModel
434: * colorSpace (LINEAR_RGB | sRGB | URL) #IMPLIED
435: * <!-- A string representing a predefined RGB ColorSpace or a
436: * URL representing the location of any ICC profile from
437: * which an RGB ColorSpace may be created. -->
438: * <!-- Data type: String -->
439: * bits CDATA #REQUIRED
440: * <!-- Number of bits per color component -->
441: * <!-- Data type: int -->
442: * rmask CDATA #REQUIRED
443: * <!-- Bitmask of the red component -->
444: * <!-- Data type: int -->
445: * gmask CDATA #REQUIRED
446: * <!-- Bitmask of the grenn component -->
447: * <!-- Data type: int -->
448: * bmask CDATA #REQUIRED
449: * <!-- Bitmask of the blue component -->
450: * <!-- Data type: int -->
451: * amask CDATA "0">
452: * <!-- Bitmask of the alpha component -->
453: * <!-- Data type: int -->
454: *
455: * <!ELEMENT IndexColorModel EMPTY>
456: * <!-- IndexColorModel -->
457: *
458: * <!ATTLIST IndexColorModel
459: * bits CDATA #REQUIRED
460: * <!-- Number of bits per color component -->
461: * <!-- Data type: int -->
462: * size CDATA #REQUIRED
463: * <!-- Number of elements in the colormap -->
464: * <!-- Data type: int -->
465: * r CDATA #REQUIRED
466: * <!-- Red elements of the colormap -->
467: * <!-- Data type: byte array -->
468: * g CDATA #REQUIRED
469: * <!-- Green elements of the colormap -->
470: * <!-- Data type: byte array -->
471: * b CDATA #REQUIRED
472: * <!-- Blue elements of the colormap -->
473: * <!-- Data type: byte array -->
474: * a CDATA #IMPLIED>
475: * <!-- Alpha elements of the colormap -->
476: * <!-- Data type: byte array -->
477: *]>
478: *</pre>
479: *
480: *
481: * @param source The <code>ImageInputStream</code> containing all the raw
482: * images.
483: * @param xmlSource The <code>org.xml.sax.InputSource</code> to provide
484: * the xml document in which the stream structure is defined.
485: *
486: * @throws RuntimeException If the parse configuration isn't correct.
487: *
488: * @throws IllegalArgumentException If the number of "width" elements isn't
489: * the same as the number of "height" elements.
490: *
491: * @throws SAXException If one is thrown in parsing.
492: *
493: * @throws IOException If one is thrown in parsing, or creating color space
494: * from a URL.
495: */
496: public RawImageInputStream(ImageInputStream source,
497: org.xml.sax.InputSource xmlSource) throws SAXException,
498: IOException {
499: this .source = source;
500:
501: DocumentBuilderFactory dbf = DocumentBuilderFactory
502: .newInstance();
503: dbf.setValidating(true);
504: dbf.setNamespaceAware(true);
505: dbf
506: .setAttribute(
507: "http://java.sun.com/xml/jaxp/properties/schemaLanguage",
508: "http://www.w3.org/2001/XMLSchema");
509: DocumentBuilder db = null;
510: try {
511: db = dbf.newDocumentBuilder();
512: } catch (ParserConfigurationException ex) {
513: throw new RuntimeException(I18N
514: .getString("RawImageInputStream1"), ex);
515: }
516:
517: Document doc = db.parse(xmlSource);
518:
519: //gets the byte order
520: NodeList nodes = doc.getElementsByTagName("byteOrder");
521: String byteOrder = nodes.item(0).getNodeValue();
522: if ("NETWORK".equals(byteOrder)) {
523: this .setByteOrder(ByteOrder.BIG_ENDIAN);
524: this .source.setByteOrder(ByteOrder.BIG_ENDIAN);
525: } else if ("REVERSE".equals(byteOrder)) {
526: this .setByteOrder(ByteOrder.LITTLE_ENDIAN);
527: this .setByteOrder(ByteOrder.LITTLE_ENDIAN);
528: }
529:
530: //gets image offsets
531: nodes = doc.getElementsByTagName("offset");
532: int length = nodes.getLength();
533: this .imageOffsets = new long[length];
534: for (int i = 0; i < length; i++) {
535: imageOffsets[i] = new Long(nodes.item(i).getNodeValue())
536: .longValue();
537: }
538:
539: //gets image dimensions
540: nodes = doc.getElementsByTagName("width");
541: NodeList nodes1 = doc.getElementsByTagName("height");
542: length = nodes.getLength();
543: if (length != nodes1.getLength())
544: throw new IllegalArgumentException(I18N
545: .getString("RawImageInputStream2"));
546:
547: this .imageDimensions = new Dimension[length];
548: for (int i = 0; i < length; i++) {
549: String w = nodes.item(i).getNodeValue();
550: String h = nodes1.item(i).getNodeValue();
551:
552: imageDimensions[i] = new Dimension((new Integer(w))
553: .intValue(), (new Integer(h)).intValue());
554: }
555:
556: //get sampleModel
557: SampleModel sampleModel = null;
558:
559: // for ComponentSampleModel
560: nodes = doc.getElementsByTagName("ComponentSampleModel");
561: if (nodes.getLength() > 0) {
562: Node node = nodes.item(0);
563: int[] bankIndices = getIntArray(node, "bankIndices");
564:
565: if (bankIndices == null)
566: sampleModel = new ComponentSampleModel(getInt(node,
567: "dataType"), getInt(node, "w"), getInt(node,
568: "h"), getInt(node, "pixelStride"), getInt(node,
569: "scanlineStride"), getIntArray(node,
570: "bandOffsets"));
571: else
572: sampleModel = new ComponentSampleModel(getInt(node,
573: "dataType"), getInt(node, "w"), getInt(node,
574: "h"), getInt(node, "pixelStride"), getInt(node,
575: "scanlineStride"), bankIndices, getIntArray(
576: node, "bandOffsets"));
577: }
578:
579: // for MultiPixelPackedSampleModel
580: nodes = doc.getElementsByTagName("MultiPixelPackedSampleModel");
581: if (nodes.getLength() > 0) {
582: Node node = nodes.item(0);
583: sampleModel = new MultiPixelPackedSampleModel(getInt(node,
584: "dataType"), getInt(node, "w"), getInt(node, "h"),
585: getInt(node, "numberOfBits"), getInt(node,
586: "scanlineStride"), getInt(node,
587: "dataBitOffset"));
588: }
589:
590: // for SinglePixelPackedSampleModel
591: nodes = doc
592: .getElementsByTagName("SinglePixelPackedSampleModel");
593: if (nodes.getLength() > 0) {
594: Node node = nodes.item(0);
595: sampleModel = new SinglePixelPackedSampleModel(getInt(node,
596: "dataType"), getInt(node, "w"), getInt(node, "h"),
597: getInt(node, "scanlineStride"), getIntArray(node,
598: "bitMasks"));
599: }
600:
601: //get colorModel
602: ColorModel colorModel = null;
603:
604: // for ComponentColorModel
605: nodes = doc.getElementsByTagName("ComponentColorModel");
606: if (nodes.getLength() > 0) {
607: Node node = nodes.item(0);
608: colorModel = new ComponentColorModel(
609: getColorSpace(node),
610: getIntArray(node, "bits"),
611: getBoolean(node, "hasAlpha"),
612: getBoolean(node, "isAlphaPremultiplied"),
613: getTransparency(getAttribute(node, "transparency")),
614: getInt(node, "transferType"));
615: }
616:
617: // for DirectColorModel
618: nodes = doc.getElementsByTagName("DirectColorModel");
619: if (nodes.getLength() > 0) {
620: Node node = nodes.item(0);
621: colorModel = new DirectColorModel(getColorSpace(node),
622: getInt(node, "bits"), getInt(node, "rmask"),
623: getInt(node, "gmask"), getInt(node, "bmask"),
624: getInt(node, "amask"), false, Transparency.OPAQUE);
625: }
626:
627: // for IndexColorModel
628: nodes = doc.getElementsByTagName("IndexColorModel");
629: if (nodes.getLength() > 0) {
630: Node node = nodes.item(0);
631: byte[] alpha = getByteArray(node, "a");
632:
633: if (alpha == null)
634: colorModel = new IndexColorModel(getInt(node, "bits"),
635: getInt(node, "size"), getByteArray(node, "r"),
636: getByteArray(node, "g"),
637: getByteArray(node, "b"));
638: else
639: colorModel = new IndexColorModel(getInt(node, "bits"),
640: getInt(node, "size"), getByteArray(node, "r"),
641: getByteArray(node, "g"),
642: getByteArray(node, "b"), alpha);
643: }
644:
645: //create image type
646: this .type = new ImageTypeSpecifier(colorModel, sampleModel);
647:
648: //assign imagedimension based on the sample model
649: if (this .imageDimensions.length == 0) {
650: this .imageDimensions = new Dimension[this .imageOffsets.length];
651:
652: imageDimensions[0] = new Dimension(sampleModel.getWidth(),
653: sampleModel.getHeight());
654: for (int i = 1; i < imageDimensions.length; i++)
655: imageDimensions[i] = imageDimensions[0];
656: }
657: }
658:
659: /**
660: * Retrieves the image type.
661: *
662: * @return the image type
663: */
664: public ImageTypeSpecifier getImageType() {
665: return type;
666: }
667:
668: /**
669: * Retrieves the image offset of the <code>imageIndex</code>th image.
670: *
671: * @param imageIndex the index of the image of interest.
672: * @throws IllegalArgumentException If the provided parameter is out of
673: * range.
674: * @return the offset in the stream to the specified image.
675: */
676: public long getImageOffset(int imageIndex) {
677: if (imageIndex < 0 || imageIndex >= imageOffsets.length)
678: throw new IllegalArgumentException(I18N
679: .getString("RawImageInputStream3"));
680: return imageOffsets[imageIndex];
681: }
682:
683: /** Retrieves the dimnsion of the <code>imageIndex</code>th image.
684: * @param imageIndex the index of the image of interest.
685: * @throws IllegalArgumentException If the provided parameter is out of
686: * rangle.
687: * @return the size of the specified image.
688: */
689: public Dimension getImageDimension(int imageIndex) {
690: if (imageIndex < 0 || imageIndex >= imageOffsets.length)
691: throw new IllegalArgumentException(I18N
692: .getString("RawImageInputStream3"));
693: return imageDimensions[imageIndex];
694: }
695:
696: /**
697: * Retrieves the number of images in the <code>ImageInputStream</code>.
698: * @return the number of image in the stream.
699: */
700: public int getNumImages() {
701: return imageOffsets.length;
702: }
703:
704: public void setByteOrder(ByteOrder byteOrder) {
705: source.setByteOrder(byteOrder);
706: }
707:
708: public ByteOrder getByteOrder() {
709: return source.getByteOrder();
710: }
711:
712: public int read() throws IOException {
713: return source.read();
714: }
715:
716: public int read(byte[] b) throws IOException {
717: return source.read(b);
718: }
719:
720: public int read(byte[] b, int off, int len) throws IOException {
721: return source.read(b, off, len);
722: }
723:
724: public void readBytes(IIOByteBuffer buf, int len)
725: throws IOException {
726: source.readBytes(buf, len);
727: }
728:
729: public boolean readBoolean() throws IOException {
730: return source.readBoolean();
731: }
732:
733: public byte readByte() throws IOException {
734: return source.readByte();
735: }
736:
737: public int readUnsignedByte() throws IOException {
738: return source.readUnsignedByte();
739: }
740:
741: public short readShort() throws IOException {
742: return source.readShort();
743: }
744:
745: public int readUnsignedShort() throws IOException {
746: return source.readUnsignedShort();
747: }
748:
749: public char readChar() throws IOException {
750: return source.readChar();
751: }
752:
753: public int readInt() throws IOException {
754: return source.readInt();
755: }
756:
757: public long readUnsignedInt() throws IOException {
758: return source.readUnsignedInt();
759: }
760:
761: public long readLong() throws IOException {
762: return source.readLong();
763: }
764:
765: public float readFloat() throws IOException {
766: return source.readFloat();
767: }
768:
769: public double readDouble() throws IOException {
770: return source.readDouble();
771: }
772:
773: public String readLine() throws IOException {
774: return source.readLine();
775: }
776:
777: public String readUTF() throws IOException {
778: return source.readUTF();
779: }
780:
781: public void readFully(byte[] b, int off, int len)
782: throws IOException {
783: source.readFully(b, off, len);
784: }
785:
786: public void readFully(byte[] b) throws IOException {
787: source.readFully(b);
788: }
789:
790: public void readFully(short[] s, int off, int len)
791: throws IOException {
792: source.readFully(s, off, len);
793: }
794:
795: public void readFully(char[] c, int off, int len)
796: throws IOException {
797: source.readFully(c, off, len);
798: }
799:
800: public void readFully(int[] i, int off, int len) throws IOException {
801: source.readFully(i, off, len);
802: }
803:
804: public void readFully(long[] l, int off, int len)
805: throws IOException {
806: source.readFully(l, off, len);
807: }
808:
809: public void readFully(float[] f, int off, int len)
810: throws IOException {
811: source.readFully(f, off, len);
812: }
813:
814: public void readFully(double[] d, int off, int len)
815: throws IOException {
816: source.readFully(d, off, len);
817: }
818:
819: public long getStreamPosition() throws IOException {
820: return source.getStreamPosition();
821: }
822:
823: public int getBitOffset() throws IOException {
824: return source.getBitOffset();
825: }
826:
827: public void setBitOffset(int bitOffset) throws IOException {
828: source.setBitOffset(bitOffset);
829: }
830:
831: public int readBit() throws IOException {
832: return source.readBit();
833: }
834:
835: public long readBits(int numBits) throws IOException {
836: return source.readBits(numBits);
837: }
838:
839: public long length() throws IOException {
840: return source.length();
841: }
842:
843: public int skipBytes(int n) throws IOException {
844: return source.skipBytes(n);
845: }
846:
847: public long skipBytes(long n) throws IOException {
848: return source.skipBytes(n);
849: }
850:
851: public void seek(long pos) throws IOException {
852: source.seek(pos);
853: }
854:
855: public void mark() {
856: source.mark();
857: }
858:
859: public void reset() throws IOException {
860: source.reset();
861: }
862:
863: public void flushBefore(long pos) throws IOException {
864: source.flushBefore(pos);
865: }
866:
867: public void flush() throws IOException {
868: source.flush();
869: }
870:
871: public long getFlushedPosition() {
872: return source.getFlushedPosition();
873: }
874:
875: public boolean isCached() {
876: return source.isCached();
877: }
878:
879: public boolean isCachedMemory() {
880: return source.isCachedMemory();
881: }
882:
883: public boolean isCachedFile() {
884: return source.isCachedFile();
885: }
886:
887: public void close() throws IOException {
888: source.close();
889: }
890: }
|