1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 package org.apache.commons.imaging; 18 19 import java.awt.Dimension; 20 import java.awt.image.BufferedImage; 21 import java.io.File; 22 import java.io.IOException; 23 import java.io.OutputStream; 24 import java.io.PrintWriter; 25 import java.io.StringWriter; 26 import java.util.ArrayList; 27 import java.util.Arrays; 28 import java.util.List; 29 import java.util.Locale; 30 import java.util.logging.Level; 31 import java.util.logging.Logger; 32 33 import org.apache.commons.imaging.common.BinaryFileParser; 34 import org.apache.commons.imaging.common.BufferedImageFactory; 35 import org.apache.commons.imaging.common.ImageMetadata; 36 import org.apache.commons.imaging.common.SimpleBufferedImageFactory; 37 import org.apache.commons.imaging.common.bytesource.ByteSource; 38 import org.apache.commons.imaging.common.bytesource.ByteSourceArray; 39 import org.apache.commons.imaging.common.bytesource.ByteSourceFile; 40 import org.apache.commons.imaging.formats.bmp.BmpImageParser; 41 import org.apache.commons.imaging.formats.dcx.DcxImageParser; 42 import org.apache.commons.imaging.formats.gif.GifImageParser; 43 import org.apache.commons.imaging.formats.icns.IcnsImageParser; 44 import org.apache.commons.imaging.formats.ico.IcoImageParser; 45 import org.apache.commons.imaging.formats.jpeg.JpegImageParser; 46 import org.apache.commons.imaging.formats.pcx.PcxImageParser; 47 import org.apache.commons.imaging.formats.png.PngImageParser; 48 import org.apache.commons.imaging.formats.pnm.PnmImageParser; 49 import org.apache.commons.imaging.formats.psd.PsdImageParser; 50 import org.apache.commons.imaging.formats.rgbe.RgbeImageParser; 51 import org.apache.commons.imaging.formats.tiff.TiffImageParser; 52 import org.apache.commons.imaging.formats.wbmp.WbmpImageParser; 53 import org.apache.commons.imaging.formats.xbm.XbmImageParser; 54 import org.apache.commons.imaging.formats.xpm.XpmImageParser; 55 56 /** 57 * Provides the abstract base class for all image reading and writing 58 * utilities. ImageParser implementations are expected to extend this 59 * class providing logic for identifying and processing data in their 60 * own specific format. Specific implementations are found 61 * under the com.apache.commons.imaging.formats package. 62 * 63 * <h2>Application Notes</h2> 64 * 65 * <h3>Format support</h3> 66 * 67 * For the most recent information on format support for the 68 * Apache Commons Imaging package, refer to 69 * <a href="https://commons.apache.org/imaging/formatsupport.html">Format Support</a> 70 * at the main project development web site. 71 * 72 * <h3>On the accuracy of this Javadoc</h3> 73 * 74 * The original authors of this class did not supply documentation. 75 * The Javadoc for this class is based on inspection of the 76 * source code. In some cases, the purpose and usage for particular 77 * methods was deduced from the source and may not perfectly reflect 78 * the intentions of the original. Therefore, you should not assume 79 * that the documentation is perfect, especially in the more obscure 80 * and specialized areas of implementation. 81 * 82 * <h3>The "params" argument</h3> 83 * 84 * <p>Many of the methods specified by this class accept an argument of 85 * type {@code T} defining the parameters to be used when 86 * processing an image. For example, some of the output formats permit 87 * of different kinds of image compression or color models. Some of the 88 * reading methods permit the calling application to require strict 89 * format compliance.</p> 90 * 91 * @param <T> type of parameters used by this image parser 92 */ 93 public abstract class ImageParser<T extends ImagingParameters> extends BinaryFileParser { 94 95 private static final Logger LOGGER = Logger.getLogger(ImageParser.class.getName()); 96 97 /** 98 * Gets an array of new instances of all image parsers. 99 * 100 * @return A valid array of image parsers 101 */ 102 public static List<ImageParser<?>> getAllImageParsers() { 103 return Arrays.asList( 104 new BmpImageParser(), 105 new DcxImageParser(), 106 new GifImageParser(), 107 new IcnsImageParser(), 108 new IcoImageParser(), 109 new JpegImageParser(), 110 new PcxImageParser(), 111 new PngImageParser(), 112 new PnmImageParser(), 113 new PsdImageParser(), 114 new RgbeImageParser(), 115 new TiffImageParser(), 116 new WbmpImageParser(), 117 new XbmImageParser(), 118 new XpmImageParser() 119 // new JBig2ImageParser(), 120 // new TgaImageParser(), 121 ); 122 } 123 124 /** 125 * Get a default parameters instance for this parser. 126 * @return default parameters instance 127 */ 128 public abstract T getDefaultParameters(); 129 130 /** 131 * Get image metadata from the specified byte source. Format-specific 132 * ImageParser implementations are expected to return a valid 133 * IImageMetadata object or to throw an ImageReadException if unable 134 * to process the specified byte source. 135 * 136 * @param byteSource A valid byte source. 137 * @return A valid, potentially subject-matter-specific implementation of 138 * the IImageMetadata interface describing the content extracted 139 * from the source content. 140 * @throws ImageReadException In the event that the ByteSource 141 * content does not conform to the format of the specific parser 142 * implementation. 143 * @throws IOException In the event of unsuccessful data read operation. 144 */ 145 public final ImageMetadata getMetadata(final ByteSource byteSource) throws ImageReadException, IOException { 146 return getMetadata(byteSource, null); 147 } 148 149 /** 150 * Get image metadata from the specified byte source. Format-specific 151 * ImageParser implementations are expected to return a valid 152 * IImageMetadata object or to throw an ImageReadException if unable 153 * to process the specified byte source. 154 * 155 * <p>The params argument provides a mechanism for individual 156 * implementations to pass optional information into the parser. 157 * Not all formats will require this capability. Because the 158 * base class may call this method with a null params argument, 159 * implementations should <strong>always</strong> include logic 160 * for ignoring null input. 161 * 162 * @param byteSource A valid byte source. 163 * @param params Optional instructions for special-handling or 164 * interpretation of the input data (null objects are permitted and 165 * must be supported by implementations). 166 * @return A valid, potentially subject-matter-specific implementation of 167 * the IImageMetadata interface describing the content extracted 168 * from the source content. 169 * @throws ImageReadException In the event that the ByteSource 170 * content does not conform to the format of the specific parser 171 * implementation. 172 * @throws IOException In the event of unsuccessful data read operation. 173 */ 174 public abstract ImageMetadata getMetadata(ByteSource byteSource, T params) 175 throws ImageReadException, IOException; 176 177 /** 178 * Get image metadata from the specified array of bytes. Format-specific 179 * ImageParser implementations are expected to return a valid 180 * IImageMetadata object or to throw an ImageReadException if unable 181 * to process the specified data. 182 * 183 * @param bytes A valid array of bytes 184 * @return A valid, potentially subject-matter-specific implementation of 185 * the IImageMetadata interface describing the content extracted 186 * from the source content. 187 * @throws ImageReadException In the event that the specified content 188 * does not conform to the format of the specific 189 * parser implementation. 190 * @throws IOException In the event of unsuccessful data read operation. 191 */ 192 public final ImageMetadata getMetadata(final byte[] bytes) throws ImageReadException, IOException { 193 return getMetadata(bytes, null); 194 } 195 196 /** 197 * Get image metadata from the specified array of bytes. Format-specific 198 * ImageParser implementations are expected to return a valid 199 * IImageMetadata object or to throw an ImageReadException if unable 200 * to process the specified data. 201 * 202 * <p>The params argument provides a mechanism for individual 203 * implementations to pass optional information into the parser. 204 * Not all formats will require this capability. Because the 205 * base class may call this method with a null params argument, 206 * implementations should <strong>always</strong> include logic 207 * for ignoring null input. 208 * 209 * @param bytes A valid array of bytes 210 * @param params Optional instructions for special-handling or 211 * interpretation of the input data (null objects are permitted and 212 * must be supported by implementations). 213 * @return A valid image metadata object describing the content extracted 214 * from the specified content. 215 * @throws ImageReadException In the event that the specified content 216 * does not conform to the format of the specific 217 * parser implementation. 218 * @throws IOException In the event of unsuccessful data read operation. 219 */ 220 public final ImageMetadata getMetadata(final byte[] bytes, final T params) 221 throws ImageReadException, IOException { 222 return getMetadata(new ByteSourceArray(bytes), params); 223 } 224 225 /** 226 * Get image metadata from the specified file. Format-specific 227 * ImageParser implementations are expected to return a valid 228 * IImageMetadata object or to throw an ImageReadException if unable 229 * to process the specified data. 230 * 231 * @param file A valid reference to a file. 232 * @return A valid image metadata object describing the content extracted 233 * from the specified content. 234 * @throws ImageReadException In the event that the specified content 235 * does not conform to the format of the specific 236 * parser implementation. 237 * @throws IOException In the event of unsuccessful file read or 238 * access operation. 239 */ 240 public final ImageMetadata getMetadata(final File file) throws ImageReadException, IOException { 241 return getMetadata(file, null); 242 } 243 244 /** 245 * Get image metadata from the specified file. Format-specific 246 * ImageParser implementations are expected to return a valid 247 * IImageMetadata object or to throw an ImageReadException if unable 248 * to process the specified data. 249 * 250 * <p>The params argument provides a mechanism for individual 251 * implementations to pass optional information into the parser. 252 * Not all formats will require this capability. Because the 253 * base class may call this method with a null params argument, 254 * implementations should <strong>always</strong> include logic 255 * for ignoring null input. 256 * 257 * @param file A valid reference to a file. 258 * @param params Optional instructions for special-handling or 259 * interpretation of the input data (null objects are permitted and 260 * must be supported by implementations). 261 * @return A valid image metadata object describing the content extracted 262 * from the specified content. 263 * @throws ImageReadException In the event that the specified content 264 * does not conform to the format of the specific 265 * parser implementation. 266 * @throws IOException In the event of unsuccessful file read or 267 * access operation. 268 */ 269 public final ImageMetadata getMetadata(final File file, final T params) 270 throws ImageReadException, IOException { 271 if (LOGGER.isLoggable(Level.FINEST)) { 272 LOGGER.finest(getName() + ".getMetadata" + ": " + file.getName()); 273 } 274 275 if (!canAcceptExtension(file)) { 276 return null; 277 } 278 279 return getMetadata(new ByteSourceFile(file), params); 280 } 281 282 /** 283 * Get image information from the specified ByteSource. Format-specific 284 * ImageParser implementations are expected to return a valid 285 * ImageInfo object or to throw an ImageReadException if unable 286 * to process the specified data. 287 * 288 * <p>The params argument provides a mechanism for individual 289 * implementations to pass optional information into the parser. 290 * Not all formats will require this capability. Because the 291 * base class may call this method with a null params argument, 292 * implementations should <strong>always</strong> include logic 293 * for ignoring null input. 294 * 295 * @param byteSource A valid ByteSource object 296 * @param params Optional instructions for special-handling or interpretation 297 * of the input data (null objects are permitted and 298 * must be supported by implementations). 299 * @return A valid image information object describing the content extracted 300 * from the specified data. 301 * @throws ImageReadException In the event that the specified content 302 * does not conform to the format of the specific 303 * parser implementation. 304 * @throws IOException In the event of unsuccessful data access operation. 305 */ 306 public abstract ImageInfo getImageInfo(ByteSource byteSource, T params) 307 throws ImageReadException, IOException; 308 309 /** 310 * Get image information from the specified ByteSource. Format-specific 311 * ImageParser implementations are expected to return a valid 312 * ImageInfo object or to throw an ImageReadException if unable 313 * to process the specified data. 314 * 315 * @param byteSource A valid ByteSource object 316 * @return A valid image information object describing the content extracted 317 * from the specified data. 318 * @throws ImageReadException In the event that the specified content 319 * does not conform to the format of the specific 320 * parser implementation. 321 * @throws IOException In the event of unsuccessful data 322 * access operation. 323 */ 324 public final ImageInfo getImageInfo(final ByteSource byteSource) throws ImageReadException, IOException { 325 return getImageInfo(byteSource, null); 326 } 327 328 /** 329 * Get image information from the specified array of bytes. Format-specific 330 * ImageParser implementations are expected to return a valid 331 * ImageInfo object or to throw an ImageReadException if unable 332 * to process the specified data. 333 * <p>The params argument provides a mechanism for individual 334 * implementations to pass optional information into the parser. 335 * Not all formats will require this capability. Because the 336 * base class may call this method with a null params argument, 337 * implementations should <strong>always</strong> include logic 338 * for ignoring null input. 339 * 340 * @param bytes A valid array of bytes 341 * @param params Optional instructions for special-handling or 342 * interpretation of the input data (null objects are permitted and 343 * must be supported by implementations). 344 * @return A valid image information object describing the content extracted 345 * from the specified data. 346 * @throws ImageReadException In the event that the specified content 347 * does not conform to the format of the specific 348 * parser implementation. 349 * @throws IOException In the event of unsuccessful data 350 * access operation. 351 */ 352 public final ImageInfo getImageInfo(final byte[] bytes, final T params) 353 throws ImageReadException, IOException { 354 return getImageInfo(new ByteSourceArray(bytes), params); 355 } 356 357 /** 358 * Get image information from the specified file Format-specific 359 * ImageParser implementations are expected to return a valid 360 * ImageInfo object or to throw an ImageReadException if unable 361 * to process the specified data. 362 * <p>The params argument provides a mechanism for individual 363 * implementations to pass optional information into the parser. 364 * Not all formats will require this capability. Because the 365 * base class may call this method with a null params argument, 366 * implementations should <strong>always</strong> include logic 367 * for ignoring null input. 368 * 369 * @param file A valid File object 370 * @param params Optional instructions for special-handling or 371 * interpretation of the input data (null objects are permitted and 372 * must be supported by implementations). 373 * @return A valid image information object describing the content extracted 374 * from the specified data. 375 * @throws ImageReadException In the event that the specified content 376 * does not conform to the format of the specific 377 * parser implementation. 378 * @throws IOException In the event of unsuccessful file read or 379 * access operation. 380 */ 381 public final ImageInfo getImageInfo(final File file, final T params) 382 throws ImageReadException, IOException { 383 if (!canAcceptExtension(file)) { 384 return null; 385 } 386 387 return getImageInfo(new ByteSourceFile(file), params); 388 } 389 390 /** 391 * Determines the format compliance of the content of the supplied byte 392 * source based on rules provided by a specific implementation. 393 * 394 * @param byteSource A valid instance of ByteSource 395 * @return true if the content is format-compliant; otherwise, false 396 * @throws ImageReadException may be thrown by sub-classes 397 * @throws IOException may be thrown by sub-classes 398 */ 399 public FormatCompliance getFormatCompliance(final ByteSource byteSource) 400 throws ImageReadException, IOException { 401 return null; 402 } 403 404 /** 405 * Determines the format compliance of the content of the supplied byte 406 * array based on rules provided by a specific implementation. 407 * 408 * @param bytes A valid byte array. 409 * @return A valid FormatCompliance object. 410 * @throws ImageReadException may be thrown by sub-classes 411 * @throws IOException may be thrown by sub-classes 412 */ 413 public final FormatCompliance getFormatCompliance(final byte[] bytes) 414 throws ImageReadException, IOException { 415 return getFormatCompliance(new ByteSourceArray(bytes)); 416 } 417 418 /** 419 * Determines the format compliance of the specified file based on 420 * rules provided by a specific implementation. 421 * 422 * @param file A valid reference to a file. 423 * @return A valid format compliance object. 424 * @throws ImageReadException may be thrown by sub-classes 425 * @throws IOException may be thrown by sub-classes 426 */ 427 public final FormatCompliance getFormatCompliance(final File file) 428 throws ImageReadException, IOException { 429 if (!canAcceptExtension(file)) { 430 return null; 431 } 432 433 return getFormatCompliance(new ByteSourceFile(file)); 434 } 435 436 /** 437 * Gets all images specified by the byte source (some 438 * formats may include multiple images within a single data source). 439 * 440 * @param byteSource A valid instance of ByteSource. 441 * @return A valid (potentially empty) list of BufferedImage objects. 442 * @throws ImageReadException In the event that the specified content 443 * does not conform to the format of the specific 444 * parser implementation. 445 * @throws IOException In the event of unsuccessful read or access operation. 446 */ 447 public List<BufferedImage> getAllBufferedImages(final ByteSource byteSource) 448 throws ImageReadException, IOException { 449 final BufferedImage bi = getBufferedImage(byteSource, null); 450 451 final List<BufferedImage> result = new ArrayList<>(); 452 453 // FIXME this doesn't look like we're actually getting all images contained in the given ByteSource... 454 result.add(bi); 455 456 return result; 457 } 458 459 /** 460 * Gets all images specified by the byte array (some 461 * formats may include multiple images within a single data source). 462 * 463 * @param bytes A valid byte array 464 * @return A valid (potentially empty) list of BufferedImage objects. 465 * @throws ImageReadException In the event that the specified content 466 * does not conform to the format of the specific 467 * parser implementation. 468 * @throws IOException In the event of unsuccessful read or access operation. 469 */ 470 public final List<BufferedImage> getAllBufferedImages(final byte[] bytes) 471 throws ImageReadException, IOException { 472 return getAllBufferedImages(new ByteSourceArray(bytes)); 473 } 474 475 /** 476 * Gets all images specified by indicated file (some 477 * formats may include multiple images within a single data source). 478 * 479 * @param file A valid reference to a file. 480 * @return A valid (potentially empty) list of BufferedImage objects. 481 * @throws ImageReadException In the event that the specified content 482 * does not conform to the format of the specific 483 * parser implementation. 484 * @throws IOException In the event of unsuccessful read or access operation. 485 */ 486 public final List<BufferedImage> getAllBufferedImages(final File file) throws ImageReadException, IOException { 487 if (!canAcceptExtension(file)) { 488 return null; 489 } 490 491 return getAllBufferedImages(new ByteSourceFile(file)); 492 } 493 494 /** 495 * Gets a buffered image specified by the byte source (for 496 * sources that specify multiple images, choice of which image 497 * is returned is implementation dependent). 498 * 499 * @param byteSource A valid instance of ByteSource 500 * @param params Optional instructions for special-handling or 501 * interpretation of the input data (null objects are permitted and 502 * must be supported by implementations). 503 * @return A valid instance of BufferedImage. 504 * @throws ImageReadException In the event that the specified content 505 * does not conform to the format of the specific 506 * parser implementation. 507 * @throws IOException In the event of unsuccessful read or access operation. 508 */ 509 public abstract BufferedImage getBufferedImage(ByteSource byteSource, T params) 510 throws ImageReadException, IOException; 511 512 /** 513 * Gets a buffered image specified by the byte array (for 514 * sources that specify multiple images, choice of which image 515 * is returned is implementation dependent). 516 * 517 * @param bytes A valid byte array 518 * @param params Optional instructions for special-handling or 519 * interpretation of the input data (null objects are permitted and 520 * must be supported by implementations). 521 * @return A valid instance of BufferedImage. 522 * @throws ImageReadException In the event that the specified content 523 * does not conform to the format of the specific 524 * parser implementation. 525 * @throws IOException In the event of unsuccessful read or access operation. 526 */ 527 public final BufferedImage getBufferedImage(final byte[] bytes, final T params) 528 throws ImageReadException, IOException { 529 return getBufferedImage(new ByteSourceArray(bytes), params); 530 } 531 532 /** 533 * Gets a buffered image specified by the indicated file (for 534 * sources that specify multiple images, choice of which image 535 * is returned is implementation dependent). 536 * 537 * @param file A valid file reference. 538 * @param params Optional instructions for special-handling or 539 * interpretation of the input data (null objects are permitted and 540 * must be supported by implementations). 541 * @return A valid instance of BufferedImage. 542 * @throws ImageReadException In the event that the specified content 543 * does not conform to the format of the specific 544 * parser implementation. 545 * @throws IOException In the event of unsuccessful read or access operation. 546 */ 547 public final BufferedImage getBufferedImage(final File file, final T params) 548 throws ImageReadException, IOException { 549 if (!canAcceptExtension(file)) { 550 return null; 551 } 552 553 return getBufferedImage(new ByteSourceFile(file), params); 554 } 555 556 557 /** 558 * Writes the content of a BufferedImage to the specified output 559 * stream. 560 * 561 * <p>The params argument provides a mechanism for individual 562 * implementations to pass optional information into the parser. 563 * Not all formats will support this capability. Currently, 564 * some of the parsers do not check for null arguments.</p> 565 * 566 * @param src An image giving the source content for output 567 * @param os A valid output stream for storing the formatted image 568 * @param params optional parameters, defining format-specific instructions for output 569 * (such as selections for data compression, color models, etc.) 570 * @throws ImageWriteException In the event that the output format 571 * cannot handle the input image or invalid params are specified. 572 * @throws IOException In the event of an write error from 573 * the output stream. 574 */ 575 public void writeImage(final BufferedImage src, final OutputStream os, T params) 576 throws ImageWriteException, IOException { 577 os.close(); // we are obligated to close stream. 578 579 throw new ImageWriteException("This image format (" + getName() + ") cannot be written."); 580 } 581 582 /** 583 * Get the size of the image described by the specified byte array. 584 * 585 * @param bytes A valid byte array. 586 * @return A valid instance of Dimension. 587 * @throws ImageReadException In the event that the specified content 588 * does not conform to the format of the specific 589 * parser implementation. 590 * @throws IOException In the event of unsuccessful read or access operation. 591 */ 592 public final Dimension getImageSize(final byte[] bytes) throws ImageReadException, IOException { 593 return getImageSize(bytes, null); 594 } 595 596 /** 597 * Get the size of the image described by the specified byte array. 598 * 599 * @param bytes A valid byte array. 600 * @param params Optional instructions for special-handling or 601 * interpretation of the input data. 602 * @return A valid instance of Dimension. 603 * @throws ImageReadException In the event that the specified content 604 * does not conform to the format of the specific 605 * parser implementation. 606 * @throws IOException In the event of unsuccessful read or access operation. 607 */ 608 public final Dimension getImageSize(final byte[] bytes, final T params) 609 throws ImageReadException, IOException { 610 return getImageSize(new ByteSourceArray(bytes), params); 611 } 612 613 /** 614 * Get the size of the image described by the specified file. 615 * 616 * @param file A valid reference to a file. 617 * @return A valid instance of Dimension. 618 * @throws ImageReadException In the event that the specified content 619 * does not conform to the format of the specific 620 * parser implementation. 621 * @throws IOException In the event of unsuccessful read or access operation. 622 */ 623 public final Dimension getImageSize(final File file) throws ImageReadException, IOException { 624 return getImageSize(file, null); 625 } 626 627 /** 628 * Get the size of the image described by the specified file. 629 * 630 * @param file A valid reference to a file. 631 * @param params Optional instructions for special-handling or 632 * interpretation of the input data. 633 * @return A valid instance of Dimension. 634 * @throws ImageReadException In the event that the specified content 635 * does not conform to the format of the specific 636 * parser implementation. 637 * @throws IOException In the event of unsuccessful read or access operation. 638 */ 639 public final Dimension getImageSize(final File file, final T params) 640 throws ImageReadException, IOException { 641 642 if (!canAcceptExtension(file)) { 643 return null; 644 } 645 646 return getImageSize(new ByteSourceFile(file), params); 647 } 648 649 /** 650 * Get the size of the image described by the specified ByteSource. 651 * 652 * @param byteSource A valid reference to a ByteSource. 653 * @param params Optional instructions for special-handling or 654 * interpretation of the input data. 655 * @return A valid instance of Dimension. 656 * @throws ImageReadException In the event that the specified content 657 * does not conform to the format of the specific 658 * parser implementation. 659 * @throws IOException In the event of unsuccessful read or access operation. 660 */ 661 public abstract Dimension getImageSize(ByteSource byteSource, T params) 662 throws ImageReadException, IOException; 663 664 /** 665 * Get an array of bytes describing the International Color Consortium (ICC) 666 * specification for the color space of the image contained in the 667 * input byte array. Not all formats support ICC profiles. 668 * 669 * @param bytes A valid array of bytes. 670 * @return If available, a valid array of bytes; otherwise, a null 671 * @throws ImageReadException In the event that the specified content 672 * does not conform to the format of the specific 673 * parser implementation. 674 * @throws IOException In the event of unsuccessful read or access operation. 675 */ 676 public final byte[] getICCProfileBytes(final byte[] bytes) throws ImageReadException, IOException { 677 return getICCProfileBytes(bytes, null); 678 } 679 680 /** 681 * Get an array of bytes describing the International Color Consortium (ICC) 682 * specification for the color space of the image contained in the 683 * input byte array. Not all formats support ICC profiles. 684 * 685 * @param bytes A valid array of bytes. 686 * @param params Optional instructions for special-handling or 687 * interpretation of the input data. 688 * @return If available, a valid array of bytes; otherwise, a null 689 * @throws ImageReadException In the event that the specified content 690 * does not conform to the format of the specific 691 * parser implementation. 692 * @throws IOException In the event of unsuccessful read or access operation. 693 */ 694 public final byte[] getICCProfileBytes(final byte[] bytes, final T params) 695 throws ImageReadException, IOException { 696 return getICCProfileBytes(new ByteSourceArray(bytes), params); 697 } 698 699 /** 700 * Get an array of bytes describing the International Color Consortium (ICC) 701 * specification for the color space of the image contained in the 702 * input file. Not all formats support ICC profiles. 703 * 704 * @param file A valid file reference. 705 * @return If available, a valid array of bytes; otherwise, a null 706 * @throws ImageReadException In the event that the specified content 707 * does not conform to the format of the specific 708 * parser implementation. 709 * @throws IOException In the event of unsuccessful read or access operation. 710 */ 711 public final byte[] getICCProfileBytes(final File file) throws ImageReadException, IOException { 712 return getICCProfileBytes(file, null); 713 } 714 715 /** 716 * Get an array of bytes describing the International Color Consortium (ICC) 717 * specification for the color space of the image contained in the 718 * input file. Not all formats support ICC profiles. 719 * 720 * @param file A valid file reference. 721 * @param params Optional instructions for special-handling or 722 * interpretation of the input data. 723 * @return If available, a valid array of bytes; otherwise, a null 724 * @throws ImageReadException In the event that the specified content 725 * does not conform to the format of the specific 726 * parser implementation. 727 * @throws IOException In the event of unsuccessful read or access operation. 728 */ 729 public final byte[] getICCProfileBytes(final File file, final T params) 730 throws ImageReadException, IOException { 731 if (!canAcceptExtension(file)) { 732 return null; 733 } 734 735 if (LOGGER.isLoggable(Level.FINEST)) { 736 LOGGER.finest(getName() + ": " + file.getName()); 737 } 738 739 return getICCProfileBytes(new ByteSourceFile(file), params); 740 } 741 742 /** 743 * Get an array of bytes describing the International Color Consortium (ICC) 744 * specification for the color space of the image contained in the 745 * input byteSource. Not all formats support ICC profiles. 746 * 747 * @param byteSource A valid ByteSource. 748 * @param params Optional instructions for special-handling or 749 * interpretation of the input data. 750 * @return If available, a valid array of bytes; otherwise, a null 751 * @throws ImageReadException In the event that the specified content 752 * does not conform to the format of the specific 753 * parser implementation. 754 * @throws IOException In the event of unsuccessful read or access operation. 755 */ 756 public abstract byte[] getICCProfileBytes(ByteSource byteSource, T params) 757 throws ImageReadException, IOException; 758 759 /** 760 * Write the ImageInfo and format-specific information for the image 761 * content of the specified byte array to a string. 762 * 763 * @param bytes A valid array of bytes. 764 * @return A valid string. 765 * @throws ImageReadException In the event that the specified content 766 * does not conform to the format of the specific 767 * parser implementation. 768 * @throws IOException In the event of unsuccessful read or access operation. 769 */ 770 public final String dumpImageFile(final byte[] bytes) throws ImageReadException, IOException { 771 return dumpImageFile(new ByteSourceArray(bytes)); 772 } 773 774 775 /** 776 * Write the ImageInfo and format-specific information for the image 777 * content of the specified file to a string. 778 * 779 * @param file A valid file reference. 780 * @return A valid string. 781 * @throws ImageReadException In the event that the specified content 782 * does not conform to the format of the specific 783 * parser implementation. 784 * @throws IOException In the event of unsuccessful read or access operation. 785 */ 786 public final String dumpImageFile(final File file) throws ImageReadException, IOException { 787 if (!canAcceptExtension(file)) { 788 return null; 789 } 790 791 if (LOGGER.isLoggable(Level.FINEST)) { 792 LOGGER.finest(getName() + ": " + file.getName()); 793 } 794 795 return dumpImageFile(new ByteSourceFile(file)); 796 } 797 798 /** 799 * Write the ImageInfo and format-specific information for the image 800 * content of the specified byte source to a string. 801 * 802 * @param byteSource A valid byte source. 803 * @return A valid string. 804 * @throws ImageReadException In the event that the specified content 805 * does not conform to the format of the specific 806 * parser implementation. 807 * @throws IOException In the event of unsuccessful read or access operation. 808 */ 809 public final String dumpImageFile(final ByteSource byteSource) 810 throws ImageReadException, IOException { 811 final StringWriter sw = new StringWriter(); 812 final PrintWriter pw = new PrintWriter(sw); 813 814 dumpImageFile(pw, byteSource); 815 816 pw.flush(); 817 818 return sw.toString(); 819 } 820 821 /** 822 * Write the ImageInfo and format-specific information for the image 823 * content of the specified byte source to a PrintWriter 824 * 825 * @param pw print writer used for writing the ImageInfo 826 * @param byteSource A valid byte source. 827 * @return A valid PrintWriter. 828 * @throws ImageReadException In the event that the specified content 829 * does not conform to the format of the specific 830 * parser implementation. 831 * @throws IOException In the event of unsuccessful read or access operation. 832 */ 833 public boolean dumpImageFile(final PrintWriter pw, final ByteSource byteSource) 834 throws ImageReadException, IOException { 835 return false; 836 } 837 838 839 /** 840 * Get a descriptive name for the implementation of an ImageParser. 841 * 842 * @return a valid, subject-matter-specific string. 843 */ 844 public abstract String getName(); 845 846 /** 847 * Get the default extension for the format specified by an implementation 848 * of ImageParser. Some parsers can support more than one extension 849 * (i.e. .JPEG, .JPG; .TIF, .TIFF, etc.). 850 * 851 * @return A valid string. 852 */ 853 public abstract String getDefaultExtension(); 854 855 /** 856 * Get an array of all accepted extensions 857 * 858 * @return A valid array of one or more elements. 859 */ 860 protected abstract String[] getAcceptedExtensions(); 861 862 /** 863 * Get an array of ImageFormat objects describing all accepted types 864 * 865 * @return A valid array of one or more elements. 866 */ 867 protected abstract ImageFormat[] getAcceptedTypes(); 868 869 /** 870 * Indicates whether the ImageParser implementation can accept 871 * the specified format 872 * 873 * @param type An instance of ImageFormat. 874 * @return If the parser can accept the format, true; otherwise, false. 875 */ 876 public boolean canAcceptType(final ImageFormat type) { 877 final ImageFormat[] types = getAcceptedTypes(); 878 879 for (final ImageFormat type2 : types) { 880 if (type2.equals(type)) { 881 return true; 882 } 883 } 884 return false; 885 } 886 887 /** 888 * Indicates whether the ImageParser implementation can accept 889 * the specified file based on its extension. 890 * 891 * @param file An valid file reference. 892 * @return If the parser can accept the format, true; otherwise, false. 893 */ 894 public boolean canAcceptExtension(final File file) { 895 return canAcceptExtension(file.getName()); 896 } 897 898 /** 899 * Indicates whether the ImageParser implementation can accept 900 * the specified file name based on its extension. 901 * 902 * @param fileName A valid string giving a file name or file path. 903 * @return If the parser can accept the format, true; otherwise, false. 904 */ 905 public final boolean canAcceptExtension(final String fileName) { 906 final String[] extensions = getAcceptedExtensions(); 907 if (extensions == null) { 908 return true; 909 } 910 911 final int index = fileName.lastIndexOf('.'); 912 if (index >= 0) { 913 final String fileNameExtension = fileName.substring(index + 1).toLowerCase(Locale.ENGLISH); 914 for (final String extension : extensions) { 915 if (extension.equals(fileNameExtension)) { 916 return true; 917 } 918 } 919 } 920 return false; 921 } 922 923 /** 924 * Get an instance of IBufferedImageFactory based on the presence 925 * of a specification for ImagingConstants..BUFFERED_IMAGE_FACTORY 926 * within the supplied params. 927 * 928 * @param params optional parameters. 929 * @return A valid instance of an implementation of a IBufferedImageFactory. 930 */ 931 protected BufferedImageFactory getBufferedImageFactory(final T params) { 932 if (params == null) { 933 return new SimpleBufferedImageFactory(); 934 } 935 936 final BufferedImageFactory result = params.getBufferedImageFactory(); 937 938 if (null != result) { 939 return result; 940 } 941 942 return new SimpleBufferedImageFactory(); 943 } 944 }