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