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