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 * <h3>Application Notes</h3> 064 * 065 * <h4>Format support</h4> 066 * 067 * For the most recent information on format support for the 068 * Apache Commons Imaging package, refer to 069 * <a href="http://commons.apache.org/imaging/formatsupport.html">Format Support</a> 070 * at the main project development web site. 071 * 072 * <h4>On the accuracy of this Javadoc</h4> 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 * <h4>The "Map params" argument</h4> 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 a string containing XML-formatted text conforming to the Extensible 673 * Metadata Platform (EXP) standard for representing information about 674 * image content. Not all image formats support EXP infomation and 675 * even for those that do, there is no guarantee that such information 676 * will be present in an image. 677 * 678 * @param byteSource A valid reference to a ByteSource. 679 * @param params Optional instructions for special-handling or 680 * interpretation of the input data. 681 * @return If XMP metadata is present, a valid string; 682 * if it is not present, a null. 683 * @throws ImageReadException In the event that the specified content 684 * does not conform to the format of the specific 685 * parser implementation. 686 * @throws IOException In the event of unsuccessful read or access operation. 687 */ 688 public abstract String getXmpXml(ByteSource byteSource, Map<String, Object> params) 689 throws ImageReadException, IOException; 690 691 /** 692 * Get an array of bytes describing the International Color Consortium (ICC) 693 * specification for the color space of the image contained in the 694 * input byte array. Not all formats support ICC profiles. 695 * 696 * @param bytes A valid array of bytes. 697 * @return If available, a valid array of bytes; otherwise, a null 698 * @throws ImageReadException In the event that the specified content 699 * does not conform to the format of the specific 700 * parser implementation. 701 * @throws IOException In the event of unsuccessful read or access operation. 702 */ 703 public final byte[] getICCProfileBytes(final byte[] bytes) throws ImageReadException, IOException { 704 return getICCProfileBytes(bytes, null); 705 } 706 707 /** 708 * Get an array of bytes describing the International Color Consortium (ICC) 709 * specification for the color space of the image contained in the 710 * input byte array. Not all formats support ICC profiles. 711 * 712 * @param bytes A valid array of bytes. 713 * @param params Optional instructions for special-handling or 714 * interpretation of the input data. 715 * @return If available, a valid array of bytes; otherwise, a null 716 * @throws ImageReadException In the event that the specified content 717 * does not conform to the format of the specific 718 * parser implementation. 719 * @throws IOException In the event of unsuccessful read or access operation. 720 */ 721 public final byte[] getICCProfileBytes(final byte[] bytes, final Map<String, Object> params) 722 throws ImageReadException, IOException { 723 return getICCProfileBytes(new ByteSourceArray(bytes), params); 724 } 725 726 /** 727 * Get an array of bytes describing the International Color Consortium (ICC) 728 * specification for the color space of the image contained in the 729 * input file. Not all formats support ICC profiles. 730 * 731 * @param file A valid file reference. 732 * @return If available, a valid array of bytes; otherwise, a null 733 * @throws ImageReadException In the event that the specified content 734 * does not conform to the format of the specific 735 * parser implementation. 736 * @throws IOException In the event of unsuccessful read or access operation. 737 */ 738 public final byte[] getICCProfileBytes(final File file) throws ImageReadException, IOException { 739 return getICCProfileBytes(file, null); 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 file. Not all formats support ICC profiles. 746 * 747 * @param file A valid file reference. 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 final byte[] getICCProfileBytes(final File file, final Map<String, Object> params) 757 throws ImageReadException, IOException { 758 if (!canAcceptExtension(file)) { 759 return null; 760 } 761 762 if (LOGGER.isLoggable(Level.FINEST)) { 763 LOGGER.finest(getName() + ": " + file.getName()); 764 } 765 766 return getICCProfileBytes(new ByteSourceFile(file), params); 767 } 768 769 /** 770 * Get an array of bytes describing the International Color Consortium (ICC) 771 * specification for the color space of the image contained in the 772 * input byteSoruce. Not all formats support ICC profiles. 773 * 774 * @param byteSource A valid ByteSource. 775 * @param params Optional instructions for special-handling or 776 * interpretation of the input data. 777 * @return If available, a valid array of bytes; otherwise, a null 778 * @throws ImageReadException In the event that the specified content 779 * does not conform to the format of the specific 780 * parser implementation. 781 * @throws IOException In the event of unsuccessful read or access operation. 782 */ 783 public abstract byte[] getICCProfileBytes(ByteSource byteSource, Map<String, Object> params) 784 throws ImageReadException, IOException; 785 786 /** 787 * Write the ImageInfo and format-specific information for the image 788 * content of the specified byte array to a string. 789 * 790 * @param bytes A valid array of bytes. 791 * @return A valid string. 792 * @throws ImageReadException In the event that the specified content 793 * does not conform to the format of the specific 794 * parser implementation. 795 * @throws IOException In the event of unsuccessful read or access operation. 796 */ 797 public final String dumpImageFile(final byte[] bytes) throws ImageReadException, IOException { 798 return dumpImageFile(new ByteSourceArray(bytes)); 799 } 800 801 802 /** 803 * Write the ImageInfo and format-specific information for the image 804 * content of the specified file to a string. 805 * 806 * @param file A valid file reference. 807 * @return A valid string. 808 * @throws ImageReadException In the event that the specified content 809 * does not conform to the format of the specific 810 * parser implementation. 811 * @throws IOException In the event of unsuccessful read or access operation. 812 */ 813 public final String dumpImageFile(final File file) throws ImageReadException, IOException { 814 if (!canAcceptExtension(file)) { 815 return null; 816 } 817 818 if (LOGGER.isLoggable(Level.FINEST)) { 819 LOGGER.finest(getName() + ": " + file.getName()); 820 } 821 822 return dumpImageFile(new ByteSourceFile(file)); 823 } 824 825 /** 826 * Write the ImageInfo and format-specific information for the image 827 * content of the specified byte source to a string. 828 * 829 * @param byteSource A valid byte source. 830 * @return A valid string. 831 * @throws ImageReadException In the event that the specified content 832 * does not conform to the format of the specific 833 * parser implementation. 834 * @throws IOException In the event of unsuccessful read or access operation. 835 */ 836 public final String dumpImageFile(final ByteSource byteSource) 837 throws ImageReadException, IOException { 838 final StringWriter sw = new StringWriter(); 839 final PrintWriter pw = new PrintWriter(sw); 840 841 dumpImageFile(pw, byteSource); 842 843 pw.flush(); 844 845 return sw.toString(); 846 } 847 848 /** 849 * Write the ImageInfo and format-specific information for the image 850 * content of the specified byte source to a PrintWriter 851 * 852 * @param byteSource A valid byte source. 853 * @return A valid PrintWriter. 854 * @throws ImageReadException In the event that the specified content 855 * does not conform to the format of the specific 856 * parser implementation. 857 * @throws IOException In the event of unsuccessful read or access operation. 858 */ 859 public boolean dumpImageFile(final PrintWriter pw, final ByteSource byteSource) 860 throws ImageReadException, IOException { 861 return false; 862 } 863 864 865 /** 866 * Get a descriptive name for the implementation of an ImageParser. 867 * 868 * @return a valid, subject-matter-specific string. 869 */ 870 public abstract String getName(); 871 872 /** 873 * Get the default extension for the format specified by an implementation 874 * of ImageParser. Some parsers can support more than one extension 875 * (i.e. .JPEG, .JPG; .TIF, .TIFF, etc.). 876 * 877 * @return A valid string. 878 */ 879 public abstract String getDefaultExtension(); 880 881 /** 882 * Get an array of all accepted extensions 883 * 884 * @return A valid array of one or more elements. 885 */ 886 protected abstract String[] getAcceptedExtensions(); 887 888 /** 889 * Get an array of ImageFormat objects describing all accepted types 890 * 891 * @return A valid array of one or more elements. 892 */ 893 protected abstract ImageFormat[] getAcceptedTypes(); 894 895 /** 896 * Indicates whether the ImageParser implementation can accept 897 * the specified format 898 * 899 * @param type An instance of ImageFormat. 900 * @return If the parser can accept the format, true; otherwise, false. 901 */ 902 public boolean canAcceptType(final ImageFormat type) { 903 final ImageFormat[] types = getAcceptedTypes(); 904 905 for (final ImageFormat type2 : types) { 906 if (type2.equals(type)) { 907 return true; 908 } 909 } 910 return false; 911 } 912 913 /** 914 * Indicates whether the ImageParser implementation can accept 915 * the specified file based on its extension. 916 * 917 * @param file An valid file reference. 918 * @return If the parser can accept the format, true; otherwise, false. 919 */ 920 protected final boolean canAcceptExtension(final File file) { 921 return canAcceptExtension(file.getName()); 922 } 923 924 /** 925 * Indicates whether the ImageParser implementation can accept 926 * the specified file name based on its extension. 927 * 928 * @param filename An valid string giving a file name or file path. 929 * @return If the parser can accept the format, true; otherwise, false. 930 */ 931 protected final boolean canAcceptExtension(final String filename) { 932 final String[] exts = getAcceptedExtensions(); 933 if (exts == null) { 934 return true; 935 } 936 937 final int index = filename.lastIndexOf('.'); 938 if (index >= 0) { 939 String ext = filename.substring(index); 940 ext = ext.toLowerCase(Locale.ENGLISH); 941 942 for (final String ext2 : exts) { 943 final String ext2Lower = ext2.toLowerCase(Locale.ENGLISH); 944 if (ext2Lower.equals(ext)) { 945 return true; 946 } 947 } 948 } 949 return false; 950 } 951 952 /** 953 * Get an instance of IBufferedImageFactory based on the presence 954 * of a specification for ImagingConstants..BUFFERED_IMAGE_FACTORY 955 * within the supplied params. 956 * 957 * @param params A valid Map object, or a null. 958 * @return A valid instance of an implementation of a IBufferedImageFactory. 959 */ 960 protected BufferedImageFactory getBufferedImageFactory(final Map<String, Object> params) { 961 if (params == null) { 962 return new SimpleBufferedImageFactory(); 963 } 964 965 final BufferedImageFactory result = (BufferedImageFactory) params.get( 966 ImagingConstants.BUFFERED_IMAGE_FACTORY); 967 968 if (null != result) { 969 return result; 970 } 971 972 return new SimpleBufferedImageFactory(); 973 } 974 975 /** 976 * A utility method to search a params specification and determine 977 * whether it contains the ImagingConstants.PARAM_KEY_STRICT 978 * specification. Intended 979 * for internal use by ImageParser implementations. 980 * 981 * @param params A valid Map object (or a null). 982 * @return If the params specify strict format compliance, true; 983 * otherwise, false. 984 */ 985 public static boolean isStrict(final Map<String, Object> params) { 986 if (params == null || !params.containsKey(ImagingConstants.PARAM_KEY_STRICT)) { 987 return false; 988 } 989 return ((Boolean) params.get(ImagingConstants.PARAM_KEY_STRICT)).booleanValue(); 990 } 991}