jai-imageio-core-1.2/0000775000175100017510000000000011650556211013467 5ustar tilletillejai-imageio-core-1.2/LICENSE-codecLibJIIO.txt0000664000175100017510000003447210203036165017473 0ustar tilletille Sun Microsystems, Inc. Binary Code License Agreement CODECLIB FOR JAI-IMAGE I/O READ THE TERMS OF THIS AGREEMENT AND ANY PROVIDED SUPPLEMENTAL LICENSE TERMS (COLLECTIVELY "AGREEMENT") CAREFULLY BEFORE OPENING THE SOFTWARE MEDIA PACKAGE. BY OPENING THE SOFTWARE MEDIA PACKAGE, YOU AGREE TO THE TERMS OF THIS AGREEMENT. IF YOU ARE ACCESSING THE SOFTWARE ELECTRONICALLY, INDICATE YOUR ACCEPTANCE OF THESE TERMS BY SELECTING THE "ACCEPT" BUTTON AT THE END OF THIS AGREEMENT. IF YOU DO NOT AGREE TO ALL THESE TERMS, PROMPTLY RETURN THE UNUSED SOFTWARE TO YOUR PLACE OF PURCHASE FOR A REFUND OR, IF THE SOFTWARE IS ACCESSED ELECTRONICALLY, SELECT THE "DECLINE" BUTTON AT THE END OF THIS AGREEMENT. 1. LICENSE TO USE. Sun grants you a non-exclusive and non-transferable license for the internal use only of the accompanying software and documentation and any error corrections provided by Sun (collectively "Software"), by the number of users and the class of computer hardware for which the corresponding fee has been paid. 2. RESTRICTIONS. Software is confidential and copyrighted. Title to Software and all associated intellectual property rights is retained by Sun and/or its licensors. Except as specifically authorized in any Supplemental License Terms, you may not make copies of Software, other than a single copy of Software for archival purposes. Unless enforcement is prohibited by applicable law, you may not modify, decompile, or reverse engineer Software. You acknowledge that Software is not designed, licensed or intended for use in the design, construction, operation or maintenance of any nuclear facility. Sun disclaims any express or implied warranty of fitness for such uses. No right, title or interest in or to any trademark, service mark, logo or trade name of Sun or its licensors is granted under this Agreement. 3. LIMITED WARRANTY. Sun warrants to you that for a period of ninety (90) days from the date of purchase, as evidenced by a copy of the receipt, the media on which Software is furnished (if any) will be free of defects in materials and workmanship under normal use. Except for the foregoing, Software is provided "AS IS". Your exclusive remedy and Sun's entire liability under this limited warranty will be at Sun's option to replace Software media or refund the fee paid for Software. 4. DISCLAIMER OF WARRANTY. UNLESS SPECIFIED IN THIS AGREEMENT, ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT ARE DISCLAIMED, EXCEPT TO THE EXTENT THAT THESE DISCLAIMERS ARE HELD TO BE LEGALLY INVALID. 5. LIMITATION OF LIABILITY. TO THE EXTENT NOT PROHIBITED BY LAW, IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR SPECIAL, INDIRECT, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF OR RELATED TO THE USE OF OR INABILITY TO USE SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. In no event will Sun's liability to you, whether in contract, tort (including negligence), or otherwise, exceed the amount paid by you for Software under this Agreement. The foregoing limitations will apply even if the above stated warranty fails of its essential purpose. 6. Termination. This Agreement is effective until terminated. You may terminate this Agreement at any time by destroying all copies of Software. This Agreement will terminate immediately without notice from Sun if you fail to comply with any provision of this Agreement. Upon Termination, you must destroy all copies of Software. 7. Export Regulations. All Software and technical data delivered under this Agreement are subject to US export control laws and may be subject to export or import regulations in other countries. You agree to comply strictly with all such laws and regulations and acknowledge that you have the responsibility to obtain such licenses to export, re-export, or import as may be required after delivery to you. 8. U.S. Government Restricted Rights. If Software is being acquired by or on behalf of the U.S. Government or by a U.S. Government prime contractor or subcontractor (at any tier), then the Government's rights in Software and accompanying documentation will be only as set forth in this Agreement; this is in accordance with 48 CFR 227.7201 through 227.7202-4 (for Department of Defense (DOD) acquisitions) and with 48 CFR 2.101 and 12.212 (for non-DOD acquisitions). 9. Governing Law. Any action related to this Agreement will be governed by California law and controlling U.S. federal law. No choice of law rules of any jurisdiction will apply. 10. Severability. If any provision of this Agreement is held to be unenforceable, this Agreement will remain in effect with the provision omitted, unless omission would frustrate the intent of the parties, in which case this Agreement will immediately terminate. 11. Integration. This Agreement is the entire agreement between you and Sun relating to its subject matter. It supersedes all prior or contemporaneous oral or written communications, proposals, representations and warranties and prevails over any conflicting or additional terms of any quote, order, acknowledgment, or other communication between the parties relating to its subject matter during the term of this Agreement. No modification of this Agreement will be binding, unless in writing and signed by an authorized representative of each party. Supplemental provisions for CODECLIB for JAI-IMAGE I/O 1. COPYRIGHT NOTICE AND ACKNOWLEDGMENT. COPYRIGHT 2002 SUN MICROSYSTEM, INC. ALL RIGHTS RESERVED. The following copyrights apply to specific Software provided under his license. JPEG2000 IMPLEMENTATION IN C This Software is based on the JPEG2000 CODEC Software, licensed under the IMAGE POWER JPEG-2000 PUBLIC LICENSE, Copyright (c) 1999-2000, Image Power, Inc. and the University of British Columbia, Canada; Copyright (c) 2001-2002 Michael David Adams. All rights reserved. JPEG2000 IMPLEMENTATION IN JAVA Copyright (c) 1999/2000 JJ2000 Partners. This software module was originally developed by Raphaël Grosbois and Diego Santa Cruz (Swiss Federal Institute of Technology-EPFL); Joel Askelöf (Ericsson Radio Systems AB); and Bertrand Berthelot, David Bouchard, Félix Henry, Gerard Mozelle and Patrice Onno (Canon Research Centre France S.A) in the course of development of the JPEG2000 standard as specified by ISO/IEC 15444 (JPEG 2000 Standard). This software module is an implementation of a part of the JPEG 2000 Standard. Swiss Federal Institute of Technology-EPFL, Ericsson Radio Systems AB and Canon Research Centre France S.A (collectively JJ2000 Partners) agree not to assert against ISO/IEC and users of the JPEG 2000 Standard (Users) any of their rights under the copyright, not including other intellectual property rights, for this software module with respect to the usage by ISO/IEC and Users of this software module or modifications thereof for use in hardware or software products claiming conformance to the JPEG 2000 Standard. Those intending to use this software module in hardware or software products are advised that their use may infringe existing patents. The original developers of this software module, JJ2000 Partners and ISO/IEC assume no liability for use of this software module or modifications thereof. No license or right to this software module is granted for non JPEG 2000 Standard conforming products. JJ2000 Partners have full right to use this software module for his/her own purpose, assign or donate this software module to any third party and to inhibit third parties from using this software module for non JPEG 2000 Standard conforming products. This copyright notice must be included in all copies or derivative works of this software module. 2. LICENSE TO USE. Permission is hereby granted, free of charge, to any person (the "User") obtaining a copy of this JCODECLIB FOR JAI-IMAGE I/O Software, the Java Advanced Imaging and the JAI Image I/O Open Source Project, and associated documentation ("Software"), to deal in the Software without restriction, including without limitation the right to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software (in source and binary forms), and to permit persons to whom the Software is furnished to do so, provided further that the License Conditions below are met and that the Software is bundled with the implementation of the Java Advanced Imaging and the JAI Image I/O Open Source Project. A. Redistribution of source code must retain the above copyright notices, and this list of conditions, and the following Warranty Disclaimer and Limitation of Liability. B. Redistribution in binary form must reproduce the above copyright notices, and this list of conditions, and the following Warranty Disclaimer and Limitation of Liability in the documentation and/or other materials provided with the distribution. C. Neither the name of Sun Microsystems, Inc., Image Power, Inc. nor any other contributor (including, but not limited to, the University of British Columbia and Michael David Adams) may be used to endorse or promote products derived from this software without specific prior written permission. D. User agrees that it shall not commence any action against Sun Microsystems, Inc., Image Power, Inc., the University of British Columbia, Michael David Adams, or any other contributors (collectively "Licensors") for infringement of any intellectual property rights ("IPR") held by the User in respect of any technology that User owns or has a right to license or sublicense and which is an element required in order to claim compliance with ISO/IEC 15444-1 (i.e., JPEG-2000 Part 1). "IPR" means all intellectual property rights worldwide arising under statutory or common law, and whether or not perfected, including, without limitation, all (i) patents and patent applications owned or licensable by User; (ii) rights associated with works of authorship including copyrights, copyright applications, copyright registrations, mask work rights, mask work applications, mask work registrations; (iii) rights relating to the protection of trade secrets and confidential information; (iv) any right analogous to those set forth in subsections (i), (ii), or (iii) and any other proprietary rights relating to intangible property (other than trademark, trade dress, or service mark rights); and (v) divisions, continuations, renewals, reissues and extensions of the foregoing (as and to the extent applicable) now existing, hereafter filed, issued or acquired. E. If User commences an infringement action against any Licensor(s) then such Licensor(s) shall have the right to terminate User's license and all sublicenses that have been granted hereunder by User to other parties. F. This software is for use only in hardware or software products that are compliant with ISO/IEC 15444-1 (i.e., JPEG-2000 Part 1). No license or right to this Software is granted for products that do not comply with ISO/IEC 15444-1. The JPEG-2000 Part 1 standard can be purchased from the ISO. 3. DISCLAIMER OF WARRANTY. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE. NO USE OF THE JPEG2000 CODEC SOFTWARE IS AUTHORIZED HEREUNDER EXCEPT UNDER THIS DISCLAIMER. THE JPEG2000 CODEC SOFTWARE IS PROVIDED BY THE LICENSORS AND CONTRIBUTORS UNDER THIS LICENSE ON AN ``AS-IS'' BASIS, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES THAT THE JPEG2000 CODEC SOFTWARE IS FREE OF DEFECTS, IS MERCHANTABLE, IS FIT FOR A PARTICULAR PURPOSE OR IS NON-INFRINGING. THOSE INTENDING TO USE THE JPEG2000 CODEC SOFTWARE OR MODIFICATIONS THEREOF FOR USE IN HARDWARE OR SOFTWARE PRODUCTS ARE ADVISED THAT THEIR USE MAY INFRINGE EXISTING PATENTS, COPYRIGHTS, TRADEMARKS, OR OTHER INTELLECTUAL PROPERTY RIGHTS. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE JPEG2000 CODEC SOFTWARE IS WITH THE USER. SHOULD ANY PART OF THE JPEG2000 CODEC SOFTWARE PROVE DEFECTIVE IN ANY RESPECT, THE USER (AND NOT THE INITIAL DEVELOPERS, SUN MICROSYSTEMS, INC., THE UNIVERSITY OF BRITISH COLUMBIA, IMAGE POWER, INC., MICHAEL DAVID ADAMS, OR ANY OTHER CONTRIBUTOR) SHALL ASSUME THE COST OF ANY NECESSARY SERVICING, REPAIR OR CORRECTION. 4. LIMITATION OF LIABILITY. UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL THEORY, WHETHER TORT (INCLUDING NEGLIGENCE), CONTRACT, OR OTHERWISE, SHALL THE INITIAL DEVELOPER, SUN MICROSYSTEMS, INC., THE UNIVERSITY OF BRITISH COLUMBIA, IMAGE POWER, INC., MICHAEL DAVID ADAMS, ANY OTHER CONTRIBUTOR, OR ANY DISTRIBUTOR OF THE JPEG2000 CODEC SOFTWARE, OR ANY SUPPLIER OF ANY OF SUCH PARTIES, BE LIABLE TO THE USER OR ANY OTHER PERSON FOR ANY INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES OF ANY CHARACTER INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF GOODWILL, WORK STOPPAGE, COMPUTER FAILURE OR MALFUNCTION, OR ANY AND ALL OTHER COMMERCIAL DAMAGES OR LOSSES, EVEN IF SUCH PARTY HAD BEEN INFORMED, OR OUGHT TO HAVE KNOWN, OF THE POSSIBILITY OF SUCH DAMAGES. THE JPEG2000 CODEC SOFTWARE AND UNDERLYING TECHNOLOGY ARE NOT FAULT-TOLERANT AND ARE NOT DESIGNED, MANUFACTURED OR INTENDED FOR USE OR RESALE AS ON-LINE CONTROL EQUIPMENT IN HAZARDOUS ENVIRONMENTS REQUIRING FAIL-SAFE PERFORMANCE, SUCH AS IN THE OPERATION OF NUCLEAR FACILITIES, AIRCRAFT NAVIGATION OR COMMUNICATION SYSTEMS, AIR TRAFFIC CONTROL, DIRECT LIFE SUPPORT MACHINES, OR WEAPONS SYSTEMS, IN WHICH THE FAILURE OF THE JPEG2000 CODEC SOFTWARE OR UNDERLYING TECHNOLOGY OR PRODUCT COULD LEAD DIRECTLY TO DEATH, PERSONAL INJURY, OR SEVERE PHYSICAL OR ENVIRONMENTAL DAMAGE ("HIGH RISK ACTIVITIES"). LICENSOR SPECIFICALLY DISCLAIMS ANY EXPRESS OR IMPLIED WARRANTY OF FITNESS FOR HIGH RISK ACTIVITIES. USER WILL NOT KNOWINGLY USE, DISTRIBUTE OR RESELL THE JPEG2000 CODEC SOFTWARE OR UNDERLYING TECHNOLOGY OR PRODUCTS FOR HIGH RISK ACTIVITIES AND WILL ENSURE THAT ITS CUSTOMERS AND END-USERS OF ITS PRODUCTS ARE PROVIDED WITH A COPY OF THE NOTICE SPECIFIED IN THIS SECTION.UNLESS SPECIFIED IN THIS AGREEMENT, ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT ARE DISCLAIMED, EXCEPT TO THE EXTENT THAT THESE DISCLAIMERS ARE HELD TO BE LEGALLY INVALID. For inquiries please contact: Sun Microsystems, Inc. 4150 Network Circle, Santa Clara, CA 95054 (Form ID#011801) jai-imageio-core-1.2/build.properties0000664000175100017510000000253710515267532016717 0ustar tilletille# # Base version and milestone. # String versions are as x.y[.z], file versions as x_y[_z]. # Specification milestones are edr, ..., mr. # Implementation milestones are alpha, ..., fcs # version_buildnum=04 version_betastr=alpha version_base=1.2 version_base_file=1_2 jai-imageio-core-1.2/src/0000775000175100017510000000000011650556176014270 5ustar tilletillejai-imageio-core-1.2/src/share/0000775000175100017510000000000011650556204015362 5ustar tilletillejai-imageio-core-1.2/src/share/services/0000775000175100017510000000000011650556177017216 5ustar tilletillejai-imageio-core-1.2/src/share/services/javax.imageio.spi.ImageInputStreamSpi0000664000175100017510000000373610203036165026336 0ustar tilletille# # $RCSfile: javax.imageio.spi.ImageInputStreamSpi,v $ # # # Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # - Redistribution of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # - Redistribution in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # # Neither the name of Sun Microsystems, Inc. or the names of # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # This software is provided "AS IS," without a warranty of any # kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND # WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY # EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL # NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF # USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS # DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR # ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, # CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND # REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR # INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE # POSSIBILITY OF SUCH DAMAGES. # # You acknowledge that this software is not designed or intended for # use in the design, construction, operation or maintenance of any # nuclear facility. # # $Revision: 1.1 $ # $Date: 2005-02-11 05:02:44 $ # $State: Exp $ # # --- JAI-Image I/O ImageInputStream plug-ins --- # com.sun.media.imageioimpl.stream.ChannelImageInputStreamSpi jai-imageio-core-1.2/src/share/services/javax.media.jai.OperationRegistrySpi0000664000175100017510000000371710203036165026225 0ustar tilletille# # $RCSfile: javax.media.jai.OperationRegistrySpi,v $ # # # Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # - Redistribution of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # - Redistribution in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # # Neither the name of Sun Microsystems, Inc. or the names of # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # This software is provided "AS IS," without a warranty of any # kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND # WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY # EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL # NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF # USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS # DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR # ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, # CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND # REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR # INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE # POSSIBILITY OF SUCH DAMAGES. # # You acknowledge that this software is not designed or intended for # use in the design, construction, operation or maintenance of any # nuclear facility. # # $Revision: 1.1 $ # $Date: 2005-02-11 05:02:44 $ # $State: Exp $ # # --- JAI-Image I/O operations registration --- # com.sun.media.jai.imageioimpl.ImageReadWriteSpi jai-imageio-core-1.2/src/share/services/javax.imageio.spi.ImageWriterSpi0000664000175100017510000000504010667373164025346 0ustar tilletille# # $RCSfile: javax.imageio.spi.ImageWriterSpi,v $ # # # Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # - Redistribution of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # - Redistribution in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # # Neither the name of Sun Microsystems, Inc. or the names of # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # This software is provided "AS IS," without a warranty of any # kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND # WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY # EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL # NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF # USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS # DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR # ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, # CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND # REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR # INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE # POSSIBILITY OF SUCH DAMAGES. # # You acknowledge that this software is not designed or intended for # use in the design, construction, operation or maintenance of any # nuclear facility. # # $Revision: 1.2 $ # $Date: 2007-09-05 00:21:08 $ # $State: Exp $ # # --- JAI-Image I/O ImageWriter plug-ins --- # com.sun.media.imageioimpl.plugins.jpeg.CLibJPEGImageWriterSpi com.sun.media.imageioimpl.plugins.png.CLibPNGImageWriterSpi com.sun.media.imageioimpl.plugins.jpeg2000.J2KImageWriterSpi com.sun.media.imageioimpl.plugins.jpeg2000.J2KImageWriterCodecLibSpi com.sun.media.imageioimpl.plugins.wbmp.WBMPImageWriterSpi com.sun.media.imageioimpl.plugins.bmp.BMPImageWriterSpi com.sun.media.imageioimpl.plugins.gif.GIFImageWriterSpi com.sun.media.imageioimpl.plugins.pcx.PCXImageWriterSpi com.sun.media.imageioimpl.plugins.pnm.PNMImageWriterSpi com.sun.media.imageioimpl.plugins.raw.RawImageWriterSpi com.sun.media.imageioimpl.plugins.tiff.TIFFImageWriterSpi jai-imageio-core-1.2/src/share/services/javax.imageio.spi.ImageOutputStreamSpi0000664000175100017510000000373310203036165026534 0ustar tilletille# # $RCSfile: javax.imageio.spi.ImageOutputStreamSpi,v $ # # # Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # - Redistribution of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # - Redistribution in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # # Neither the name of Sun Microsystems, Inc. or the names of # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # This software is provided "AS IS," without a warranty of any # kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND # WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY # EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL # NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF # USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS # DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR # ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, # CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND # REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR # INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE # POSSIBILITY OF SUCH DAMAGES. # # You acknowledge that this software is not designed or intended for # use in the design, construction, operation or maintenance of any # nuclear facility. # # $Revision: 1.1 $ # $Date: 2005-02-11 05:02:44 $ # $State: Exp $ # # --- JAI-Image I/O ImageReader plug-ins --- # com.sun.media.imageioimpl.stream.ChannelImageOutputStreamSpi jai-imageio-core-1.2/src/share/services/javax.imageio.spi.ImageReaderSpi0000664000175100017510000000475010667373164025303 0ustar tilletille# # $RCSfile: javax.imageio.spi.ImageReaderSpi,v $ # # # Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # - Redistribution of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # - Redistribution in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # # Neither the name of Sun Microsystems, Inc. or the names of # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # This software is provided "AS IS," without a warranty of any # kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND # WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY # EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL # NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF # USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS # DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR # ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, # CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND # REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR # INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE # POSSIBILITY OF SUCH DAMAGES. # # You acknowledge that this software is not designed or intended for # use in the design, construction, operation or maintenance of any # nuclear facility. # # $Revision: 1.2 $ # $Date: 2007-09-05 00:21:08 $ # $State: Exp $ # # --- JAI-Image I/O ImageReader plug-ins --- # com.sun.media.imageioimpl.plugins.jpeg.CLibJPEGImageReaderSpi com.sun.media.imageioimpl.plugins.png.CLibPNGImageReaderSpi com.sun.media.imageioimpl.plugins.jpeg2000.J2KImageReaderSpi com.sun.media.imageioimpl.plugins.jpeg2000.J2KImageReaderCodecLibSpi com.sun.media.imageioimpl.plugins.wbmp.WBMPImageReaderSpi com.sun.media.imageioimpl.plugins.bmp.BMPImageReaderSpi com.sun.media.imageioimpl.plugins.pcx.PCXImageReaderSpi com.sun.media.imageioimpl.plugins.pnm.PNMImageReaderSpi com.sun.media.imageioimpl.plugins.raw.RawImageReaderSpi com.sun.media.imageioimpl.plugins.tiff.TIFFImageReaderSpi jai-imageio-core-1.2/src/share/classes/0000775000175100017510000000000011650556205017020 5ustar tilletillejai-imageio-core-1.2/src/share/classes/overview.html0000664000175100017510000010771110667373231021566 0ustar tilletille JavaTM Advanced Imaging Image I/O Tools provides JAI read and write operations which use the Java Image I/O Framework, image input and output streams which use the New I/O APIs, and image reader and writer plug-ins.

JAI Image I/O Operations

JAI operations which read and write images using the Java Image I/O Framework are provided in the package {@link com.sun.media.jai.operator}.

Java Image I/O Streams

Image I/O stream classes based on the new java.nio I/O APIs, for use with the "raw" format image reader plug-in, and for reading discontiguous image data are provided in the package {@link com.sun.media.imageio.stream}.

Java Image I/O Reader and Writer Plug-ins

Several reader and writer plug-ins for use with the Java Image I/O Framework are provided. A summary of their optional capabilities and metadata support is given in the following table where F denotes false, T indicates true, X signifies that the capability is irrelevant, and U is a variable which is true if and only if the image data are uncompressed. Capabilities not listed may be assumed to revert to the respective defaults for reading and writing.

Reader/Writer Plug-in Capability Summary
Capability BMP GIF JPEG JPEG 2000 PCX PNG PNM Raw TIFF WBMP
{@link javax.imageio.ImageReader#canReadRaster()} T X F T F F T T F T
{@link javax.imageio.ImageReader#isRandomAccessEasy(int)} U X F F F F T T U T
{@link javax.imageio.ImageReader#readerSupportsThumbnails()} F F T F F F F F F F
{@link javax.imageio.ImageWriteParam#canWriteCompressed()} T T T T F T F F T F
{@link javax.imageio.ImageWriteParam#canWriteProgressive()} F T F T F T F F F F
{@link javax.imageio.ImageWriteParam#canWriteTiles()} F F F T F F F T T F
{@link javax.imageio.ImageWriter#canInsertEmpty(int)} F F F F F F F F T F
{@link javax.imageio.ImageWriter#canInsertImage(int)} F F F F F F F F T F
{@link javax.imageio.ImageWriter#canReplacePixels(int)} F F F F F F F F T F
{@link javax.imageio.ImageWriter#canWriteRasters()} T F F T F F T T F T
{@link javax.imageio.ImageWriter#canWriteEmpty()} F F F F F F F F T F
{@link javax.imageio.ImageWriter#canWriteSequence()} F T F F F F F F T F
Stream Metadata F T F F F F F F T F
Standard Image Metadata T T T (reader only) T F T T F T T (reader only)
Native Image Metadata T T T (reader only) T F T T F T T (reader only)

BMP

ImageReader and ImageWriter plug-ins are provided for the Bitmap (BMP) format. A summary of the attributes of these plug-ins is given in the following table with more details in the description of the package {@link com.sun.media.imageio.plugins.bmp}.

BMP Reader/Writer Plug-in Attributes
Attribute Value
Format Name bmp
MIME Type image/bmp
Suffix bmp
Native Image Metadata com_sun_media_imageio_plugins_bmp_image_1.0
{@link javax.imageio.ImageWriteParam} {@link com.sun.media.imageio.plugins.bmp.BMPImageWriteParam}
References No formal, well-defined specification exists but the BMP - Windows Bitmap Format FAQ Entry contains useful information

GIF

An ImageWriter plug-in is provided for the Graphics Interchange Format (GIF). Animated GIF images may be created using the standard sequence writing methods defined in {@link javax.imageio.ImageWriter}. By default the writer creates version "89a" images.

The writer supports setting output stream metadata from metadata supplied to the writer in either the native GIF stream metadata format javax_imageio_gif_stream_1.0 or the standard metadata format javax_imageio_1.0, and setting output image metadata from metadata supplied to the writer in either the native GIF image metadata format javax_imageio_gif_image_1.0 or the standard metadata format javax_imageio_1.0. The mapping of standard metadata format to the GIF native stream and image metadata formats is given in the tables below.

A global color table is written to the output stream if one of the following conditions obtains:

In the first case the global color table in the stream metadata is used, in the second the local color table in the image metadata is used, and in the third a global color table is created from the ColorModel or SampleModel of the (first) image.

A local color table is written to the output stream only if image metadata containing a LocalColorTable element are supplied to the writer, or no image metadata are supplied to the writer and the local color table which would be generated from the image itself is not equal to the global color table.

A Graphic Control Extension block is written to the output stream only if image metadata containing a GraphicControlExtension element are supplied to the writer, or no image metadata are supplied and the local color table generated from the image requires a transparent index. Application, Plain Text, and Comment Extension blocks are written only if they are supplied to the writer via image metadata.

Mapping of Standard to GIF Native Stream Metadata
Standard Metadata Component GIF Native Stream Metadata Component
/Chroma/Palette/PaletteEntry@index /GlobalColorTable/ColorTableEntry@index
/Chroma/Palette/PaletteEntry@red /GlobalColorTable/ColorTableEntry@red
/Chroma/Palette/PaletteEntry@green /GlobalColorTable/ColorTableEntry@green
/Chroma/Palette/PaletteEntry@blue /GlobalColorTable/ColorTableEntry@blue
/Chroma/BackgroundIndex@value /GlobalColorTable@backgroundColorIndex
/Data/BitsPerSample@value /LogicalScreenDescriptor@colorResolution
/Dimension/PixelAspectRatio@value /LogicalScreenDescriptor@pixelAspectRatio
/Dimension/HorizontalScreenSize@value /LogicalScreenDescriptor@logicalScreenWidth
/Dimension/VerticalScreenSize@value /LogicalScreenDescriptor@logicalScreenHeight
/Document/FormatVersion@value /Version@value

Mapping of Standard to GIF Native Image Metadata
Standard Metadata Component GIF Native Image Metadata Component
/Chroma/Palette/PaletteEntry@index /LocalColorTable/ColorTableEntry@index
/Chroma/Palette/PaletteEntry@red /LocalColorTable/ColorTableEntry@red
/Chroma/Palette/PaletteEntry@green /LocalColorTable/ColorTableEntry@green
/Chroma/Palette/PaletteEntry@blue /LocalColorTable/ColorTableEntry@blue
/Compression/NumProgressiveScans@value /ImageDescriptor@interlaceFlag
/Dimension/HorizontalPixelOffset@value /ImageDescriptor@imageLeftPosition
/Dimension/VerticalPixelOffset@value /ImageDescriptor@imageTopPosition
/Text/TextEntry@value /CommentExtensions/CommentExtension@value
/Transparency/TransparentIndex@value /GraphicControlExtension@transparentColorIndex (/GraphicControlExtension@transparentColorFlag is also set to "TRUE")

GIF Writer Plug-in Attributes
Attribute Value
Format Name gif
MIME Type image/gif
Suffix gif
{@link javax.imageio.ImageWriteParam} ImageWriteParam subclass
References GIF 87a Specification (W3C page)

GIF ImageWriteParam Subclass Attributes
Attribute Value
Compression Types "LZW"
Compression Modes ImageWriteParam.MODE_DEFAULT, ImageWriteParam.MODE_EXPLICIT
Progressive Modes ImageWriteParam.MODE_COPY_FROM_METADATA (use metadata setting if provided, otherwise interlaced), ImageWriteParam.MODE_DEFAULT (interlaced), ImageWriteParam.MODE_DISABLED (not interlaced)
(MODE_COPY_FROM_METADATA is initial setting)

JPEG

ImageReader and ImageWriter plug-ins are provided for the JPEG image format. These plug-ins are accelerated using native code. If security permission settings disallow loading native code, or if the system property "com.sun.media.imageio.disableCodecLib" is set to "true" at the time of plug-in registration the service provider will deregister itself and the plug-ins will not be available.

In addition to providing better performance through native acceleration for conventional (lossy) JPEG (baseline sequential DCT, 8-bit sample precision), these plug-ins also support the following additional JPEG coding processes from ISO-10918-1/ITU-T.81:

as well as the following JPEG coding process from ISO-14495-1/ITU-T.87:

All subsampling and sub-banding is performed in memory, however, so if either is required, use of the core JPEG plug-in might be preferable. This plug-in performs best when the data are pixel interleaved with pixel stride equal to the number of samples per pixel and color component order G (grayscale), GA (grayscale with alpha), RGB (red-green-blue), BGR (blue-green-red), RGBA (red-green-blue with alpha), or CMYK (cyan-magenta-yellow-black) as appropriate for the color space. Other layouts will cause data to be reformatted in memory.

If the JPEG reader detects an ICC profile in an APP2 marker segment it will use it to define the raw {@link javax.imageio.ImageTypeSpecifier}. If the inferred color space not based on the ICC profile is compatible with the ICC profile-based color space, then a second ImageTypeSpecifier derived from this inferred color space will be included in the {@link java.util.Iterator} returned by {@link javax.imageio.ImageReader#getImageTypes}. If the iterator contains more than one type, the first one will be based on the ICC profile and the second on the inferred color space.

The JPEG reader supports TIFF native image metadata as an extra metadata format. If the JPEG stream contains an EXIF APP1 marker segment, the primary IFD contained therein will be available from the metadata tree extracted using the TIFF extra metadata format name. The IIOMetadata object returned by the JPEG reader may also be used in a call to {@link com.sun.media.imageio.plugins.tiff.TIFFDirectory#createFromMetadata TIFFDirectory.createFromMetadata()} to create a TIFFDirectory instance from which TIFFFields may be easily extracted.

The JPEG reader supports thumbnails. These may be derived from JFIF APP0, JFXX APP0, or EXIF APP1 marker segments. Although APP0 marker segments are not allowed by the EXIF specification, there nevertheless exist EXIF images which contain them. If there is more than one thumbnail present, the JFIF thumbnail will be retrieved first, followed by any JFXX thumbnail(s), followed by any EXIF thumbnail. The source of each respective thumbnail may be determined by consulting the native image metadata.

The baseline DCT JPEG writer encodes images with from 1 to 4 bands. If the image is 4-banded with a ColorSpace of type {@link java.awt.color.ColorSpace#TYPE_CMYK ColorSpace.TYPE_CMYK}, an Adobe APP14 marker with transform parameter value 0 will be written and the image components will not be subsampled.

JPEG Reader/Writer Plug-in Attributes
Attribute Value
Format Names jpeg, jpg, jpeg-lossless (ISO 10918-1 lossless), jpeg-ls (ISO 14495-1 lossless), jfif
MIME Type image/jpeg
Suffixes jpeg, jpg, jls (ISO 14495-1 lossless), jfif
Native Image Metadata javax_imageio_jpeg_1.0
Extra Image Metadata com_sun_media_imageio_plugins_tiff_image_1.0
{@link javax.imageio.ImageWriteParam} ImageWriteParam subclass
References JPEG Home Page

JPEG ImageWriteParam Subclass Attributes
Attribute Value
Compression Types "JPEG" (conventional, lossy JPEG), "JPEG-LOSSLESS" (ISO-10918-1 lossless), "JPEG-LS" (ISO-14495-1 lossless)
Compression Modes ImageWriteParam.MODE_DEFAULT (lossy), ImageWriteParam.MODE_EXPLICIT
{@link javax.imageio.ImageWriteParam#isCompressionLossless()} true if and only if compressionType is not "JPEG"

JPEG 2000

JavaTM and native-based ImageReader and ImageWriter plug-ins are provided for the JPEG 2000 image format. A summary of the attributes of these plug-ins is given in the table below with more details in the description of the package {@link com.sun.media.imageio.plugins.jpeg2000}. If security permission settings disallow loading native code, or if the system property "com.sun.media.imageio.disableCodecLib" is set to "true" at the time of plug-in registration the native service providers will deregister themselves and the native plug-ins will not be available. If both the native and JavaTM plug-ins are registered, the native plug-ins will have higher precedence in the IIORegistry.

JPEG 2000 Reader/Writer Plug-in Attributes
Attribute Value
Format Names jpeg2000, jpeg 2000
MIME Type image/jp2, image/jpeg2000
Suffix jp2
Native Image Metadata com_sun_media_imageio_plugins_jpeg2000_image_1.0
{@link javax.imageio.ImageReadParam} {@link com.sun.media.imageio.plugins.jpeg2000.J2KImageReadParam}
{@link javax.imageio.ImageWriteParam} {@link com.sun.media.imageio.plugins.jpeg2000.J2KImageWriteParam}
References JPEG 2000 Links

PCX

ImageReader and ImageWriter plug-ins are provided for the PCX image format. A summary of the attributes of these plug-ins is given in the following table.

PCX Reader/Writer Plug-in Attributes
Attribute Value
Format Name pcx
MIME Types image/pcx, image/x-pcx, image/x-windows-pcx, image/x-pc-paintbrush
Suffixes pcx
References PCX Summary from the Encyclopedia of Graphics File Formats

PNG

ImageReader and ImageWriter plug-ins are provided for the Portable Network Graphics (PNG) image format. These plug-ins are accelerated using native code. If security permission settings disallow loading native code, or if the system property "com.sun.media.imageio.disableCodecLib" is set to "true" at the time of plug-in registration the service provider will deregister itself and the plug-ins will not be available.

In addition to providing better performance through native acceleration, these plug-ins also provide the ability to set the compression level and encoder strategy. All subsampling and sub-banding is performed in memory, however, so if either of these is required, use of the core PNG plug-in might be preferable. This plug-in performs best when the data are either packed bilevel (1 sample per pixel, 1 bit per sample) or pixel interleaved with pixel stride equal to the number of samples per pixel and color component order G (grayscale), GA (grayscale with alpha), RGB (red-green-blue), or RGBA (red-green-blue with alpha) as appropriate for the color space. Other layouts will cause data to be reformatted in memory. Currently only bit depths of 1, 8, and 16 are supported.

If the PNG reader detects an ICC profile in an iCCP chunk it will use it to define the raw {@link javax.imageio.ImageTypeSpecifier}. If the inferred color space not based on the ICC profile field is compatible with the ICC profile-based color space, then a second ImageTypeSpecifier derived from this inferred color space will be included in the {@link java.util.Iterator} returned by {@link javax.imageio.ImageReader#getImageTypes}. If the iterator contains more than one type, the first one will be based on the ICC profile and the second on the inferred color space.

The PNG writer will write an iCCP chunk to the output if one is in the native image metadata object provided to the writer, or if the ColorSpace of the ColorModel of the destination ImageTypeSpecifier is based on an ICC profile which is not one of the standard ColorSpaces corresponding to the ColorSpace.cs_* constants. The destination type is set via {@link javax.imageio.ImageWriteParam#setDestinationType(ImageTypeSpecifier) ImageWriteParam.setDestinationType()} and defaults to the ImageTypeSpecifier of the image being written.

PNG Reader/Writer Plug-in Attributes
Attribute Value
Format Name png
MIME Type image/png
Suffix png
Native Image Metadata javax_imageio_png_1.0
{@link javax.imageio.ImageWriteParam} ImageWriteParam subclass
References W3C PNG Page

PNG ImageWriteParam Subclass Attributes
Attribute Value
Compression Types "DEFAULT", "FILTERED", "HUFFMAN_ONLY"
Compression Modes ImageWriteParam.MODE_DEFAULT, ImageWriteParam.MODE_EXPLICIT, ImageWriteParam.MODE_COPY_FROM_METADATA (initial setting).
Compression Quality Sets compression level as compressionLevel = (int)(9*(1.0F - compressionQuality))
Progressive Modes ImageWriteParam.MODE_DEFAULT ("Adam7" interlacing), ImageWriteParam.MODE_DISABLED (no interlacing), ImageWriteParam.MODE_COPY_FROM_METADATA (initial setting).

Mapping Between Standard and Native PNG Image Metadata
Standard Metadata Component PNG Native Image Metadata Component
/Chroma/ColorSpaceType@name /IHDR@colorType
/Chroma/NumChannels@value /IHDR@colorType, /tRNS
/Chroma/Gamma@value /gAMA@gamma
/Chroma/BlackIsZero@value Always "TRUE"
/Chroma/Palette /PLTE
/Chroma/Palette/PaletteEntry@red /PLTE/PLTEEntry@red
/Chroma/Palette/PaletteEntry@green /PLTE/PLTEEntry@green
/Chroma/Palette/PaletteEntry@blue /PLTE/PLTEEntry@blue
/Chroma/Palette/PaletteEntry@alpha /PLTE/PLTEEntry@alpha
/Chroma/BackgroundIndex@value /bKGD/bKGD_Palette@index
/Chroma/BackgroundColor@red /bKGD/bKGD_RGB@red or /bKGD/bKGD_Grayscale@gray
/Chroma/BackgroundColor@green /bKGD/bKGD_RGB@green or /bKGD/bKGD_Grayscale@gray
/Chroma/BackgroundColor@blue /bKGD/bKGD_RGB@blue or /bKGD/bKGD_Grayscale@gray
/Compression/CompressionTypeName@value Always "deflate"
/Compression/Lossless@value Always "TRUE"
/Compression/NumProgressiveScans@value /IHDR/interlaceMethod@value
/Data/PlanarConfiguration@value Always "PixelInterleaved"
/Data/SampleFormat@value /IHDR@colorType
/Data/BitsPerSample@value /IHDR@bitDepth, /IHDR@colorType, /tRNS
/Data/SignificantBitsPerSample@value /sBIT
/Dimension/PixelAspectRatio@value /pHYs@pixelsPerUnitYAxis//pHYs@pixelsPerUnitXAxis or 1.0
/Dimension/ImageOrientation@value Always "Normal"
/Dimension/HorizontalPixelSize@value /pHYs@pixelsPerUnitXAxis, /pHYS@unitSpecifier
/Dimension/VerticalPixelSize@value /pHYs@pixelsPerUnitYAxis, /pHYS@unitSpecifier
/Document/ImageModificationTime@value /tIME
/Text/TextEntry /tEXt, /iTXt, /zTXt
/Transparency/Alpha@value /IHDR@colorType, /tRNS@alpha
/Transparency/TransparentColor@value /tRNS

PNM

ImageReader and ImageWriter plug-ins are provided for the "portable anymap" (PNM) image format which refers collectively to the formats PBM (portable bitmap), PGM (portable graymap), and PPM (portable pixmap). A summary of the attributes of these plug-ins is given in the following table with more details in the description of the package {@link com.sun.media.imageio.plugins.pnm}.

PNM Reader/Writer Plug-in Attributes
Attribute Value
Format Name pnm
MIME Types image/x-portable-anymap, image/x-portable-bitmap image/x-portable-graymap,image/x-portable-pixmap
Suffixes pbm, pgm, ppm
Native Image Metadata com_sun_media_imageio_plugins_pnm_image_1.0
{@link javax.imageio.ImageWriteParam} {@link com.sun.media.imageio.plugins.pnm.PNMImageWriteParam}
References The Netpbm Formats,
Manpage of pbm,
Manpage of pgm,
Manpage of ppm

Raw

ImageReader and ImageWriter plug-ins are provided for the "raw" image format. The ImageReader plug-in for the "raw" format requires an input which is a {@link com.sun.media.imageio.stream.RawImageInputStream}.

The reader plug-in reads any uncompressed data defined by ComponentSampleModel, SinglePixelPackedSampleModel or MultiPixelPackedSampleModel as viewed via the ImageInputStream. For example, if extra data are prepended or appended to image lines, {@link com.sun.media.imageio.stream.SegmentedImageInputStream} may be used to define the location of the image data for each line. Thus, if the data viewed from RawImageInputStream are defined by the SampleModels above after RawImageInputStream is chained with SegmentedImageInputStream, the reader plug-in can decode these data correctly.

The writer plug-in writes the data to the stream exactly as defined by the SampleModel. If the SampleModel has a scanline stride associated with it, this will be used to determine the length of each line written. If only the actual image data and not any prefix or suffix data on the line are to be written and the scanline stride is greater than the SampleModel width multiplied by the number of bands, the image should first be reformatted to remove the extra data. If JAI is available the "Format" operation may be used for reformatting the data.

Raw Reader/Writer Plug-in Attributes
Attribute Value
Format Name raw
MIME Type none
Suffix none
{@link javax.imageio.ImageWriteParam} ImageWriteParam subclass
References XML {@link org.xml.sax.InputSource} defined at {@link com.sun.media.imageio.stream.RawImageInputStream#RawImageInputStream(javax.imageio.stream.ImageInputStream,org.xml.sax.InputSource)}

Raw ImageWriteParam Subclass Attributes
Attribute Value
Tiling Modes ImageWriteParam.MODE_DEFAULT

TIFF

ImageReader and ImageWriter plug-ins are provided for the Tag(ged) Image File Format (TIFF). A summary of the attributes of these plug-ins is given in the table below with more details in the description of the package {@link com.sun.media.imageio.plugins.tiff}. Native code is used to accelerate bilevel encodings. If security permission settings disallow loading native code, or if the system property "com.sun.media.imageio.disableCodecLib" is set to "true" at the time of (de)compression, native acceleration will not be used.

TIFF Reader/Writer Plug-in Attributes
Attribute Value
Format Names tif, tiff
MIME Type image/tiff
Suffixes tif, tiff
Native Stream Metadata com_sun_media_imageio_plugins_tiff_stream_1.0
Native Image Metadata com_sun_media_imageio_plugins_tiff_image_1.0
{@link javax.imageio.ImageReadParam} {@link com.sun.media.imageio.plugins.tiff.TIFFImageReadParam}
{@link javax.imageio.ImageWriteParam} {@link com.sun.media.imageio.plugins.tiff.TIFFImageWriteParam}
References TIFF 6.0 Specification (PDF),
TIFF Specification Supplement 1 (PDF),
TIFF Specification Supplement 2 (PDF) (covers ZLIB and JPEG compression in TIFF),
The Unofficial TIFF Home Page,
TIFF Software (libtiff),
TIFF-F Revised Specification,
JPEG-in-TIFF compression,
DEFLATE specification (Zip-in-TIFF),
ZLIB specification (Zip-in-TIFF),
ICC Specification (PDF): section B.4: Embedding ICC profiles in TIFF files,
EXIF and related resources

WBMP

ImageReader and ImageWriter plug-ins are provided for the Wireless Bitmap (WBMP) image format. A summary of the attributes of these plug-ins is given in the following table.

WBMP Reader/Writer Plug-in Attributes
Attribute Value
Format Name wbmp
MIME Type image/vnd.wap.wbmp
Suffix wbmp
Native Image Metadata com_sun_media_imageio_plugins_wbmp_image_1.0
References WAP Media Types Specification (PDF) available from WAP Forum Specifications and Open Mobile Alliance

Image Metadata

The XML schema for the WBMP native image metadata format is as follows:
<?xml version="1.0" encoding="UTF-8"?>

<!-- Schema for WBMP native image metadata format. -->

<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
            xmlns="http://com.sun.media.imageio.plugins"
            targetNamespace="http://com.sun.media.imageio.plugins">

  <!-- WBMP Schema 1.0 root element. -->
  <xsd:element name="com_sun_media_imageio_plugins_wbmp_image_1.0">
    <xsd:complexType>
      <xsd:sequence>

        <!-- WBMP type -->
        <xsd:element name="WBMPType" type="xsd:unsignedInt"/>

        <!-- Bitmap width -->
        <xsd:element name="Width" type="xsd:unsignedInt"/>

        <!-- Bitmap height -->
        <xsd:element name="Height" type="xsd:unsignedInt"/>

      </xsd:sequence>
    </xsd:complexType>
  </xsd:element> <!-- wbmp_image_1.0 -->

</xsd:schema>

@since 1.0 jai-imageio-core-1.2/src/share/classes/com/0000775000175100017510000000000011650556205017576 5ustar tilletillejai-imageio-core-1.2/src/share/classes/com/sun/0000775000175100017510000000000011650556205020403 5ustar tilletillejai-imageio-core-1.2/src/share/classes/com/sun/media/0000775000175100017510000000000011650556206021463 5ustar tilletillejai-imageio-core-1.2/src/share/classes/com/sun/media/jai/0000775000175100017510000000000011650556205022225 5ustar tilletillejai-imageio-core-1.2/src/share/classes/com/sun/media/jai/imageioimpl/0000775000175100017510000000000011650556205024521 5ustar tilletillejai-imageio-core-1.2/src/share/classes/com/sun/media/jai/imageioimpl/ImageReadCRIF.java0000664000175100017510000004243310343443200027640 0ustar tilletille/* * $RCSfile: ImageReadCRIF.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.2 $ * $Date: 2005-12-01 00:39:04 $ * $State: Exp $ */ package com.sun.media.jai.imageioimpl; import java.awt.Dimension; import java.awt.RenderingHints; import java.awt.geom.Rectangle2D; import java.awt.image.RenderedImage; import java.awt.image.renderable.ParameterBlock; import java.awt.image.renderable.RenderableImage; import java.awt.image.renderable.RenderContext; import java.io.FileInputStream; import java.io.InputStream; import java.io.IOException; import java.io.RandomAccessFile; import java.net.Socket; import java.net.URL; import java.nio.channels.Channel; import java.nio.channels.Channels; import java.util.Collection; import java.util.Comparator; import java.util.EventListener; import java.util.Iterator; import java.util.Locale; import java.util.TreeMap; import java.util.Vector; import javax.imageio.ImageIO; import javax.imageio.ImageReader; import javax.imageio.ImageReadParam; import javax.imageio.event.IIOReadProgressListener; import javax.imageio.event.IIOReadUpdateListener; import javax.imageio.event.IIOReadWarningListener; import javax.imageio.spi.ImageReaderSpi; import javax.imageio.stream.ImageInputStream; import javax.media.jai.CRIFImpl; import javax.media.jai.ImageLayout; import javax.media.jai.JAI; import javax.media.jai.MultiResolutionRenderableImage; import javax.media.jai.PropertySource; import javax.media.jai.WritablePropertySource; import com.sun.media.jai.operator.ImageReadDescriptor; public final class ImageReadCRIF extends CRIFImpl { public ImageReadCRIF() { super(); // Pass up the name? } /** * Attempt to create an {@link ImageInputStream} for the supplied * input. The following sequence is effected: *
    *
  1. *
  2. ImageIO.createImageInputStream() is invoked * with parameter set to the (possibly converted) input and the * value it returns (which could be null) is returned * to the caller.
  3. *
* * @param input An Object to be used as the source, * such as a String, URL, File, * readable RandomAccessFile, InputStream, * readable Socket, or readable Channel. * * @return An ImageInputStream or null. */ private static ImageInputStream getImageInputStream(Object input) { // The value to be returned. ImageInputStream stream = null; // If already an ImageInputStream cast and return. if(input instanceof ImageInputStream) { stream = (ImageInputStream)input; } else { // If the input is a String replace it with a RandomAccessFile. if(input instanceof String) { try { // 'input' is conditionally checked for readability // in the OperationDescriptor. input = new RandomAccessFile((String)input, "r"); } catch(Exception e) { // Try to get the file as an InputStream resource. This // would happen when the application and image file are // packaged in a JAR file input = ImageReadCRIF.class.getClassLoader().getResourceAsStream((String)input); if (input == null) throw new RuntimeException (I18N.getString("ImageReadCRIF0")+" "+input); } } else if(input instanceof URL) { // If the input is a URL replace it with an InputStream. try { input = ((URL)input).openStream(); } catch(Exception e) { throw new RuntimeException (I18N.getString("ImageReadCRIF1")+" "+input); } } else if(input instanceof Socket) { // If output is a Socket replace it with an InputStream. try { Socket socket = (Socket)input; // XXX check binding, connection, closed, shutdown // as these could have changed. input = socket.getInputStream(); } catch(Exception e) { throw new RuntimeException (I18N.getString("ImageReadCRIF2")+" "+input); } } } // Create the ImageInputStream. try { stream = ImageIO.createImageInputStream(input); } catch(Exception e) { throw new RuntimeException(e); } return stream; } /** * Get the ImageReader and set its input and metadata flag. * The input set on the reader might not be the same object as the input * passed in if the latter was replaced by getImageInputStream(). */ static ImageReader getImageReader(ParameterBlock pb) { // Get the input. Object input = pb.getObjectParameter(0); // Get the reader parameter. ImageReader reader = (ImageReader)pb.getObjectParameter(8); // Attempt to create an ImageInputStream from the input. ImageInputStream stream = getImageInputStream(input); // If no reader passed in, try to find one. if(reader == null) { // Get all compatible readers. Iterator readers = ImageIO.getImageReaders(stream != null ? stream : input); // If any readers, take the first one whose originating // service provider indicates that it can decode the input. if(readers != null && readers.hasNext()) { do { ImageReader tmpReader = (ImageReader)readers.next(); ImageReaderSpi readerSpi = tmpReader.getOriginatingProvider(); try { if(readerSpi.canDecodeInput(stream != null ? stream : input)) { reader = tmpReader; } } catch(IOException ioe) { // XXX Ignore it? } } while(reader == null && readers.hasNext()); } } // If reader found, set its input and metadata flag. if(reader != null) { // Get the locale parameter and set on the reader. Locale locale = (Locale)pb.getObjectParameter(6); if(locale != null) { reader.setLocale(locale); } // Get the listeners parameter and set on the reader. EventListener[] listeners = (EventListener[])pb.getObjectParameter(5); if(listeners != null) { for(int i = 0; i < listeners.length; i++) { EventListener listener = listeners[i]; if(listener instanceof IIOReadProgressListener) { reader.addIIOReadProgressListener( (IIOReadProgressListener)listener); } if(listener instanceof IIOReadUpdateListener) { reader.addIIOReadUpdateListener( (IIOReadUpdateListener)listener); } if(listener instanceof IIOReadWarningListener) { reader.addIIOReadWarningListener( (IIOReadWarningListener)listener); } } } // Get the metadata reading flag. boolean readMetadata = ((Boolean)pb.getObjectParameter(2)).booleanValue(); // Set the input and indicate metadata reading state. reader.setInput(stream != null ? stream : input, false, // seekForwardOnly !readMetadata); // ignoreMetadata } return reader; } static void copyProperty(PropertySource ps, WritablePropertySource wps, String propertyName) { Object propertyValue = ps.getProperty(propertyName); if(propertyValue != null && !propertyValue.equals(java.awt.Image.UndefinedProperty)) { wps.setProperty(propertyName, propertyValue); } } public RenderedImage create(ParameterBlock pb, RenderingHints rh) { // Value to be returned. RenderedImage image = null; // Get the reader. ImageReader reader = getImageReader(pb); // Proceed if a compatible reader was found. if(reader != null) { // Get the remaining parameters required. int imageIndex = pb.getIntParameter(1); ImageReadParam param = (ImageReadParam)pb.getObjectParameter(7); boolean readThumbnails = ((Boolean)pb.getObjectParameter(3)).booleanValue(); // Initialize the layout. ImageLayout layout = (rh != null && rh.containsKey(JAI.KEY_IMAGE_LAYOUT)) ? (ImageLayout)rh.get(JAI.KEY_IMAGE_LAYOUT) : new ImageLayout(); try { // Get the parameter input. Object paramInput = pb.getObjectParameter(0); // Get the reader input. Object readerInput = reader.getInput(); // Set the stream to close when the OpImage is disposed. ImageInputStream streamToClose = null; if(readerInput != paramInput && readerInput instanceof ImageInputStream) { streamToClose = (ImageInputStream)readerInput; } // Create the rendering. image = new ImageReadOpImage(layout, rh, param, reader, imageIndex, readThumbnails, streamToClose); } catch(Exception e) { throw new RuntimeException(e); } } return image; } // XXX This implementation of renderable mode is incredibly lame // but the architecture and implementation allow for nothing else. // It would be better if the CRIFs had some kind of state that // could be associated with them. As it standards getBounds2D() // will create a new MultiResolutionRenderableImage and so will // the second create() below. Actually what is needed is a // RenderableImageFactory definition. // XXX There is also a problem with multiple invocations of the // rendered mode case. Without saving and seeking back to the // same offset it appears to have problems. Should ImageReadOpImage // save the initial position and always seek back to it? public RenderableImage createRenderable(ParameterBlock pb, RenderingHints rh) { // Read the collection. Collection sequence = ImageReadCIF.createStatic(pb, rh); // Create a SortedMap which sorts on the basis of inverse area. // The keys will be Dimensions and the objects RenderedImages. TreeMap sourceMap = new TreeMap(new Comparator() { public int compare(Object o1, Object o2) { Dimension d1 = (Dimension)o1; Dimension d2 = (Dimension)o2; int area1 = d1.width*d1.height; int area2 = d2.width*d2.height; double inverse1 = area1 == 0 ? Double.MAX_VALUE : 1.0/area1; double inverse2 = area2 == 0 ? Double.MAX_VALUE : 1.0/area2; if(inverse1 < inverse2) { return -1; } else if(inverse1 > inverse2) { return 1; } else { return 0; } } public boolean equals(Object o1, Object o2) { return o1.equals(o2); } }); Iterator images = sequence.iterator(); while(images.hasNext()) { RenderedImage image = (RenderedImage)images.next(); sourceMap.put(new Dimension(image.getWidth(), image.getHeight()), image); } // Create the rendered source list sorted by inverse area. Vector renderedSources = new Vector(sourceMap.size()); Iterator keys = sourceMap.keySet().iterator(); while(keys.hasNext()) { renderedSources.add(sourceMap.get(keys.next())); } // Create the RenderableImage from the sorted RenderedImages. MultiResolutionRenderableImage renderableImage = new MultiResolutionRenderableImage(renderedSources, 0.0F, 0.0F, 1.0F); // Set properties from those of the first rendered source. PropertySource firstSource = (PropertySource)renderedSources.get(0); copyProperty(firstSource, renderableImage, ImageReadDescriptor.PROPERTY_NAME_IMAGE_READ_PARAM); copyProperty(firstSource, renderableImage, ImageReadDescriptor.PROPERTY_NAME_IMAGE_READER); copyProperty(firstSource, renderableImage, ImageReadDescriptor.PROPERTY_NAME_METADATA_STREAM); copyProperty(firstSource, renderableImage, ImageReadDescriptor.PROPERTY_NAME_METADATA_IMAGE); // Return the RenderableImage. return renderableImage; } public RenderedImage create(RenderContext rc, ParameterBlock pb) { RenderableImage renderableImage = createRenderable(pb, rc.getRenderingHints()); RenderedImage renderedImage = renderableImage.createRendering(rc); ((WritablePropertySource)renderedImage).setProperty( ImageReadDescriptor.PROPERTY_NAME_RENDERABLE_INPUT, (PropertySource)renderableImage); return renderedImage; } public Rectangle2D getBounds2D(ParameterBlock pb) { // XXX Should just get the aspect ratio of the first image and use it. // Otherwise this will be very inefficient. RenderableImage renderable = createRenderable(pb, null); return new Rectangle2D.Float(renderable.getMinX(), renderable.getMinY(), renderable.getWidth(), renderable.getHeight()); } } jai-imageio-core-1.2/src/share/classes/com/sun/media/jai/imageioimpl/ImageWriteCIF.java0000664000175100017510000002556410203036165027746 0ustar tilletille/* * $RCSfile: ImageWriteCIF.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.1 $ * $Date: 2005-02-11 05:01:55 $ * $State: Exp $ */ package com.sun.media.jai.imageioimpl; import java.awt.RenderingHints; import java.awt.image.BufferedImage; import java.awt.image.RenderedImage; import java.awt.image.renderable.ParameterBlock; import java.io.IOException; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import javax.imageio.ImageIO; import javax.imageio.ImageWriteParam; import javax.imageio.ImageWriter; import javax.imageio.metadata.IIOMetadata; import javax.imageio.stream.ImageOutputStream; import javax.media.jai.CollectionImage; import javax.media.jai.CollectionImageFactory; import javax.media.jai.CollectionOp; import javax.media.jai.PropertySource; import com.sun.media.jai.operator.ImageWriteDescriptor; public final class ImageWriteCIF implements CollectionImageFactory { /** Constructor. */ public ImageWriteCIF() {} public CollectionImage create(ParameterBlock args, RenderingHints hints) { // Get the writer. ImageWriter writer = (ImageWriter)args.getObjectParameter(13); // Find a writer if null. if(writer == null) { // Get the format. Should be non-null from OperationDescriptor. String format = (String)args.getObjectParameter(1); // Find a writer. Iterator writers = ImageIO.getImageWritersByFormatName(format); // Get the writer. if(writers != null) { writer = (ImageWriter)writers.next(); } else { throw new RuntimeException (I18N.getString("ImageWriteCIF0")+" "+format); } } // Get the source Collection. Collection collection = (Collection)args.getSource(0); // Determine the number of RenderedImages in the Collection. int numRenderedImages = 0; Iterator iter = collection.iterator(); while(iter.hasNext()) { if(iter.next() instanceof RenderedImage) { numRenderedImages++; } } // Set the sequence flag. boolean writeToSequence = writer.canWriteSequence(); // Check that the writer can write sequences. if(numRenderedImages > 1 && !writeToSequence) { throw new RuntimeException (I18N.getString("ImageWriteCIF1")); } // Get the stream metadata. IIOMetadata streamMetadata = (IIOMetadata)args.getObjectParameter(7); // Get the property use flag. boolean useProperties = ((Boolean)args.getObjectParameter(2)).booleanValue(); // If null, get stream metadata from source properties if allowed. if(streamMetadata == null && useProperties && collection instanceof PropertySource) { Object streamMetadataProperty = ((PropertySource)collection).getProperty( ImageWriteDescriptor.PROPERTY_NAME_METADATA_STREAM); if(streamMetadataProperty instanceof IIOMetadata) { streamMetadata = (IIOMetadata)streamMetadataProperty; } } // Get the writer parameters. ImageWriteParam param = (ImageWriteParam)args.getObjectParameter(12); // Transcode the stream metadata if requested. if(streamMetadata != null) { // Get the transcoding flag. boolean transcode = ((Boolean)args.getObjectParameter(3)).booleanValue(); if(transcode) { // Overwrite the stream metadata with transcoded metadata. streamMetadata = writer.convertStreamMetadata(streamMetadata, param); } } if(writeToSequence) { // Write the stream metadata to the sequence. try { // Get the output. Object output = args.getObjectParameter(0); // Try to get an ImageOutputStream. ImageOutputStream stream = ImageWriteCRIF.getImageOutputStream(output); // Set the writer's output. writer.setOutput(stream != null ? stream : output); // Prepare the sequence. writer.prepareWriteSequence(streamMetadata); } catch(IOException e) { throw new RuntimeException(e); } } // Clone the ParameterBlock as the writer, image metadata, and // thumbnail parameters will be replaced. ParameterBlock imagePB = (ParameterBlock)args.clone(); // Clear the stream metadata. imagePB.set(null, 7); // Set the ImageWriter. imagePB.set(writer, 13); // Get the image metadata array. IIOMetadata[] imageMetadata = (IIOMetadata[])args.getObjectParameter(8); // Get the thumbnail array. BufferedImage[] thumbnails = (BufferedImage[])args.getObjectParameter(9); // Create a new Iterator. iter = collection.iterator(); // Create an ImageIOCollectionImage to contain the result: ImageIOCollectionImage imageList = new ImageIOCollectionImage(collection.size()); // Iterate over the collection. int imageIndex = 0; while(iter.hasNext()) { // Get the next element. Object nextElement = iter.next(); // Process if a RenderedImage. if(nextElement instanceof RenderedImage) { // Replace source with current RenderedImage. imagePB.setSource((RenderedImage)nextElement, 0); // Replace image metadata. if(imageMetadata != null) { imagePB.set(imageMetadata[imageIndex], 8); } // Replace thumbnail array. if(thumbnails != null) { imagePB.set(thumbnails[imageIndex], 9); } // Write the image to the sequence RenderedImage nextImage = ImageWriteCRIF.create(imageIndex, writeToSequence, imagePB, hints); // If the ImageWriteParam passed in was null, replace it // with the first non-null ImageWriteParam property value // and set the value in the local ParameterBlock. if(param == null) { Object paramPropertyValue = nextImage.getProperty( ImageWriteDescriptor.PROPERTY_NAME_IMAGE_WRITE_PARAM); if(paramPropertyValue instanceof ImageWriteParam) { param = (ImageWriteParam)paramPropertyValue; // Replace the ImageWriteParam so the CRIF doesn't // have to re-do the tile size initialization. imagePB.set(param, 12); } } // Add the image to the collection to be returned. imageList.add(nextImage); // Increment the index. imageIndex++; } } // Get the pixel replacement parameter. boolean allowPixelReplacement = ((Boolean)args.getObjectParameter(5)).booleanValue(); if(writeToSequence && !allowPixelReplacement) { // Complete writing the sequence. try { // XXX What about pixel replacement? If this is invoked here // it will not be possible. How can this be invoked such that // pixel replacement can occur but the user is not obliged to // call this method manually? // Answer: document that the user must obtain the writer from // the collection-level ImageWriter property and invoke // endWriteSequence() on it. writer.endWriteSequence(); } catch(IOException e) { throw new RuntimeException(e); } } // Set collection-level properties. if(param != null) { imageList.setProperty( ImageWriteDescriptor.PROPERTY_NAME_IMAGE_WRITE_PARAM, param); } imageList.setProperty( ImageWriteDescriptor.PROPERTY_NAME_IMAGE_WRITER, writer); if(streamMetadata != null) { imageList.setProperty( ImageWriteDescriptor.PROPERTY_NAME_METADATA_STREAM, streamMetadata); } // Return CollectionImage. return imageList; } // Forget it. public CollectionImage update(ParameterBlock oldParamBlock, RenderingHints oldHints, ParameterBlock newParamBlock, RenderingHints newHints, CollectionImage oldRendering, CollectionOp op) { return null; } } jai-imageio-core-1.2/src/share/classes/com/sun/media/jai/imageioimpl/ImageReadOpImage.java0000664000175100017510000010675610456010035030450 0ustar tilletille/* * $RCSfile: ImageReadOpImage.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.2 $ * $Date: 2006-07-14 21:43:57 $ * $State: Exp $ */ package com.sun.media.jai.imageioimpl; import java.awt.Dimension; import java.awt.Point; import java.awt.Rectangle; import java.awt.image.BufferedImage; import java.awt.image.ColorModel; import java.awt.image.Raster; import java.awt.image.SampleModel; import java.awt.image.WritableRaster; import java.io.InputStream; import java.io.IOException; import java.util.Iterator; import java.util.Map; import javax.imageio.ImageReader; import javax.imageio.ImageReadParam; import javax.imageio.ImageTypeSpecifier; import javax.imageio.metadata.IIOMetadata; import javax.imageio.spi.ImageReaderSpi; import javax.imageio.stream.ImageInputStream; import javax.media.jai.ImageLayout; import javax.media.jai.OpImage; import com.sun.media.jai.operator.ImageReadDescriptor; /** * Implementation of the OpImage of the "ImageRead" operation. */ final class ImageReadOpImage extends OpImage { /** * XXX For testing only. */ /* XXX public static void main(String[] args) throws Throwable { java.io.File file = new java.io.File(args[0]); int imageIndex = args.length > 1 ? Integer.valueOf(args[1]).intValue() : 0; int tileSize = args.length > 2 ? Integer.valueOf(args[2]).intValue() : 128; javax.imageio.stream.ImageInputStream stream = new javax.imageio.stream.FileImageInputStream(file); Iterator iter = javax.imageio.ImageIO.getImageReaders(stream); ImageReader imageReader = (ImageReader)iter.next(); imageReader.setInput(stream, true, // seekForwardOnly false); // ignoreMetadata ImageLayout layout = new ImageLayout(); layout.setTileWidth(tileSize).setTileHeight(tileSize); //layout.setTileGridXOffset(42).setTileGridYOffset(7); ImageReadParam param = imageReader.getDefaultReadParam(); param.setSourceSubsampling(2, 2, 0, 0); param.setSourceRegion(new Rectangle(128, 0, 256, 256)); param.setSourceBands(new int[] {2, 1, 0}); param.setDestinationBands(new int[] {0, 1, 2}); OpImage image = new ImageReadOpImage(layout, // ImageLayout null, // Map param, // ImageReadParam imageReader, imageIndex, true, null); // streamToClose System.out.println(new ImageLayout(image)); System.out.println("\nImage Properties:"); String[] propNames = image.getPropertyNames(); if(propNames != null) { for(int i = 0; i < propNames.length; i++) { System.out.println(i+" "+propNames[i]+" = "+ image.getProperty(propNames[i])); } } System.out.println(""); BufferedImage[] thumbnails = null; Object thumbnailProp = image.getProperty(ImageReadDescriptor.PROPERTY_NAME_THUMBNAILS); if(thumbnailProp != java.awt.Image.UndefinedProperty) { thumbnails = (BufferedImage[])thumbnailProp; } java.awt.Frame frame = new java.awt.Frame("ImageReadOpImage Test: "+file); if(thumbnails != null) { frame.setLayout(new java.awt.GridLayout(1, thumbnails.length+1)); } frame.add(new javax.media.jai.widget.ScrollingImagePanel(image, image.getWidth(), image.getHeight())); if(thumbnails != null) { for(int i= 0; i < thumbnails.length; i++) { frame.add(new javax.media.jai.widget.ScrollingImagePanel(thumbnails[i], thumbnails[i].getWidth(), thumbnails[i].getHeight())); } } frame.pack(); frame.show(); } */ /** * The ImageReadParam used in reading the image. */ private ImageReadParam param; /** * The ImageReader used to read the image. */ private ImageReader reader; /** * The index of the image to be read. */ private int imageIndex; /** * Whether thumbnails are to be read. */ private boolean readThumbnails; /** * Whether stream metadata have been be read. */ private boolean streamMetadataRead = false; /** * Whether image metadata have been be read. */ private boolean imageMetadataRead = false; /** * A stream to be closed when the instance is disposed; may be null. */ private ImageInputStream streamToClose; /** * Destination to source X scale factor. */ private int scaleX; /** * Destination to source Y scale factor. */ private int scaleY; /** * Destination to source X translation factor. */ private int transX; /** * Destination to source Y translation factor. */ private int transY; /** * Derive the image layout based on the user-supplied layout, * reading parameters, and image index. */ private static ImageLayout layoutHelper(ImageLayout il, ImageReadParam param, ImageReader reader, int imageIndex) throws IOException { ImageLayout layout = (il == null) ? new ImageLayout() : (ImageLayout)il.clone(); // --- Determine the image type. --- // If not provided in the original layout, set the SampleModel // and ColorModel from the ImageReadParam, if supplied. if(!layout.isValid(ImageLayout.SAMPLE_MODEL_MASK) && !layout.isValid(ImageLayout.COLOR_MODEL_MASK)) { // If an ImageReadParam has been supplied and has its // destinationType set then use it. Otherwise default to // the raw image type. ImageTypeSpecifier imageType = (param != null && param.getDestinationType() != null) ? param.getDestinationType() : reader.getRawImageType(imageIndex); // XXX The following block of code should not be necessary // but for J2SE 1.4.0 FCS ImageReader.getRawImageType(0) // returns null for earth.jpg, Bas-noir.jpg, etc. if(imageType == null) { Iterator imageTypes = reader.getImageTypes(imageIndex); while(imageType == null && imageTypes.hasNext()) { imageType = (ImageTypeSpecifier)imageTypes.next(); } } // XXX Should an exception be thrown if imageType is null? if(imageType != null) { // Set the SampleModel and ColorModel. layout.setSampleModel(imageType.getSampleModel()); layout.setColorModel(imageType.getColorModel()); } } // --- Set up the destination bounds. --- // Calculate the computable destination bounds. Dimension sourceSize = getSourceSize(param, reader, imageIndex); Rectangle srcRegion = new Rectangle(); Rectangle destRegion = new Rectangle(); computeRegions(param, sourceSize.width, sourceSize.height, layout.getMinX(null), // valid value or 0 layout.getMinY(null), // valid value or 0 false, srcRegion, destRegion); if(!destRegion.isEmpty()) { // Backup layout image bounds with computable bounds. if(!layout.isValid(ImageLayout.WIDTH_MASK)) { layout.setWidth(destRegion.width); } if(!layout.isValid(ImageLayout.HEIGHT_MASK)) { layout.setHeight(destRegion.height); } if(!layout.isValid(ImageLayout.MIN_X_MASK)) { layout.setMinX(destRegion.x); } if(!layout.isValid(ImageLayout.MIN_Y_MASK)) { layout.setMinY(destRegion.y); } // Ensure the layout bounds intersect computable bounds. Rectangle destBounds = new Rectangle(layout.getMinX(null), layout.getMinY(null), layout.getWidth(null), layout.getHeight(null)); if(destRegion.intersection(destBounds).isEmpty()) { throw new IllegalArgumentException (I18N.getString("ImageReadOpImage0")); } } // --- Set up the tile grid. --- if(!layout.isValid(ImageLayout.TILE_GRID_X_OFFSET_MASK)) { layout.setTileGridXOffset(reader.getTileGridXOffset(imageIndex)); } if(!layout.isValid(ImageLayout.TILE_GRID_Y_OFFSET_MASK)) { layout.setTileGridYOffset(reader.getTileGridYOffset(imageIndex)); } if(!layout.isValid(ImageLayout.TILE_WIDTH_MASK)) { layout.setTileWidth(reader.getTileWidth(imageIndex)); } if(!layout.isValid(ImageLayout.TILE_HEIGHT_MASK)) { layout.setTileHeight(reader.getTileHeight(imageIndex)); } return layout; } /** * Returns whether an ImageTypeSpecifier may be used * to read in the image at a specified index. * * XXX */ private static boolean isCompatibleType(ImageTypeSpecifier imageType, ImageReader reader, int imageIndex) throws IOException { Iterator imageTypes = reader.getImageTypes(imageIndex); boolean foundIt = false; while (imageTypes.hasNext()) { ImageTypeSpecifier type = (ImageTypeSpecifier)imageTypes.next(); if (type.equals(imageType)) { foundIt = true; break; } } return foundIt; } /** * Returns the source region to be read. If the sourceRenderSize * is being used it is returned; otherwise the raw source dimensions * are returned. * * XXX */ private static Dimension getSourceSize(ImageReadParam param, ImageReader reader, int imageIndex) throws IOException { Dimension sourceSize = null; if(param != null && param.canSetSourceRenderSize()) { sourceSize = param.getSourceRenderSize(); } if(sourceSize == null) { sourceSize = new Dimension(reader.getWidth(imageIndex), reader.getHeight(imageIndex)); } return sourceSize; } /** * XXX */ // Code copied from ImageReader.java private static Rectangle getSourceRegion(ImageReadParam param, int srcWidth, int srcHeight) { Rectangle sourceRegion = new Rectangle(0, 0, srcWidth, srcHeight); if (param != null) { Rectangle region = param.getSourceRegion(); if (region != null) { sourceRegion = sourceRegion.intersection(region); } int subsampleXOffset = param.getSubsamplingXOffset(); int subsampleYOffset = param.getSubsamplingYOffset(); sourceRegion.x += subsampleXOffset; sourceRegion.y += subsampleYOffset; sourceRegion.width -= subsampleXOffset; sourceRegion.height -= subsampleYOffset; } return sourceRegion; } /** * XXX */ // clipDestRegion: whether to clip destRegion to positive coordinates. // Code based on method of same name in ImageReader.java private static void computeRegions(ImageReadParam param, int srcWidth, int srcHeight, int destMinX, int destMinY, boolean clipDestRegion, Rectangle srcRegion, Rectangle destRegion) { if (srcRegion == null) { throw new IllegalArgumentException("srcRegion == null"); } if (destRegion == null) { throw new IllegalArgumentException("destRegion == null"); } // Start with the entire source image srcRegion.setBounds(0, 0, srcWidth, srcHeight); // Destination also starts with source image, as that is the // maximum extent if there is no subsampling destRegion.setBounds(destMinX, destMinY, srcWidth, srcHeight); // Clip that to the param region, if there is one int periodX = 1; int periodY = 1; int gridX = 0; int gridY = 0; if (param != null) { Rectangle paramSrcRegion = param.getSourceRegion(); if (paramSrcRegion != null) { srcRegion.setBounds(srcRegion.intersection(paramSrcRegion)); } periodX = param.getSourceXSubsampling(); periodY = param.getSourceYSubsampling(); gridX = param.getSubsamplingXOffset(); gridY = param.getSubsamplingYOffset(); srcRegion.translate(gridX, gridY); srcRegion.width -= gridX; srcRegion.height -= gridY; Point destinationOffset = param.getDestinationOffset(); destRegion.translate(destinationOffset.x, destinationOffset.y); } if(clipDestRegion) { // Now clip any negative destination offsets, i.e. clip // to the top and left of the destination image if (destRegion.x < 0) { int delta = -destRegion.x*periodX; srcRegion.x += delta; srcRegion.width -= delta; destRegion.x = 0; } if (destRegion.y < 0) { int delta = -destRegion.y*periodY; srcRegion.y += delta; srcRegion.height -= delta; destRegion.y = 0; } } // Now clip the destination Region to the subsampled width and height int subsampledWidth = (srcRegion.width + periodX - 1)/periodX; int subsampledHeight = (srcRegion.height + periodY - 1)/periodY; destRegion.width = subsampledWidth; destRegion.height = subsampledHeight; if (srcRegion.isEmpty() || destRegion.isEmpty()) { throw new IllegalArgumentException (I18N.getString("ImageReadOpImage1")); } } /** * XXX * NB: This class may reset the following fields of the ImageReadParam * destinationOffset * destinationType * sourceRegion */ ImageReadOpImage(ImageLayout layout, Map configuration, ImageReadParam param, ImageReader reader, int imageIndex, boolean readThumbnails, ImageInputStream streamToClose) throws IOException { super(null, layoutHelper(layout, param, reader, imageIndex), configuration, false); // Revise parameter 'param' as needed. if(param == null) { // Get the ImageReadParam from the ImageReader. param = reader.getDefaultReadParam(); } else if(param instanceof Cloneable) { this.param = param; } else if(param.getClass().getName().equals( "javax.imageio.ImageReadParam")) { // The ImageReadParam passed in is non-null. As the // ImageReadParam class is not Cloneable, if the param // class is simply ImageReadParam, then create a new // ImageReadParam instance and set all its fields // which were set in param. This will eliminate problems // with concurrent modification of param for the cases // in which there is not a special ImageReadparam used. // Create a new ImageReadParam instance. ImageReadParam newParam = new ImageReadParam(); // Set all fields which need to be set. // IIOParamController field. if(param.hasController()) { newParam.setController(param.getController()); } // Destination fields. newParam.setDestination(param.getDestination()); if(param.getDestinationType() != null) { // Set the destination type only if non-null as the // setDestinationType() clears the destination field. newParam.setDestinationType(param.getDestinationType()); } newParam.setDestinationBands(param.getDestinationBands()); newParam.setDestinationOffset(param.getDestinationOffset()); // Source fields. newParam.setSourceBands(param.getSourceBands()); newParam.setSourceRegion(param.getSourceRegion()); if(param.getSourceMaxProgressivePass() != Integer.MAX_VALUE) { newParam.setSourceProgressivePasses( param.getSourceMinProgressivePass(), param.getSourceNumProgressivePasses()); } if(param.canSetSourceRenderSize()) { newParam.setSourceRenderSize(param.getSourceRenderSize()); } newParam.setSourceSubsampling(param.getSourceXSubsampling(), param.getSourceYSubsampling(), param.getSubsamplingXOffset(), param.getSubsamplingYOffset()); // Replace the local variable with the new ImageReadParam. param = newParam; } // Revise parameter 'readThumbnails' as needed. if(readThumbnails && !reader.hasThumbnails(imageIndex)) { // Unset thumbnail flag if not supported by ImageReader. readThumbnails = false; } // Set instance variables from (possibly revised) parameters. this.param = param; this.reader = reader; this.imageIndex = imageIndex; this.readThumbnails = readThumbnails; this.streamToClose = streamToClose; // If an ImageTypeSpecifier is specified in the ImageReadParam // but it is incompatible with the ImageReader, then attempt to // replace it with a compatible one derived from this image. if(param.getDestinationType() != null && !isCompatibleType(param.getDestinationType(), reader, imageIndex) && sampleModel != null && colorModel != null) { ImageTypeSpecifier newImageType = new ImageTypeSpecifier(colorModel, sampleModel); if(isCompatibleType(newImageType, reader, imageIndex)) { param.setDestinationType(newImageType); } } // --- Compute the destination to source mapping coefficients. --- Dimension sourceSize = getSourceSize(param, reader, imageIndex); Rectangle srcRegion = getSourceRegion(param, sourceSize.width, sourceSize.height); Point destinationOffset = this.param.getDestinationOffset(); this.scaleX = this.param.getSourceXSubsampling(); this.scaleY = this.param.getSourceYSubsampling(); this.transX = srcRegion.x + this.param.getSubsamplingXOffset() - this.param.getSourceXSubsampling()*(minX + destinationOffset.x); this.transY = srcRegion.y + this.param.getSubsamplingYOffset() - this.param.getSourceYSubsampling()*(minY + destinationOffset.y); // Replace the original destination offset with (0,0) as the // destination-to-source mapping assimilates this value. this.param.setDestinationOffset(new Point()); // XXX Need to unset other ImageReadParam settings either here // or in computeTile(). Examine this issue taking into account // synchronization. // Set the ImageReadParam property. setProperty(ImageReadDescriptor.PROPERTY_NAME_IMAGE_READ_PARAM, param); // Set the ImageReader property. setProperty(ImageReadDescriptor.PROPERTY_NAME_IMAGE_READER, reader); // If metadata are being read, set the value of the metadata // properties to UndefinedProperty so that the property // names will appear in the array of property names. The actual // values will be retrieved when getProperty() is invoked. if(!reader.isIgnoringMetadata()) { // Get the service provider interface, if any. ImageReaderSpi provider = reader.getOriginatingProvider(); // Stream metadata. if(provider == null || provider.isStandardStreamMetadataFormatSupported() || provider.getNativeStreamMetadataFormatName() != null) { // Assume an ImageReader with a null provider supports // stream metadata. setProperty(ImageReadDescriptor.PROPERTY_NAME_METADATA_STREAM, java.awt.Image.UndefinedProperty); } else { // Provider supports neither standard nor native stream // metadata so set flag to suppress later reading attempt. streamMetadataRead = true; } // Image metadata. if(provider == null || provider.isStandardImageMetadataFormatSupported() || provider.getNativeImageMetadataFormatName() != null) { // Assume an ImageReader with a null provider supports // image metadata. setProperty(ImageReadDescriptor.PROPERTY_NAME_METADATA_IMAGE, java.awt.Image.UndefinedProperty); } else { // Provider supports neither standard nor native image // metadata so set flag to suppress later reading attempt. imageMetadataRead = true; } } // If thumbnail read flag is set, set the value of the thumbnail // property to UndefinedProperty so that the thumbnail property // name will appear in the array of property names. The actual // value will be retrieved when getProperty() is invoked. if(readThumbnails && reader.readerSupportsThumbnails()) { setProperty(ImageReadDescriptor.PROPERTY_NAME_THUMBNAILS, java.awt.Image.UndefinedProperty); } } /** * Returns false as ImageReaders might return Rasters * via computeTile() tile that are internally cached. */ public boolean computesUniqueTiles() { return false; } /** * XXX */ private Rectangle computeSourceRect(Rectangle destRect) { Rectangle sourceRect = new Rectangle(); sourceRect.x = scaleX*destRect.x + transX; sourceRect.y = scaleY*destRect.y + transY; sourceRect.width = scaleX*(destRect.x + destRect.width) + transX - sourceRect.x; sourceRect.height = scaleY*(destRect.y + destRect.height) + transY - sourceRect.y; return sourceRect; } /** * Computes a tile. * * @param tileX The X index of the tile. * @param tileY The Y index of the tile. */ public Raster computeTile(int tileX, int tileY) { //XXX System.out.println("Tile ("+tileX+","+tileY+")"); // Create a new WritableRaster to represent this tile. Point org = new Point(tileXToX(tileX), tileYToY(tileY)); //WritableRaster dest = Raster.createWritableRaster(sampleModel, org); Rectangle rect = new Rectangle(org.x, org.y, tileWidth, tileHeight); // Clip output rectangle to image bounds. // Not sure what will happen here with the bounds intersection. Rectangle destRect = rect.intersection(getBounds()); // XXX Check for destRect.isEmpty()? /* XXX delete java.awt.geom.AffineTransform transform = new java.awt.geom.AffineTransform(scaleX, 0, 0, scaleY, transX, transY); */ Rectangle srcRect = computeSourceRect(destRect); /* XXX delete transform.createTransformedShape(destRect).getBounds(); */ WritableRaster readerTile = null; try { synchronized(reader) { param.setSourceRegion(srcRect); BufferedImage bi = reader.read(imageIndex, param); WritableRaster ras = bi.getRaster(); readerTile = ras.createWritableChild(0, 0, ras.getWidth(), ras.getHeight(), org.x, org.y, null); } } catch(IOException e) { throw new RuntimeException(e); } WritableRaster tile = null; if(sampleModel == readerTile.getSampleModel()) { tile = readerTile; } else { // XXX As this method is synchronized, could a single // destination be supplied to the reader instead of // creating a new one? tile = Raster.createWritableRaster(sampleModel, org); tile.setRect(readerTile); } return tile; } /** * Throws an IllegalArgumentException since the image has no image * sources. * * @param sourceRect ignored. * @param sourceIndex ignored. * * @throws IllegalArgumentException since the image has no sources. */ public Rectangle mapSourceRect(Rectangle sourceRect, int sourceIndex) { throw new IllegalArgumentException (I18N.getString("ImageReadOpImage2")); } /** * Throws an IllegalArgumentException since the image has no image * sources. * * @param destRect ignored. * @param sourceIndex ignored. * * @throws IllegalArgumentException since the image has no sources. */ public Rectangle mapDestRect(Rectangle destRect, int sourceIndex) { throw new IllegalArgumentException (I18N.getString("ImageReadOpImage2")); } /** * Gets a property from the property set of this image. If the * property name is not recognized, * java.awt.Image.UndefinedProperty will be returned. * *

This implementation first attempts to retrieve the property * using the equivalent superclass method. If the returned value * is not a valid property value, the requested property name is * that of the image thumbnails property, the stream metadata * property, or the image metadata property, and there has been no * prior attempt to read the corresponding property value, then its * reads the value and set the property. This implementation therefore * defers reading of the image thumbnails, stream metadata, and image * metadata values until the correpsonding property is actually * requested.

* * @param name the name of the property to get, as a String. * * @return A reference to the property Object, or the value * java.awt.Image.UndefinedProperty. * * @exception IllegalArgumentException if propertyName * is null. */ public Object getProperty(String name) { // Attempt to get property from superclass method. Object property = super.getProperty(name); // If thumbnail property name with undefined value and thumbnails // are being read and an attempt to read them has not already been // made, then read the thumbnails and set the property. if((property == null || property == java.awt.Image.UndefinedProperty)) { // Thumbnails if(readThumbnails && name.equalsIgnoreCase( ImageReadDescriptor.PROPERTY_NAME_THUMBNAILS)) { // Lock the class to avoid a race condition here // and with computeTile(). synchronized(reader) { // First re-check the flag in case another thread // got here first. if(readThumbnails) { try { // Get number of thumbnails. int numThumbnails = reader.getNumThumbnails(imageIndex); if(numThumbnails > 0) { // Read all thumbnails. BufferedImage[] thumbnails = new BufferedImage[numThumbnails]; for(int i = 0; i < numThumbnails; i++) { thumbnails[i] = reader.readThumbnail(imageIndex, i); } // Set thumbnail property. setProperty( ImageReadDescriptor.PROPERTY_NAME_THUMBNAILS, thumbnails); // Update return value. property = thumbnails; } } catch(IOException e) { throw new RuntimeException(e); } finally { // If return value is somehow null set it // to UndefinedProperty. if(property == null) { property = java.awt.Image.UndefinedProperty; } // Unset thumbnail flag to avert subsequent // reading attempts in case this one failed. readThumbnails = false; } } } } else if(!reader.isIgnoringMetadata() && ((!streamMetadataRead && name.equalsIgnoreCase( ImageReadDescriptor.PROPERTY_NAME_METADATA_STREAM)) || (!imageMetadataRead && name.equalsIgnoreCase( ImageReadDescriptor.PROPERTY_NAME_METADATA_IMAGE)))) { // Lock the class to avoid a race condition here // and with computeTile(). synchronized(reader) { // Set flag to indicate stream or image metadata. boolean isStreamMetadata = name.equalsIgnoreCase( ImageReadDescriptor.PROPERTY_NAME_METADATA_STREAM); // Recheck the appropriate flag. if(!(isStreamMetadata ? streamMetadataRead : imageMetadataRead)) { // Set property name. String propertyName = isStreamMetadata ? ImageReadDescriptor.PROPERTY_NAME_METADATA_STREAM : ImageReadDescriptor.PROPERTY_NAME_METADATA_IMAGE; IIOMetadata metadata = null; try { // Read metadata. metadata = isStreamMetadata ? reader.getStreamMetadata() : reader.getImageMetadata(imageIndex); // Set metadata property. if(metadata != null) { setProperty(propertyName, metadata); } // Update return value. property = metadata; } catch(IOException e) { throw new RuntimeException(e); } finally { // If return value is somehow null set it // to UndefinedProperty. if(property == null) { property = java.awt.Image.UndefinedProperty; } // Set appropriate flag to avert subsequent // reading attempts in case this one failed. if(isStreamMetadata) { streamMetadataRead = true; } else { imageMetadataRead = true; } } } } } } return property; } /** * Closes an ImageInputStream passed in, if any. */ public void dispose() { if(streamToClose != null) { try { streamToClose.close(); } catch(IOException e) { // Ignore it. } } super.dispose(); } } jai-imageio-core-1.2/src/share/classes/com/sun/media/jai/imageioimpl/ImageReadCIF.java0000664000175100017510000001477110203036165027525 0ustar tilletille/* * $RCSfile: ImageReadCIF.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.1 $ * $Date: 2005-02-11 05:01:54 $ * $State: Exp $ */ package com.sun.media.jai.imageioimpl; import java.awt.Dimension; import java.awt.RenderingHints; import java.awt.image.renderable.ParameterBlock; import java.util.ArrayList; import java.util.List; import javax.imageio.ImageReader; import javax.media.jai.CollectionImage; import javax.media.jai.CollectionImageFactory; import javax.media.jai.CollectionOp; import javax.media.jai.JAI; import javax.media.jai.PlanarImage; import com.sun.media.jai.operator.ImageReadDescriptor; public class ImageReadCIF implements CollectionImageFactory { static CollectionImage createStatic(ParameterBlock args, RenderingHints hints) { // Clone the ParameterBlock as the ImageChoice will be overwritten. ParameterBlock renderedPB = (ParameterBlock)args.clone(); // Get the ImageChoice. int[] imageIndices = (int[])args.getObjectParameter(1); // Variables to be set in the subsequent "if" block. // XXX Could probably collapse the if block into a single code seq. int numSources; ImageIOCollectionImage imageList = null; if(imageIndices == null) { // null-valued ImageChoice: load all images. // Load the first image. renderedPB.set(0, 1); PlanarImage image = JAI.create("ImageRead", renderedPB, hints); // Get the ImageReader property. Object readerProperty = image.getProperty( ImageReadDescriptor.PROPERTY_NAME_IMAGE_READER); // Try to read the number of images. if(readerProperty instanceof ImageReader) { try { // XXX Really should not allow search here. If search // is disallowed and -1 is returned from getNumImages(), // then "ImageRead" should just be called until an // IndexOutOfBoundsException is caught. numSources = ((ImageReader)readerProperty).getNumImages(true); } catch(Exception e) { // IOException // Default to one source. numSources = 1; } } else { numSources = 1; } // Allocate and fill index array. imageIndices = new int[numSources]; for(int i = 0; i < numSources; i++) { imageIndices[i] = i; } // Allocate list and add first image. imageList = new ImageIOCollectionImage(numSources); imageList.add(image); } else { // Set the number of sources and create the list. numSources = imageIndices.length; imageList = new ImageIOCollectionImage(numSources); // Load the first image requested. renderedPB.set(imageIndices[0], 1); PlanarImage image = JAI.create("ImageRead", renderedPB, hints); // Add the first image to the list. imageList.add(image); } // Read subsequent images and add to the list. for(int idx = 1; idx < numSources; idx++) { renderedPB.set(imageIndices[idx], 1); PlanarImage image = JAI.create("ImageRead", renderedPB, hints); imageList.add(image); } // Get the first image in the Collection. PlanarImage firstImage = (PlanarImage)imageList.get(0); // Transfer properties to the Collection. ImageReadCRIF.copyProperty(firstImage, imageList, ImageReadDescriptor.PROPERTY_NAME_IMAGE_READ_PARAM); ImageReadCRIF.copyProperty(firstImage, imageList, ImageReadDescriptor.PROPERTY_NAME_IMAGE_READER); ImageReadCRIF.copyProperty(firstImage, imageList, ImageReadDescriptor.PROPERTY_NAME_METADATA_STREAM); return imageList; } /** Constructor. */ public ImageReadCIF() {} public CollectionImage create(ParameterBlock args, RenderingHints hints) { return createStatic(args, hints); } // Forget it. public CollectionImage update(ParameterBlock oldParamBlock, RenderingHints oldHints, ParameterBlock newParamBlock, RenderingHints newHints, CollectionImage oldRendering, CollectionOp op) { return null; } } jai-imageio-core-1.2/src/share/classes/com/sun/media/jai/imageioimpl/ImageWriteCRIF.java0000664000175100017510000006547410203036165030074 0ustar tilletille/* * $RCSfile: ImageWriteCRIF.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.1 $ * $Date: 2005-02-11 05:01:55 $ * $State: Exp $ */ package com.sun.media.jai.imageioimpl; import java.awt.Dimension; import java.awt.RenderingHints; import java.awt.image.BufferedImage; import java.awt.image.RenderedImage; import java.awt.image.renderable.ParameterBlock; import java.awt.image.renderable.RenderableImage; import java.awt.image.renderable.RenderContext; import java.io.IOException; import java.io.OutputStream; import java.io.RandomAccessFile; import java.net.Socket; import java.util.Arrays; import java.util.EventListener; import java.util.Iterator; import java.util.Locale; import javax.imageio.IIOImage; import javax.imageio.ImageIO; import javax.imageio.ImageTypeSpecifier; import javax.imageio.ImageWriter; import javax.imageio.ImageWriteParam; import javax.imageio.event.IIOWriteProgressListener; import javax.imageio.event.IIOWriteWarningListener; import javax.imageio.metadata.IIOMetadata; import javax.imageio.stream.ImageOutputStream; import javax.media.jai.CRIFImpl; import javax.media.jai.PlanarImage; import javax.media.jai.RenderedImageAdapter; import javax.media.jai.WritablePropertySource; import com.sun.media.jai.operator.ImageWriteDescriptor; public final class ImageWriteCRIF extends CRIFImpl { public static void main(String[] args) throws Throwable { java.io.File inFile = new java.io.File(args[0]); java.io.File outFile = new java.io.File(args[1]); String format = args.length > 2 ? args[2] : "png"; String mode = args.length > 3 ? args[3] : "rendered"; int imageIndex = 0; javax.imageio.stream.ImageInputStream inStream = javax.imageio.ImageIO.createImageInputStream(inFile); java.util.Iterator iter = javax.imageio.ImageIO.getImageReaders(inStream); javax.imageio.ImageReader reader = (javax.imageio.ImageReader)iter.next(); reader.setInput(inStream); RenderedImage image = reader.read(imageIndex); javax.imageio.metadata.IIOMetadata streamMetadata = reader.getStreamMetadata(); javax.imageio.metadata.IIOMetadata imageMetadata = reader.getImageMetadata(imageIndex); java.awt.image.BufferedImage[] thumbnails = null; if(reader.hasThumbnails(imageIndex)) { int numThumbnails = reader.getNumThumbnails(imageIndex); thumbnails = new java.awt.image.BufferedImage[numThumbnails]; for(int i = 0; i < numThumbnails; i++) { thumbnails[i] = reader.readThumbnail(imageIndex, i); } } ImageWriteCRIF crif = new ImageWriteCRIF(); ParameterBlock pb = new ParameterBlock(); if(mode.equalsIgnoreCase("rendered")) { pb.addSource(image); } else if(mode.equalsIgnoreCase("renderable")) { ParameterBlock renderablePB = new ParameterBlock(); renderablePB.addSource(image); RenderableImage renderable = javax.media.jai.JAI.createRenderable("renderable", renderablePB); pb.addSource(renderable); } pb.add(outFile); // Output pb.add(format); // Format pb.add(Boolean.TRUE); // UseProperties pb.add(Boolean.TRUE); // Transcode pb.add(Boolean.TRUE); // VerifyOutput pb.add(Boolean.TRUE); // AllowPixelReplacement pb.add(null); // TileSize pb.add(streamMetadata); pb.add(imageMetadata); pb.add(thumbnails); pb.add(null); // EventListener[] pb.add(null); // Locale pb.add(null); // ImageWriteParam pb.add(null); // ImageWriter if(mode.equalsIgnoreCase("rendered")) { crif.create(pb, null); } else if(mode.equalsIgnoreCase("renderable")) { java.awt.geom.AffineTransform transform = new java.awt.geom.AffineTransform(256, 0, 0, 512, 0, 0); crif.create(new RenderContext(transform), pb); } } public ImageWriteCRIF() { super(); } /** * Attempt to create an {@link ImageOutputStream} for the supplied * output. The following sequence is effected: *
    *
  1. *
  2. ImageIO.createImageOutputStream() is invoked * with parameter set to the (possibly converted) output and the * value it returns (which could be null) is returned * to the caller.
  3. *
* * @param output An Object to be used as the destination, * such as a String, File, writable * RandomAccessFile, OutputStream, writable * Socket, or writable Channel. * * @return An ImageOutputStream or null. */ static ImageOutputStream getImageOutputStream(Object output) { // The value to be returned. ImageOutputStream stream = null; // If already an ImageOutputStream just cast. if(output instanceof ImageOutputStream) { stream = (ImageOutputStream)output; } else { if(output instanceof String) { // If output is a String replace it with a RandomAccessFile. try { // 'output' is conditionally checked for writability // in the OperationDescriptor. output = new RandomAccessFile((String)output, "rw"); } catch(Exception e) { throw new RuntimeException (I18N.getString("ImageWriteCRIF0")+" "+output); } } else if(output instanceof Socket) { // If output is a Socket replace it with an OutputStream. try { // XXX check binding, connection, closed, shutdown // as these could have changed. output = ((Socket)output).getOutputStream(); } catch(Exception e) { throw new RuntimeException (I18N.getString("ImageWriteCRIF1")+" "+output); } } // Create the ImageOutputStream. try { stream = ImageIO.createImageOutputStream(output); } catch(IOException e) { throw new RuntimeException(e); } } return stream; } /** * {@link RenderedImageFactory} implementation. */ public RenderedImage create(ParameterBlock pb, RenderingHints rh) { return create(0, false, pb, rh); } private static ImageWriteParam getWriteParam(ImageWriteParam param, ImageWriter writer) { // Set default to original ImageWriteParam. ImageWriteParam newParam = param; if(param == null) { newParam = writer.getDefaultWriteParam(); } else if(param.getClass().getName().equals( "javax.imageio.ImageWriteParam")) { // The ImageWriteParam passed in is non-null. As the // ImageWriteParam class is not Cloneable, if the param // class is simply ImageWriteParam, then create a new // ImageWriteParam instance and set all its fields // which were set in param. This will eliminate problems // with concurrent modification of param for the cases // in which there is not a special ImageWriteParam used. // Create a new ImageWriteParam instance. newParam = writer.getDefaultWriteParam(); // Set all fields which need to be set. // IIOParamController field. if(param.hasController()) { newParam.setController(param.getController()); } // Destination fields. newParam.setDestinationOffset(param.getDestinationOffset()); newParam.setDestinationType(param.getDestinationType()); // Source fields. newParam.setSourceBands(param.getSourceBands()); newParam.setSourceRegion(param.getSourceRegion()); newParam.setSourceSubsampling(param.getSourceXSubsampling(), param.getSourceYSubsampling(), param.getSubsamplingXOffset(), param.getSubsamplingYOffset()); // Compression. if(param.canWriteCompressed()) { int compressionMode = param.getCompressionMode(); newParam.setCompressionMode(compressionMode); if(compressionMode == ImageWriteParam.MODE_EXPLICIT) { newParam.setCompressionQuality(param.getCompressionQuality()); newParam.setCompressionType(param.getCompressionType()); } } // Progressive if(param.canWriteProgressive()) { newParam.setProgressiveMode(param.getProgressiveMode()); } // Tiling if(param.canWriteTiles()) { int tilingMode = param.getTilingMode(); newParam.setTilingMode(tilingMode); if(tilingMode == ImageWriteParam.MODE_EXPLICIT) { newParam.setTiling(param.getTileWidth(), param.getTileHeight(), param.getTileGridXOffset(), param.getTileGridYOffset()); } } } return newParam; } /** * If tiling is supported, determine the appropriate tile size and * set it on the returned param if necessary. The returned param * will either be a new ImageWriteParam or the one passed in with * its tiling settings possibly modified. */ private static ImageWriteParam setTileSize(ImageWriteParam param, ImageWriter writer, Dimension tileSize, RenderedImage source) { ImageWriteParam returnParam = getWriteParam(param, writer); // If tiling possible set tile size if needed. if(returnParam.canWriteTiles()) { if(tileSize != null) { // Check tile size. if(tileSize.width <= 0 || tileSize.height <= 0) { throw new IllegalArgumentException ("tileSize.width <= 0 || tileSize.height <= 0"); } // Use specified tile size. returnParam.setTilingMode(ImageWriteParam.MODE_EXPLICIT); returnParam.setTiling(tileSize.width, tileSize.height, 0, 0); // XXX set tile offsets? } else if(param == null) { if(source.getNumXTiles() > 1 || source.getNumYTiles() > 1) { // Null tile size and param args: use source tile size. returnParam.setTilingMode(ImageWriteParam.MODE_EXPLICIT); returnParam.setTiling(source.getTileWidth(), source.getTileHeight(), 0, 0); // XXX set tile offsets? } } else if(returnParam.getTilingMode() == ImageWriteParam.MODE_EXPLICIT) { // Param passed in has explicit mode set but the tile // grid might not actually be set. boolean setTileSize = false; // Save reference to preferred tile size array. Dimension[] preferredTileSizes = returnParam.getPreferredTileSizes(); // Set the tile width. int tileWidth = 0; try { // Try to get it from the param. tileWidth = returnParam.getTileWidth(); } catch(IllegalStateException e) { // Not set in the param. setTileSize = true; if(preferredTileSizes != null && preferredTileSizes.length >= 2 && preferredTileSizes[0].width > 0 && preferredTileSizes[1].width > 0) { // Use average of first two preferred tile widths. tileWidth = (preferredTileSizes[0].width + preferredTileSizes[1].width) / 2; } else { // Use source image tile width. tileWidth = source.getTileWidth(); } } // Set the tile height. int tileHeight = 0; try { // Try to get it from the param. tileHeight = returnParam.getTileHeight(); } catch(IllegalStateException e) { // Not set in the param. setTileSize = true; if(preferredTileSizes != null && preferredTileSizes.length >= 2 && preferredTileSizes[0].height > 0 && preferredTileSizes[1].height > 0) { // Use average of first two preferred tile heights. tileHeight = (preferredTileSizes[0].height + preferredTileSizes[1].height) / 2; } else { // Use source image tile height. tileHeight = source.getTileHeight(); } } // Set the tile size if not previously set in the param. if(setTileSize) { returnParam.setTiling(tileWidth, tileHeight, 0, 0); // XXX set tile offsets? } } } return returnParam; } static RenderedImage create(int imageIndex, boolean writeToSequence, ParameterBlock pb, RenderingHints rh) { // Value to be returned. RenderedImage image = null; // Get the source image. RenderedImage source = pb.getRenderedSource(0); // Get the writer parameters. ImageWriteParam param = (ImageWriteParam)pb.getObjectParameter(12); // Set the target image type. ImageTypeSpecifier destinationType = null; if(param != null) { destinationType = param.getDestinationType(); } if(destinationType == null) { destinationType = new ImageTypeSpecifier(source); } // Get the writer. ImageWriter writer = (ImageWriter)pb.getObjectParameter(13); if(writer == null) { // Get the format. Should be non-null from OperationDescriptor. String format = (String)pb.getObjectParameter(1); // Find a writer. Iterator writers = ImageIO.getImageWriters(destinationType, format); // Get the writer. if(writers != null && writers.hasNext()) { writer = (ImageWriter)writers.next(); } } // XXX What if no writer? Exception? if(writer != null) { // XXX Replace ImageWriter parameter in ParameterBlock? ImageOutputStream streamToClose = null; // Set the output if not writing to a sequence (in which // case the output should already be set. if(!writeToSequence) { // Get the output. Object output = pb.getObjectParameter(0); // Try to get an ImageOutputStream. ImageOutputStream stream = getImageOutputStream(output); // Set stream to close if not writing to a sequence. streamToClose = stream != output ? stream : null; // Set the writer's output. writer.setOutput(stream != null ? stream : output); } // Get the property use flag. boolean useProperties = ((Boolean)pb.getObjectParameter(2)).booleanValue(); // Get the transcoding flag. boolean transcode = ((Boolean)pb.getObjectParameter(3)).booleanValue(); IIOMetadata streamMetadata = null; if(!writeToSequence) { // Get the stream metadata. streamMetadata = (IIOMetadata)pb.getObjectParameter(7); // If null, get stream metadata from source properties // if allowed. if(streamMetadata == null && useProperties) { Object streamMetadataProperty = source.getProperty( ImageWriteDescriptor.PROPERTY_NAME_METADATA_STREAM); if(streamMetadataProperty instanceof IIOMetadata) { streamMetadata = (IIOMetadata)streamMetadataProperty; } } // Transcode the stream metadata if requested. if(streamMetadata != null && transcode) { // Overwrite the stream metadata with transcoded metadata. streamMetadata = writer.convertStreamMetadata(streamMetadata, param); } } // Get the image metadata. IIOMetadata imageMetadata = (IIOMetadata)pb.getObjectParameter(8); // If null, get image metadata from source properties if allowed. if(imageMetadata == null && useProperties) { Object imageMetadataProperty = source.getProperty( ImageWriteDescriptor.PROPERTY_NAME_METADATA_IMAGE); if(imageMetadataProperty instanceof IIOMetadata) { imageMetadata = (IIOMetadata)imageMetadataProperty; } } // Transcode the image metadata if requested. if(imageMetadata != null && transcode) { // Overwrite the image metadata with transcoded metadata. imageMetadata = writer.convertImageMetadata(imageMetadata, destinationType, param); } // Get the thumbnails if supported by the writer. BufferedImage[] thumbnails = null; if(writer.getNumThumbnailsSupported(destinationType, param, streamMetadata, imageMetadata) > 0) { thumbnails = (BufferedImage[])pb.getObjectParameter(9); // If null, get thumbnails from source properties if allowed. if(thumbnails == null && useProperties) { Object thumbnailsProperty = source.getProperty( ImageWriteDescriptor.PROPERTY_NAME_METADATA_IMAGE); if(thumbnailsProperty instanceof BufferedImage[]) { thumbnails = (BufferedImage[])thumbnailsProperty; } } } // Get the locale parameter and set on the writer. Locale locale = (Locale)pb.getObjectParameter(11); if(locale != null) { writer.setLocale(locale); } // Get the listeners parameter and set on the writer. EventListener[] listeners = (EventListener[])pb.getObjectParameter(10); if(listeners != null) { for(int i = 0; i < listeners.length; i++) { EventListener listener = listeners[i]; if(listener instanceof IIOWriteProgressListener) { writer.addIIOWriteProgressListener( (IIOWriteProgressListener)listener); } if(listener instanceof IIOWriteWarningListener) { writer.addIIOWriteWarningListener( (IIOWriteWarningListener)listener); } } } // Set the tile size. // XXX Replace ImageWriteParam parameter in ParameterBlock? param = setTileSize(param, writer, (Dimension)pb.getObjectParameter(6), source); // Create the IIOImage container. IIOImage iioImage = new IIOImage(source, thumbnails != null ? Arrays.asList(thumbnails) : null, imageMetadata); try { // Write the image. if(writeToSequence) { writer.writeToSequence(iioImage, param); } else { writer.write(streamMetadata, iioImage, param); } // Get the pixel replacement parameter. boolean allowPixelReplacement = ((Boolean)pb.getObjectParameter(5)).booleanValue(); // Set the return value. if(allowPixelReplacement && source instanceof PlanarImage && writer.canReplacePixels(imageIndex)) { // Create an image which is a PropertyChangeListener of // "invalidregion" events including RenderingChangeEvents. image = new PixelReplacementImage(source, rh, param, writer, imageIndex, streamToClose); // Register the image as a sink of its source so that // it automatically receives events. ((PlanarImage)source).addSink(image); } else if(!writeToSequence) { Object writerOutput = writer.getOutput(); if(writerOutput != pb.getObjectParameter(0) && writerOutput instanceof ImageOutputStream) { // This block is executed if and only if pixel // replacement is not occurring, a sequence is // not being written, and an ImageOutputStream // inaccessible to the application is set on the // ImageWriter. ((ImageOutputStream)writerOutput).flush(); } // Set the return value to the original image or // a wrapped version thereof. image = source instanceof WritablePropertySource ? source : new RenderedImageAdapter(source); } // Set required properties. WritablePropertySource wps = (WritablePropertySource)image; // Set the ImageWriteParam property. wps.setProperty( ImageWriteDescriptor.PROPERTY_NAME_IMAGE_WRITE_PARAM, param); // Set the ImageWriter property. wps.setProperty( ImageWriteDescriptor.PROPERTY_NAME_IMAGE_WRITER, writer); // Set the stream metadata property. if(streamMetadata != null) { wps.setProperty( ImageWriteDescriptor.PROPERTY_NAME_METADATA_STREAM, streamMetadata); } // Set the image metadata property. if(imageMetadata != null) { wps.setProperty( ImageWriteDescriptor.PROPERTY_NAME_METADATA_IMAGE, imageMetadata); } // Set the thumbnail property. if(thumbnails != null) { wps.setProperty( ImageWriteDescriptor.PROPERTY_NAME_THUMBNAILS, thumbnails); } } catch(IOException e) { throw new RuntimeException(e); } } return image; } } jai-imageio-core-1.2/src/share/classes/com/sun/media/jai/imageioimpl/ImageIOCollectionImage.java0000664000175100017510000000544710203036165031616 0ustar tilletille/* * $RCSfile: ImageIOCollectionImage.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.1 $ * $Date: 2005-02-11 05:01:54 $ * $State: Exp $ */ package com.sun.media.jai.imageioimpl; import java.util.ArrayList; import javax.media.jai.CollectionImage; /** * A CollectionImage to be used as the return value from * ImageReadCIF.create() and ImageWriteCIF.create(). * The imageCollection instance variable is a List. */ class ImageIOCollectionImage extends CollectionImage { /** * Creates an ImageIOCollectionImage with the specified * capacity. * * @exception IllegalArgumentException if capacity is * not positive. */ ImageIOCollectionImage(int capacity) { super(); if(capacity <= 0) { // No message as this is not at the API level and it is // the unique exception. throw new IllegalArgumentException(); } imageCollection = new ArrayList(capacity); } } jai-imageio-core-1.2/src/share/classes/com/sun/media/jai/imageioimpl/PixelReplacementImage.java0000664000175100017510000002517510203036165031571 0ustar tilletille/* * $RCSfile: PixelReplacementImage.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.1 $ * $Date: 2005-02-11 05:01:55 $ * $State: Exp $ */ package com.sun.media.jai.imageioimpl; import java.awt.Point; import java.awt.Rectangle; import java.awt.Shape; import java.awt.image.Raster; import java.awt.image.RenderedImage; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.io.IOException; import java.io.OutputStream; import java.util.Map; import java.util.Vector; import javax.media.jai.ImageLayout; import javax.media.jai.OpImage; import javax.media.jai.PlanarImage; import javax.media.jai.RenderedOp; import javax.media.jai.PropertyChangeEventJAI; import javax.media.jai.RenderingChangeEvent; import javax.imageio.ImageWriter; import javax.imageio.ImageWriteParam; import javax.imageio.stream.ImageOutputStream; /** * Implementation of PlanarImage for the "ImageWrite" operation * for the case of ImageWriters which can replace pixels. The * sole purpose of this class is to respond to "invalidregion" events so * as to update the written image. */ final class PixelReplacementImage extends PlanarImage implements PropertyChangeListener { /** * The ImageWriteParam used in writing the image. */ private ImageWriteParam param; /** * The ImageWriter used to write the image. */ private ImageWriter writer; /** * The index of the image to be write. */ private int imageIndex; /** * A stream to be closed when the instance is disposed; may be null. */ private ImageOutputStream streamToClose; /** * Creates a Vector containing a single element. */ private static Vector createVector(Object element) { Vector v = new Vector(1); v.add(element); return v; } /** * XXX */ PixelReplacementImage(RenderedImage source, Map configuration, ImageWriteParam param, ImageWriter writer, int imageIndex, ImageOutputStream streamToClose) throws IOException { super(new ImageLayout(source), // Layout same as source. createVector(source), configuration); // Verify that the writer can replace pixels. if(!writer.canReplacePixels(imageIndex)) { throw new IllegalArgumentException ("!writer.canReplacePixels(imageIndex)"); } // Set the instance variables from the parameters. // XXX Should ImageWriteParam original settings be cached for // testing later to see whether anything important has changed? this.param = param; this.writer = writer; this.imageIndex = imageIndex; this.streamToClose = streamToClose; } /** * Close an ImageOutputStream passed in. */ public void dispose() { if(streamToClose != null) { try { streamToClose.close(); } catch(IOException e) { // Ignore it. } } super.dispose(); } /** * Gets a tile. * * @param tileX The X index of the tile. * @param tileY The Y index of the tile. */ public Raster getTile(int tileX, int tileY) { return getSourceImage(0).getTile(tileX, tileY); } // --- PropertyChangeListener implementation --- // XXX Doc public void propertyChange(PropertyChangeEvent evt) { PlanarImage source = getSourceImage(0); Object eventSource = evt.getSource(); // // Process the event if the writer can replace pixels, // the event source is the source of this OpImage, // and the event name is "invalidregion". // if((evt instanceof PropertyChangeEventJAI && evt.getPropertyName().equalsIgnoreCase("invalidregion") && eventSource.equals(source)) || (evt instanceof RenderingChangeEvent && evt.getOldValue().equals(source) && eventSource instanceof RenderedOp && evt.getNewValue().equals(((RenderedOp)eventSource).getRendering()))) { // Get the invalid region information. Shape srcInvalidRegion = null; if(evt instanceof RenderingChangeEvent) { // RenderingChangeEvent presumably from a source RenderedOp. RenderingChangeEvent rcEvent = (RenderingChangeEvent)evt; // Get the invalidated region of the source. srcInvalidRegion = rcEvent.getInvalidRegion(); // Reset this image's source. source = (PlanarImage)evt.getNewValue(); setSource(source, 0); // If entire source is invalid replace with source bounds. if(srcInvalidRegion == null) { srcInvalidRegion = ((PlanarImage)rcEvent.getOldValue()).getBounds(); } } else { // Get the invalidated region of the source. Object evtNewValue = (Shape)evt.getNewValue(); // Continue if the value class is correct. if(evtNewValue instanceof Shape) { srcInvalidRegion = (Shape)evtNewValue; // If entire source is invalid replace with source bounds. if(srcInvalidRegion == null) { srcInvalidRegion = source.getBounds(); } } } // Return if the invalid portion could not be determined. if(srcInvalidRegion == null) { return; } // Return if the invalid region does not overlap the param region. if(param != null) { Rectangle sourceRegion = param.getSourceRegion(); if(sourceRegion != null && !srcInvalidRegion.intersects(sourceRegion)) { return; } } else { param = writer.getDefaultWriteParam(); } // Get indices of all tiles overlapping the invalid region. Point[] tileIndices = source.getTileIndices(srcInvalidRegion.getBounds()); // Should not happen but return if tileIndices is null. if(tileIndices == null) return; // Get subsampling values. int gridX = minX + param.getSubsamplingXOffset(); int gridY = minY + param.getSubsamplingYOffset(); int stepX = param.getSourceXSubsampling(); int stepY = param.getSourceYSubsampling(); boolean isSubsampling = stepX != 1 || stepY != 1 || gridX != minX || gridY != minY; // Loop over affected tiles. int numTiles = tileIndices.length; for(int i = 0; i < numTiles; i++) { // Save the next tile index. Point tileIndex = tileIndices[i]; // Compute tile bounds. Rectangle tileRect = source.getTileRect(tileIndex.x, tileIndex.y); // Replace if bounds intersect invalid region. if(srcInvalidRegion.intersects(tileRect)) { // Get the source tile. Raster raster = source.getTile(tileIndex.x, tileIndex.y); Rectangle destRect; if(isSubsampling) { int destMinX = (tileRect.x - gridX + stepX - 1)/stepX; int destMinY = (tileRect.y - gridY + stepY - 1)/stepY; int destMaxX = (tileRect.x + tileRect.width - gridX + stepX - 1)/stepX; int destMaxY = (tileRect.y + tileRect.height - gridY + stepY - 1)/stepY; destRect = new Rectangle(destMinX, destMinY, destMaxX - destMinX, destMaxY - destMinY); } else { destRect = tileRect; } // Replace the pixels. try { synchronized(writer) { writer.prepareReplacePixels(imageIndex, destRect); param.setDestinationOffset(destRect.getLocation()); writer.replacePixels(raster, param); writer.endReplacePixels(); } } catch(IOException e) { throw new RuntimeException(e); } } } } } } jai-imageio-core-1.2/src/share/classes/com/sun/media/jai/imageioimpl/properties0000664000175100017510000000171310203036165026631 0ustar tilletille# # $RCSfile: properties,v $ # # Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved. # # Use is subject to license terms. # # $Revision: 1.1 $ # $Date: 2005-02-11 05:01:56 $ # $State: Exp $ # # Internationalization file for com.sun.media.jai.imageioimpl ImageReadCRIF0=Cannot create read-only RandomAccessFile for path ImageReadCRIF1=Cannot create InputStream for URL ImageReadCRIF2=Cannot create InputStream for Socket ImageReadOpImage0=Destination bounds do not intersect available destination data region. ImageReadOpImage1=Source or destination region is empty. ImageReadOpImage2=Cannot perform rectangle mapping between source and destination because the image has no sources. ImageWriteCIF0=Unable to find an ImageWriter for format ImageWriteCIF1=Source Collection has more than one image and ImageWriter cannot write sequences. ImageWriteCRIF0=Cannot create read-write RandomAccessFile for path ImageWriteCRIF1=Cannot create OutputStream for Socket jai-imageio-core-1.2/src/share/classes/com/sun/media/jai/imageioimpl/I18N.java0000664000175100017510000000416510203036165026040 0ustar tilletille/* * $RCSfile: I18N.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.1 $ * $Date: 2005-02-11 05:01:54 $ * $State: Exp $ */ package com.sun.media.jai.imageioimpl; import com.sun.media.imageioimpl.common.I18NImpl; final class I18N extends I18NImpl { static String getString(String key) { return getString("com.sun.media.jai.imageioimpl.I18N", key); } } jai-imageio-core-1.2/src/share/classes/com/sun/media/jai/imageioimpl/ImageReadWriteSpi.java0000664000175100017510000001370610203036165030667 0ustar tilletille/* * $RCSfile: ImageReadWriteSpi.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.1 $ * $Date: 2005-02-11 05:01:55 $ * $State: Exp $ */ package com.sun.media.jai.imageioimpl; import java.awt.image.renderable.ContextualRenderedImageFactory; import javax.media.jai.CollectionImageFactory; import javax.media.jai.OperationDescriptor; import javax.media.jai.OperationRegistry; import javax.media.jai.OperationRegistrySpi; import com.sun.media.jai.operator.ImageReadDescriptor; import com.sun.media.jai.operator.ImageWriteDescriptor; import javax.media.jai.registry.CollectionRegistryMode; import javax.media.jai.registry.RenderableRegistryMode; import javax.media.jai.registry.RenderedRegistryMode; /** * {@link OperationRegistrySpi} implementation to register the "ImageRead" * and "ImageWrite" operations and their associated image factories. */ public class ImageReadWriteSpi implements OperationRegistrySpi { /** The name of the product to which these operations belong. */ private String productName = "com.sun.media.jai"; /** Default constructor. */ public ImageReadWriteSpi() {} /** * Registers the "ImageRead" and "ImageWrite" operations and their * associated image factories across all supported operation modes. * An {@link OperationDescriptor} is created for each operation and * registered with the supplied {@link OperationRegistry}. An image * factory is then created for each supported mode of each operation * registered for that operation with the registry. * * @param registry The registry with which to register the operations * and their factories. */ public void updateRegistry(OperationRegistry registry) { // Create the "ImageRead" descriptor instance. OperationDescriptor readDescriptor = new ImageReadDescriptor(); // Register the "ImageRead" descriptor. registry.registerDescriptor(readDescriptor); // Create the "ImageRead" CRIF. ContextualRenderedImageFactory readCRIF = new ImageReadCRIF(); // Get the "ImageRead" operation name. String imageReadName = readDescriptor.getName(); // Register the "ImageRead" factory for rendered mode. registry.registerFactory(RenderedRegistryMode.MODE_NAME, imageReadName, productName, readCRIF); // Register the "ImageRead" factory for renderable mode. registry.registerFactory(RenderableRegistryMode.MODE_NAME, imageReadName, productName, readCRIF); // Create and register the "ImageRead" factory for collection mode. registry.registerFactory(CollectionRegistryMode.MODE_NAME, imageReadName, productName, new ImageReadCIF()); // Create the "ImageWrite" descriptor instance. OperationDescriptor writeDescriptor = new ImageWriteDescriptor(); // Register the "ImageWrite" descriptor. registry.registerDescriptor(writeDescriptor); // Create the "ImageWrite" CRIF. ContextualRenderedImageFactory writeCRIF = new ImageWriteCRIF(); // Get the "ImageWrite" operation name. String imageWriteName = writeDescriptor.getName(); // Register the "ImageWrite" factory for rendered mode. registry.registerFactory(RenderedRegistryMode.MODE_NAME, imageWriteName, productName, writeCRIF); // Register the "ImageWrite" factory for renderable mode. registry.registerFactory(RenderableRegistryMode.MODE_NAME, imageWriteName, productName, writeCRIF); // Create and register the "ImageWrite" factory for collection mode. registry.registerFactory(CollectionRegistryMode.MODE_NAME, imageWriteName, productName, new ImageWriteCIF()); } } jai-imageio-core-1.2/src/share/classes/com/sun/media/jai/operator/0000775000175100017510000000000011650556205024060 5ustar tilletillejai-imageio-core-1.2/src/share/classes/com/sun/media/jai/operator/package.html0000664000175100017510000000406510203036165026335 0ustar tilletille Provides JAI operations which read and write images using the Java Image I/O Framework. These operations are plug-ins which are automatically loaded using the javax.media.jai.OperationRegistrySpi mechanism of JAI. @since 1.0 jai-imageio-core-1.2/src/share/classes/com/sun/media/jai/operator/ImageReadDescriptor.java0000664000175100017510000014344310343443200030575 0ustar tilletille/* * $RCSfile: ImageReadDescriptor.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.2 $ * $Date: 2005-12-01 00:40:32 $ * $State: Exp $ */ package com.sun.media.jai.operator; import java.awt.RenderingHints; import java.awt.image.RenderedImage; import java.awt.image.renderable.ContextualRenderedImageFactory; import java.awt.image.renderable.ParameterBlock; import java.awt.image.renderable.RenderableImage; import java.io.File; import java.io.InputStream; import java.net.Socket; import java.util.Collection; import java.util.EventListener; import java.util.Locale; import javax.imageio.ImageReadParam; import javax.imageio.ImageReader; import javax.imageio.stream.ImageInputStream; import javax.media.jai.JAI; import javax.media.jai.OperationDescriptorImpl; import javax.media.jai.OperationRegistry; import javax.media.jai.PropertyGenerator; import javax.media.jai.RenderedOp; import javax.media.jai.RenderableOp; import javax.media.jai.registry.CollectionRegistryMode; import javax.media.jai.registry.RenderableRegistryMode; import javax.media.jai.registry.RenderedRegistryMode; import com.sun.media.jai.util.PropertyGeneratorImpl; /** * An OperationDescriptor describing the "ImageRead" operation. * *

The "ImageRead" operation uses the * Java * Image I/O Framework to read images from an input source. Which formats * may be read depends on which {@link javax.imageio.ImageReader} plug-ins are * registered with the Image I/O Framework when the operation is invoked.

* *

The input source will usually be an * {@link javax.imageio.stream.ImageInputStream}, but may be a * {@link java.io.File}, {@link java.io.RandomAccessFile}, * {@link java.io.InputStream}, {@link java.net.URL}, * {@link java.net.Socket}, {@link java.nio.channels.ReadableByteChannel}, * file path represented as a String or some other type * compatible with a reader plug-in. The * {@link javax.imageio.ImageIO} class should be used to specify the location * and enable the use of cache files via its setCacheDirectory() * and setUseCache() methods, respectively. Note that this cache * pertains to image stream caching and is unrelated to the JAI * TileCache.

* *

The "ImageRead" operation supports rendered, * renderable, and * collection modes and requires no source image. * A {@link java.awt.RenderingHints} object may be supplied when the operation * is created. In addition to the {@link java.awt.RenderingHints.Key} hints * recognized by the eventual OpImage constructor, an * ImageLayout hint may also be * supplied. The settings of this ImageLayout override any other * possible derivation of its components. In particular, it is possible that * the generated image(s) have a different tile layout than that present in * the image read from the input source.

* *

Image properties are used to make available metadata and other * information. Property provision is mode-specific.

* *

* * * * * * * * * * * * * * * * * *
Resource List
Name Value
GlobalName ImageRead
LocalName ImageRead
Vendor com.sun.media.jai
Description Reads an image using the Java Image I/O Framework.
DocURL http://java.sun.com/products/java-media/jai/forDevelopers/jai-imageio-1_0-rc-docs/com/sun/media/jai/operator/ImageReadDescriptor.html
Version 1.0
arg0Desc The input source.
arg1Desc The index or indices of the image(s) to read.
arg2Desc Whether metadata should be read if available.
arg3Desc Whether thumbnails should be read if available.
arg4Desc Whether to verify the validity of the input source.
arg5Desc EventListeners to be registered with the ImageReader.
arg6Desc The Locale for the ImageReader to use.
arg7Desc Java Image I/O read parameter instance.
arg8Desc Java Image I/O reader instance.

* *

Rendered Mode

* * In rendered mode the "ImageRead" operation creates a * {@link java.awt.image.RenderedImage} from the specified input source. * *

Rendered Mode Parameters

* * The parameter list of the "ImageRead" operation in rendered mode is * as in the following table. * *

* * * * * * * * * * * * * * * * * * * * * *
Rendered Mode Parameter List
Name Class TypeDefault Value
* Input java.lang.Object.classNO_PARAMETER_DEFAULT
* ImageChoice java.lang.Integer0
* ReadMetadata java.lang.BooleanTRUE
* ReadThumbnails java.lang.BooleanTRUE
* VerifyInput java.lang.BooleanTRUE
* Listeners java.util.EventListener[]null
* Locale java.util.Localenull
* ReadParam javax.imageio.ImageReadParamnull
* Reader javax.imageio.ImageReadernull

* *

The rendered mode parameters are handled as follows: * *

* *

Parameters and Synchronization Policy

* * Note that any supplied ImageReadParam parameter may be modified within this * operator. Also, any of the various reading methods of the ImageReader may be * invoked at an arbitrary subsequent time to populate the image data. Correct * handling of these parameters at the application level is left to the user. * Specifically no guarantee as to the correct behavior of this operation is * made in the cases wherein a user passes in an ImageReadParam or ImageReader * parameter and modifies its state while this operation is still using these * objects. This applies especially in the case of multi-threaded applications. * In such instances it is recommended that the user either not pass in either * of these parameters or simply use the Java Image I/O API directly rather * than the JAI operation. (Threads managed internally by JAI, e.g., in the * TileScheduler, interact with the image object created by this operation only * via synchronized methods thereby preventing potential race conditions.) * These caveats also apply to the use of ImageReaders and ImageReadParams * obtained from image properties. * *

The foregoing policy regarding modification of any supplied ImageReadParam * or ImageReader is necessary as neither of these classes is cloneable. Given * that as a starting point there are in effect three possibilities: (A) do not * accept them as parameters, (B) accept them via alternate parameters which do * not pose these problems (for example an ImageReaderSpi and a long list of * settings represented by the ImageReadParam), or (C) accept them explicitly. * Option C has been deemed preferable despite the potential race condition * issues.

* *

In the Sun Microsystems implementation of this operation these potential * conflicts have been mitigated to a certain extent: * *

*

* *

ImageLayout Hint Handling

* * If an ImageLayout hint is provided via the operation's RenderingHints, its * values will be used. In particular a SampleModel or ColorModel supplied via * an ImageLayout hint will override any values set via the ImageTypeSpecifier * of the ImageReadParam parameter if the latter is non-null. This signifies * that the ImageTypeSpecifier of the OpImage rendering associated with the * operation node will be forced to match that of the layout even if this type * is different from or incompatible with the image types available from the * ImageReader. Note that in such an eventuality an extra amount of memory * equal to one image tile might be needed for copying purposes. This copying * is handled by the JAI operation itself. * *

Any fields of the supplied ImageLayout which are not set will be set to * default values as follows. The ImageLayout will be cloned before it is * modified.

* *

ImageLayout Defaults

* *

* *

Image Properties in Rendered Mode

* * Image properties are used to provide metadata, thumbnails, and reader-related * information. The following properties may be obtained from the RenderedOp * created for the "ImageRead" operation in rendered mode: * *

* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
Rendered Mode Image Properties
Property NameTypeComment
JAI.ImageReadParamImageReadParamSet to ImageReadParam actually used which may differ from the one passed in.
JAI.ImageReaderImageReaderSet to ImageReader actually used.
JAI.ImageMetadataIIOMetadataSet if and only if ReadMetadata parameter is TRUE and image metadata are available.
JAI.StreamMetadataIIOMetadataSet if and only if ReadMetadata parameter is TRUE and stream metadata are available.
JAI.ThumbnailsBufferedImage[]Set if and only if ReadThumbnails parameter is TRUE and thumbnails are available.

* *

If a given property is not set, this implies of course that the names of * absent properties will not appear in the array returned by getPropertyNames() * and getProperty() invoked to obtain absent properties will return * java.awt.Image.UndefinedProperty as usual.

* *

The ImageReader and ImageReadParam may be used for subsequent invocations * of the operation (for example to obtain different images in a multi-page file) * or for informational purposes. Care should be taken in using these property * values with respect to the synchronization issues previously discussed.

* *

In all cases image metadata properties will be set when the node is rendered, * i.e., metadata reading is not subject to the same deferred execution as is * image data reading. The thumbnail property value will not be set however until * its value is actually requested.

* *

Renderable Mode

* * In renderable mode the "ImageRead" operation creates a * {@link java.awt.image.renderable.RenderableImage} from the specified * input source. * *

It should be noted that although they are discussed in the context of * rendered mode, the parameter synchronization * policy and ImageLayout handling methodology * apply to renderable mode as well.

* *

Renderable Mode Parameters

* * The parameter list of the "ImageRead" operation in renderable mode is * identical to the rendered mode parameter * list mode except as indicated in the following table. * *

* * * * * *
Renderable Mode Parameter Differences
Name Class TypeDefault Value
ImageChoice int[]int[] {0,...,NumImages-1}

* *

In the Sun Microsystems renderable mode implementation of the "ImageRead" * operation, when createRendering() is invoked on the RenderableImage created * by the operation, a MultiResolutionRenderableImage is constructed from a * Vector of RenderedImages consisting of the images at the specified indices. * These images will be sorted into order of decreasing resolution (as * determined by the product of width and height for each image) and inserted * in this order in the Vector of images used to construct the * MultiResolutionRenderableImage. Metadata will be set on the component * RenderedImages as usual for rendered mode. Finally the * createRendering() invocation will be forwarded to the underlying * MultiResolutionRenderableImage and the resulting RenderedImage returned.

* *

Note that using this approach the entire MultiResolutionRenderableImage * must be regenerated for each invocation of createRendering(). If multiple * renderings are to be created from the RenderableImage without changing * the operation parameters, then a more efficient approach would be to use the * "JAI.RenderableInput" property to be described.

* *

Image Properties in Renderable Mode

* * The following property will be set on the RenderableOp created for the * "ImageRead" operation in renderable mode: * *

* * * * * * * * * * * *
Renderable Mode Image Properties
Property NameTypeComment
JAI.RenderableInputRenderableImageA RenderableImage derived from the input source according to the supplied set of parameters.

* *

The RenderableImage which is the value of the foregoing property may have * set on it any of the properties previously described for rendered mode * contingent on parameter settings and data availability. The image metadata * and thumbnail properties would be copied from the highest resolution image * among those specified by the ImageChoice parameter.

* *

If multiple renderings are to be created from the RenderableImage * without changing the operation parameters, then an efficient alternative * approach to multiple invocations of createRendering() on the RenderableImage * is to obtain the RenderableImage value of the "JAI.RenderableInput" property * and invoke createRendering() on this value.

* *

Collection Mode

* * In collection mode the "ImageRead" operation creates a * Collection of RenderedImages from the specified * input source. This could be used for example to load an animated GIF * image or a multi-page TIFF image. * *

It should be noted that although they are discussed in the context of * rendered mode, the parameter synchronization * policy and ImageLayout handling methodology * apply to collection mode as well.

* *

Collection Mode Parameters

* * The parameter list of the "ImageRead" operation in collection mode is * identical to the renderable mode * parameter list. In this case * the RenderedImages loaded for the specified indices will be used to create * a Collection of RenderedImages. The images will be loaded in the order of * the indices in the supplied array and appended to a List. The rendering of * the operation will be a CollectionImage the 'imageCollection' instance * variable of which will be set to this List. * *

Image Properties in Collection Mode

* * Contingent on parameter settings and the presence of the appropriate * metadata, the rendered Collection may have the "JAI.StreamMetadata", * "JAI.ImageReadParam", and "JAI.ImageReader" properties set. Each * RenderedImage in the Collection may contain the * rendered mode properties contingent * on parameter settings and data availability. * * @see javax.media.jai.OperationDescriptor * @see javax.imageio.ImageReader * @see javax.imageio.ImageReadParam * @see javax.imageio.metadata.IIOMetadata * @see javax.imageio.stream.ImageInputStream */ public class ImageReadDescriptor extends OperationDescriptorImpl { // Property name constants have package access for image factory use. /** ImageReadParam property name "JAI.ImageReadParam". */ public static final String PROPERTY_NAME_IMAGE_READ_PARAM = "JAI.ImageReadParam"; /** ImageReader property name "JAI.ImageReader". */ public static final String PROPERTY_NAME_IMAGE_READER = "JAI.ImageReader"; /** Image metadata property name "JAI.ImageMetadata". */ public static final String PROPERTY_NAME_METADATA_IMAGE = "JAI.ImageMetadata"; /** Stream metadata property name "JAI.StreamMetadata". */ public static final String PROPERTY_NAME_METADATA_STREAM = "JAI.StreamMetadata"; /** Thumbnail property name "JAI.Thumbnails". */ public static final String PROPERTY_NAME_THUMBNAILS = "JAI.Thumbnails"; /** * Renderable input property name "JAI.RenderableInput". */ public static final String PROPERTY_NAME_RENDERABLE_INPUT = "JAI.RenderableInput"; /** * Test method. * * @param args {inputFile[, mode]} * @throws Throwable any error. */ /* XXX public static void main(String[] args) { String fileName = args[0]; String modeName = args.length > 1 ? args[1] : RenderedRegistryMode.MODE_NAME; ParameterBlock pb = (new ParameterBlock()).add(new java.io.File(fileName)); java.awt.image.RenderedImage[] images = null; if(modeName.equalsIgnoreCase(RenderedRegistryMode.MODE_NAME)) { images = new java.awt.image.RenderedImage[1]; images[0] = JAI.create("ImageRead", pb, null); PrintProps.print((javax.media.jai.PropertySource)images[0]); } else if(modeName.equalsIgnoreCase(RenderableRegistryMode.MODE_NAME)) { //pb.add(new int[] {0}); java.awt.image.renderable.RenderableImage ri = JAI.createRenderable("ImageRead", pb, null); PrintProps.print((javax.media.jai.PropertySource)ri); images = new java.awt.image.RenderedImage[1]; //java.awt.image.renderable.RenderContext rc = // new java.awt.image.renderable.RenderContext( // new java.awt.geom.AffineTransform(42, 0, 0, 42, 0, 0)); //images[0] = ri.createRendering(rc); images[0] = ri.createDefaultRendering(); PrintProps.print((javax.media.jai.PropertySource)images[0]); } else if(modeName.equalsIgnoreCase(CollectionRegistryMode.MODE_NAME)) { //pb.add(new int[] {0}); java.util.Collection imageCollection = JAI.createCollection("ImageRead", pb, null); PrintProps.print((javax.media.jai.PropertySource)imageCollection); images = new java.awt.image.RenderedImage[imageCollection.size()]; imageCollection.toArray(images); } else { throw new UnsupportedOperationException(modeName+" mode not supported"); } final java.awt.Frame frame = new java.awt.Frame(); frame.addWindowListener(new java.awt.event.WindowAdapter() { public void windowClosing(java.awt.event.WindowEvent e) { frame.setEnabled(false); frame.dispose(); } }); int gridSide = (int)(Math.sqrt(images.length) + 0.5); frame.setLayout(new java.awt.GridLayout(gridSide, gridSide)); java.awt.Dimension screenSize = java.awt.Toolkit.getDefaultToolkit().getScreenSize(); int width = Math.min(screenSize.width/gridSide, images[0].getWidth()); int height = Math.min(screenSize.height/gridSide, images[0].getHeight()); for(int i = 0; i < images.length; i++) { javax.media.jai.widget.ScrollingImagePanel panel = new javax.media.jai.widget.ScrollingImagePanel(images[i], width, //image.getWidth(), height);//image.getHeight()); frame.add(panel); } frame.pack(); frame.show(); } */ /** * The name of the operation. */ private static final String OPERATION_NAME = "ImageRead"; /** * The resource strings that provide the general documentation and * specify the parameter list for the "ImageRead" operation. */ private static final String[][] resources = { {"GlobalName", OPERATION_NAME}, {"LocalName", OPERATION_NAME}, {"Vendor", "com.sun.media.jai"}, {"Description", I18N.getString("ImageReadDescriptor0")}, {"DocURL", "http://java.sun.com/products/java-media/jai/forDevelopers/jai-apidocs/javax/media/jai/operator/ImageReadDescriptor.html"}, {"Version", I18N.getString("DescriptorVersion")}, {"arg0Desc", I18N.getString("ImageReadDescriptor1")}, {"arg1Desc", I18N.getString("ImageReadDescriptor2")}, {"arg2Desc", I18N.getString("ImageReadDescriptor3")}, {"arg3Desc", I18N.getString("ImageReadDescriptor4")}, {"arg4Desc", I18N.getString("ImageReadDescriptor5")}, {"arg5Desc", I18N.getString("ImageReadDescriptor6")}, {"arg6Desc", I18N.getString("ImageReadDescriptor7")}, {"arg7Desc", I18N.getString("ImageReadDescriptor8")}, {"arg8Desc", I18N.getString("ImageReadDescriptor9")} }; /** The parameter names for the "ImageRead" operation. */ private static final String[] paramNames = { "Input", "ImageChoice", "ReadMetadata", "ReadThumbnails", "VerifyInput", "Listeners", "Locale", "ReadParam", "Reader" }; /** The parameter class types for rendered mode of "ImageRead". */ private static final Class[] renderedParamClasses = { java.lang.Object.class, // Input java.lang.Integer.class, // ImageChoice java.lang.Boolean.class, // ReadMetadata java.lang.Boolean.class, // ReadThumbnails java.lang.Boolean.class, // VerifyInput java.util.EventListener[].class, // Listeners java.util.Locale.class, // Locale javax.imageio.ImageReadParam.class, // ReadParam javax.imageio.ImageReader.class // Reader }; /** The parameter default values for rendered mode of "ImageRead". */ private static final Object[] renderedParamDefaults = { NO_PARAMETER_DEFAULT, // Input new Integer(0), // ImageChoice Boolean.TRUE, // ReadMetadata Boolean.TRUE, // ReadThumbnails Boolean.TRUE, // VerifyInput null, // Listeners null, // Locale null, // ReadParam null // Reader }; /** The parameter class types for renderable mode of "ImageRead". */ private static final Class[] renderableParamClasses = { java.lang.Object.class, // Input int[].class, // ImageChoice java.lang.Boolean.class, // ReadMetadata java.lang.Boolean.class, // ReadThumbnails java.lang.Boolean.class, // VerifyInput java.util.EventListener[].class, // Listeners java.util.Locale.class, // Locale javax.imageio.ImageReadParam.class, // ReadParam javax.imageio.ImageReader.class // Reader }; /** The parameter default values for renderable mode of "ImageRead". */ private static final Object[] renderableParamDefaults = { NO_PARAMETER_DEFAULT, // Input null, // ImageChoice Boolean.TRUE, // ReadMetadata Boolean.TRUE, // ReadThumbnails Boolean.TRUE, // VerifyInput null, // Listeners null, // Locale null, // ReadParam null // Reader }; /** The parameter class types for collection mode of "ImageRead". */ private static final Class[] collectionParamClasses = renderableParamClasses; /** The parameter default values for collection mode of "ImageRead". */ private static final Object[] collectionParamDefaults = renderableParamDefaults; /** Constructor. */ public ImageReadDescriptor() { super(resources, new String[] {RenderedRegistryMode.MODE_NAME, RenderableRegistryMode.MODE_NAME, CollectionRegistryMode.MODE_NAME}, null, // sourceNames new Class[][] {null, null, null}, // sourceClasses paramNames, new Class[][] {renderedParamClasses, renderableParamClasses, collectionParamClasses}, new Object[][] {renderedParamDefaults, renderableParamDefaults, collectionParamDefaults}, new Object[][] {null, null, null}); // validParamValues } /** * Type-safe convenience method for creating a {@link RenderedOp} * representing the "ImageRead" operation in rendered mode. The * method packs the parameters into a new ParameterBlock * and invokes {@link JAI#create(String,ParameterBlock,RenderingHints)}. * * @param input The input source. * @param imageChoice The index of the image to read. * @param readMetadata Whether metadata should be read if available. * @param readThumbnails Whether thumbnails should be read if available. * @param verifyInput Whether to verify the validity of the input source. * @param listeners EventListeners to be registered with the ImageReader. * @param locale The Locale for the ImageReader to use. * @param readParam Java Image I/O read parameter instance. * @param reader Java Image I/O reader instance. * @param hints Hints possibly including an ImageLayout. * @return an image derived from the input source. */ public static RenderedOp create(ImageInputStream input, Integer imageChoice, Boolean readMetadata, Boolean readThumbnails, Boolean verifyInput, EventListener[] listeners, Locale locale, ImageReadParam readParam, ImageReader reader, RenderingHints hints) { ParameterBlock args = new ParameterBlock(); args.add(input); args.add(imageChoice); args.add(readMetadata); args.add(readThumbnails); args.add(verifyInput); args.add(listeners); args.add(locale); args.add(readParam); args.add(reader); return JAI.create(OPERATION_NAME, args, hints); } /** * Type-safe convenience method for creating a {@link Collection} * representing the "ImageRead" operation in collection mode. The * method packs the parameters into a new ParameterBlock * and invokes * {@link JAI#createCollection(String,ParameterBlock, RenderingHints)}. * * @param input The input source. * @param imageChoice The indices of the images to read. * @param readMetadata Whether metadata should be read if available. * @param readThumbnails Whether thumbnails should be read if available. * @param verifyInput Whether to verify the validity of the input source. * @param listeners EventListeners to be registered with the ImageReader. * @param locale The Locale for the ImageReader to use. * @param readParam Java Image I/O read parameter instance. * @param reader Java Image I/O reader instance. * @param hints Hints possibly including an ImageLayout. * @return a collection of images derived from the input source. */ public static Collection createCollection(ImageInputStream input, int[] imageChoice, Boolean readMetadata, Boolean readThumbnails, Boolean verifyInput, EventListener[] listeners, Locale locale, ImageReadParam readParam, ImageReader reader, RenderingHints hints) { ParameterBlock args = new ParameterBlock(); args.add(input); args.add(imageChoice); args.add(readMetadata); args.add(readThumbnails); args.add(verifyInput); args.add(listeners); args.add(locale); args.add(readParam); args.add(reader); return JAI.createCollection(OPERATION_NAME, args, hints); } /** * Type-safe convenience method for creating a {@link RenderableOp} * representing the "ImageRead" operation in renderable mode. The * method packs the parameters into a new ParameterBlock * and invokes * {@link JAI#createRenderable(String,ParameterBlock,RenderingHints)}. * * @param input The input source. * @param imageChoice The indices of the images to read. * @param readMetadata Whether metadata should be read if available. * @param readThumbnails Whether thumbnails should be read if available. * @param verifyInput Whether to verify the validity of the input source. * @param listeners EventListeners to be registered with the ImageReader. * @param locale The Locale for the ImageReader to use. * @param readParam Java Image I/O read parameter instance. * @param reader Java Image I/O reader instance. * @param hints Hints possibly including an ImageLayout. * @return an image capable of rendering an image from those in the * input source. */ public static RenderableOp createRenderable(ImageInputStream input, int[] imageChoice, Boolean readMetadata, Boolean readThumbnails, Boolean verifyInput, EventListener[] listeners, Locale locale, ImageReadParam readParam, ImageReader reader, RenderingHints hints) { ParameterBlock args = new ParameterBlock(); args.add(input); args.add(imageChoice); args.add(readMetadata); args.add(readThumbnails); args.add(verifyInput); args.add(listeners); args.add(locale); args.add(readParam); args.add(reader); return JAI.createRenderable(OPERATION_NAME, args, hints); } /** * Returns the array of {@link PropertyGenerator}s for the specified * mode of this operation. * *

For renderable mode returns an array containing a single * PropertyGenerator which defines a * {@link RenderableImage}-valued property named "JAI.RenderableInput". * For all other modes null is returned.

* * @param modeName The name of the mode. * @return An array containing a single PropertyGenerator * if modeName is "renderable" (case-insensitive) or * null otherwise. */ public PropertyGenerator[] getPropertyGenerators(String modeName) { return modeName.equalsIgnoreCase(RenderableRegistryMode.MODE_NAME) ? new PropertyGenerator[] { new ImageReadPropertyGenerator() } : null; } /** * Validates the parameters in the supplied ParameterBlock. * *

In addition to the standard validation performed by the * corresponding superclass method, this method verifies the following: *

* * If the superclass method finds that the arguments are invalid, or if * this method determines that any of the foregoing conditions is true, * an error message will be appended to msg and * false will be returned; otherwise true will * be returned.

* *

The file existence and readability verification may be suppressed * by setting the VerifyInput parameter to FALSE. * This might be desirable for example if the operation is being * created for remote rendering and Input is a file which is at * a location visible on the remote peer but not on the host on which * the operation is created.

* * @param modeName The operation mode. * @param args The source and parameters of the operation. * @param msg A container for any error messages. * * @return Whether the supplied parameters are valid. */ protected boolean validateParameters(String modeName, ParameterBlock args, StringBuffer msg) { if (!super.validateParameters(modeName, args, msg)) { return false; } // Check "ImageChoice" for negative value(s). if(modeName.equalsIgnoreCase(RenderedRegistryMode.MODE_NAME)) { if(args.getIntParameter(1) < 0) { msg.append(I18N.getString("ImageReadDescriptor10")); return false; } } else { // Non-rendered modes. int[] imageIndices = (int[])args.getObjectParameter(1); if(imageIndices != null) { for(int i = 0; i < imageIndices.length; i++) { if(imageIndices[i] < 0) { msg.append(I18N.getString("ImageReadDescriptor10")); return false; } } } } // Check the input if so requested by "VerifyInput". Boolean verifyInput = (Boolean)args.getObjectParameter(4); if (verifyInput.booleanValue()){ // Get the Input parameter. Object input = args.getObjectParameter(0); if(input instanceof File || input instanceof String) { // Set file and path variables. File file = null; String path = null; if(input instanceof File) { file = (File)input; path = file.getPath(); } else if(input instanceof String) { path = (String)input; file = new File(path); } // If input is a verify that it exists and is readable. if(file != null) { if (!file.exists()) { // Check if the file is accessible as an InputStream // resource. This would be the case if the application // and the image file are packaged in a JAR file InputStream is = getClass().getClassLoader().getResourceAsStream((String)input); if(is == null) { msg.append("\"" + path + "\": " + I18N.getString("ImageReadDescriptor11")); return false; } } else if (!file.canRead()) { msg.append("\"" + path + "\": " + I18N.getString("ImageReadDescriptor12")); return false; } } } else if(input instanceof Socket) { Socket socket = (Socket)input; if(socket.isInputShutdown()) { msg.append("\"" + socket + "\": " + I18N.getString("ImageReadDescriptor13")); return false; } else if(socket.isClosed()) { msg.append("\"" + socket + "\": " + I18N.getString("ImageReadDescriptor14")); return false; } else if(!socket.isBound()) { msg.append("\"" + socket + "\": " + I18N.getString("ImageReadDescriptor15")); return false; } else if(!socket.isConnected()) { msg.append("\"" + socket + "\": " + I18N.getString("ImageReadDescriptor16")); return false; } } } return true; } } // XXX Does this need to return ImageReader and ReadParam props also? // XXX This same property needs to be set also on each rendering so that // copying does not occur and require more computation. final class ImageReadPropertyGenerator extends PropertyGeneratorImpl { /** Constructor. */ ImageReadPropertyGenerator() { super(new String[] { ImageReadDescriptor.PROPERTY_NAME_RENDERABLE_INPUT}, new Class[] {RenderableImage.class}, new Class[] {RenderableOp.class}); } /** * Returns the specified property in the renderable layer. * * @param name Property name. * @param opNode Operation node. */ public Object getProperty(String name, Object opNode) { // Check arguments. validate(name, opNode); // Default to undefined value. Object value = java.awt.Image.UndefinedProperty; if(opNode instanceof RenderableOp && name.equalsIgnoreCase( ImageReadDescriptor.PROPERTY_NAME_RENDERABLE_INPUT)) { // Save the node reference and get the hints. RenderableOp node = (RenderableOp)opNode; RenderingHints hints = node.getRenderingHints(); // Get the CRIF for "ImageRead". OperationRegistry registry = null; ContextualRenderedImageFactory crif = null; // Try to get the CRIF from a registry specified in the hints. if(hints != null && hints.containsKey(JAI.KEY_OPERATION_REGISTRY)) { registry = (OperationRegistry)hints.get(JAI.KEY_OPERATION_REGISTRY); crif = (ContextualRenderedImageFactory)registry.getFactory( RenderableRegistryMode.MODE_NAME, "ImageRead"); } // If no registry in the hints or that registry does not contain // a CRIF for "ImageRead", try to get it from the default registry. if(crif == null) { registry = JAI.getDefaultInstance().getOperationRegistry(); crif = (ContextualRenderedImageFactory)registry.getFactory( RenderableRegistryMode.MODE_NAME, "ImageRead"); } // Create the RenderableImage and set the property value to it. if(crif != null && crif instanceof com.sun.media.jai.imageioimpl.ImageReadCRIF) { value = ((com.sun.media.jai.imageioimpl.ImageReadCRIF)crif).createRenderable( node.getParameterBlock(), hints); } } return value; } } jai-imageio-core-1.2/src/share/classes/com/sun/media/jai/operator/ImageWriteDescriptor.java0000664000175100017510000017271010203036165031016 0ustar tilletille/* * $RCSfile: ImageWriteDescriptor.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.1 $ * $Date: 2005-02-11 05:01:56 $ * $State: Exp $ */ package com.sun.media.jai.operator; import java.awt.Dimension; import java.awt.RenderingHints; import java.awt.image.BufferedImage; import java.awt.image.RenderedImage; import java.awt.image.renderable.ParameterBlock; import java.awt.image.renderable.RenderableImage; import java.io.File; import java.io.IOException; import java.net.Socket; import java.util.Collection; import java.util.EventListener; import java.util.Iterator; import java.util.Locale; import javax.imageio.ImageIO; import javax.imageio.ImageWriteParam; import javax.imageio.ImageWriter; import javax.imageio.metadata.IIOMetadata; import javax.imageio.spi.ImageWriterSpi; import javax.imageio.stream.ImageOutputStream; import javax.media.jai.CollectionOp; import javax.media.jai.JAI; import javax.media.jai.OperationDescriptorImpl; import javax.media.jai.RenderableOp; import javax.media.jai.RenderedOp; import javax.media.jai.registry.CollectionRegistryMode; import javax.media.jai.registry.RenderableRegistryMode; import javax.media.jai.registry.RenderedRegistryMode; /** * An OperationDescriptor describing the "ImageWrite" operation. * *

The "ImageWrite" operation uses the * Java * Image I/O Framework to write images to an output destination. Which * formats may be written depends on which {@link javax.imageio.ImageWriter} * plug-ins are registered with the Image I/O Framework when the operation is * invoked.

* *

The output destination will usually be an * {@link javax.imageio.stream.ImageOutputStream}, but may be a * {@link java.io.File}, {@link java.io.RandomAccessFile}, * {@link java.io.OutputStream}, {@link java.net.Socket}, * {@link java.nio.channels.WritableByteChannel}, file path represented as a * String or some other type compatible with a writer plug-in. The * {@link javax.imageio.ImageIO} class should be used to specify the location * and enable the use of cache files via its setCacheDirectory() * and setUseCache() methods, respectively. Note that this cache * pertains to image stream caching and is unrelated to the JAI * TileCache. If an {@link javax.imageio.stream.ImageOutputStream} * is created internally by the operation, for example from a * {@link java.io.File}-valued Output parameter, * then it will be flushed automatically if and only if the operation is not * in collection mode and pixel replacement is * not occurring.

* *

The "ImageWrite" operation supports rendered, * renderable, and * collection modes and requires a single * source. The operation is "immediate" for all modes as specified by * OperationDescriptor.isImmediate() so that * {@link #isImmediate()} returns true. The operation will * therefore be rendered when created via either JAI.create[NS]() * or JAI.createCollection[NS](). * A {@link java.awt.RenderingHints} object supplied when the * operation is created will have no effect except with respect to the * mapping of JAI.KEY_INTERPOLATION and then only in renderable * mode.

* *

Image properties are used to pass metadata and other information to the * writer plug-in and to make available metadata as actually written to the * output destination. Property handling is mode-specific.

* *

* * * * * * * * * * * * * * * * * * * * * * *
Resource List
Name Value
GlobalName ImageWrite
LocalName ImageWrite
Vendor com.sun.media.jai
Description Writes an image using the Java Image I/O Framework.
DocURL http://java.sun.com/products/java-media/jai/forDevelopers/jai-imageio-1_0-rc-docs/com/sun/media/jai/operator/ImageWriteDescriptor.html
Version 1.0
arg0Desc The output destination.
arg1Desc The format name of the output.
arg2Desc Whether to use image metadata properties as fallbacks.
arg3Desc Whether to transcode metadata before writing.
arg4Desc Whether to verify the validity of the output destination.
arg5Desc Whether to allow pixel replacement in the output image.
arg6Desc The tile size of the output image.
arg7Desc Stream metadata to write to the output.
arg8Desc Image metadata to write to the output.
arg9Desc Thumbnails to write to the output.
arg10Desc EventListeners to be registered with the ImageWriter.
arg11Desc The Locale for the ImageWriter to use.
arg12Desc Java Image I/O write parameter instance.
arg13Desc Java Image I/O writer instance.

* *

Rendered Mode

* * In rendered mode the "ImageWrite" operation writes a * {@link java.awt.image.RenderedImage} to the specified output destination. * *

Rendered Mode Parameters

* * The parameter list of the "ImageWrite" operation in rendered mode is * as in the following table. * *

* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
Rendered Mode Parameter List
Name Class TypeDefault Value
* Output java.lang.Object.classNO_PARAMETER_DEFAULT
* Format java.lang.Stringnull
* UseProperties java.lang.BooleanTRUE
* Transcode java.lang.BooleanTRUE
* VerifyOutput java.lang.BooleanTRUE
* AllowPixelReplacement java.lang.BooleanFALSE
* TileSize java.awt.Dimensionnull
* StreamMetadata javax.imageio.metadata.IIOMetadatanull
* ImageMetadata javax.imageio.metadata.IIOMetadatanull
* Thumbnails java.awt.BufferedImage[]null
* Listeners java.util.EventListener[]null
* Locale java.util.Localenull
* WriteParam javax.imageio.ImageWriteParamnull
* Writer javax.imageio.ImageWriternull

* *

The rendered mode parameters are handled as follows: * *

*

* *

Parameters and Synchronization Policy

* * Similarly to the case of any ImageReadParam or ImageReader supplied to the * "ImageRead" operation, any ImageWriteParam or ImageWriter supplied to the * "ImageWrite" operation is subject to modification within the operation * classes. A policy similar to the * "ImageRead" * synchronization policy therefore applies as well for "ImageWrite". * *

In the Sun Microsystems implementation of this operation these potential * conflicts have been mitigated to a certain extent: * *

*

* *

Tiling

* * The following algorithm is used to determine the tile size of the * image written to the output destination: * *
 * if ImageWriter cannot write tiles
 *    output is untiled
 * else
 *    if TileSize parameter is non-null
 *       set tile size to TileSize
 *    else
 *       if WriteParam is null
 *          set tile size to source tile size
 *       else
 *          if tilingMode is ImageWriteParam.MODE_EXPLICIT
 *             if tile dimension is set in WriteParam
 *                set tile size to tile dimension from WriteParam
 *             else
 *                if preferred tile dimension is set in WriteParam
 * 		  set tile size to average of first two preferred dimensions
 *                else
 *                   set tile size to source tile size
 *          else // tilingMode is not ImageWriteParam.MODE_EXPLICIT
 *             the plug-in decides the tile size
 * 
* * There is no mechanism to set the tile grid offsets of the output. * *

Pixel Replacement

* * If AllowPixelReplacement is TRUE, the ImageWriter can replace pixels, and * the source is a PlanarImage, then the rendering of the operation * will respond to RenderingChangeEvents and Shape-valued PropertyChangeEvents * named "InvalidRegion". The rendering will be automatically registered as * a sink of the rendering of the operation node's source. As the source * rendering does not usually generate events, the calling code must also * explicitly register the "ImageWrite" rendering as a sink of the source * node. By whatever means the event is generated, when the rendering * receives such an event, it will determine the indices of all tiles which * overlap the invalid region and will replace the pixels of all these tiles * in the output. * *

Note that this behavior differs from what would happen if the RenderedOp * created by the operation received a RenderingChangeEvent: in this case a * new rendering of the node would be created using the ParameterBlock and * RenderingHints currently in effect. This would cause the entire image to be * rewritten at the current position of the output. This will also happen * when AllowPixelReplacement is FALSE. In effect in both of these cases the * behavior in response to a RenderingChangeEvent is unspecified and the result * will likely be unexpected.

* *

To avoid any inadvertent overwriting of the destination as a result of * events received by the RenderedOp, the following usage is recommended when * the objective is automatic pixel replacement: * *

 *        // Sources, parameters, and hints.
 *        ParameterBlock args;
 *        RenderingHints hints;
 * 
 *        // Create the OperationNode.
 *        RenderedOp imageWriteNode = JAI.create("ImageWrite", args, hints);
 * 
 *        // Get the rendering which already exists due to "immediate" status.
 *        RenderedImage imageWriteRendering = imageWriteNode.getRendering();
 * 
 *        // Unhook the OperationNode as a sink of its source OperationNode.
 *        imageWriteNode.getSourceImage(0).removeSink(imageWriteNode);
 *
 *        // Add the rendering as a sink of the source OperationNode.
 *        imageWriteNode.getSourceImage(0).addSink(imageWriteRendering);
 * 
 *        // Free the OperationNode for garbage collection.
 *        imageWriteNode = null;
 * 
* * At this point a reference to imageWriteRendering must be held as long as the * data of the source of the operation may change. Then provided the events are * correctly propagated to imageWriteRendering, the data in the output file * will be automatically updated to match the source data.

* *

If pixel replacement is not the objective and inadvertent overwriting is * to be avoided then the safest approach would be the following: * *

 *        // Create the OperationNode.
 *        RenderedOp imageWriteNode = JAI.create("ImageWrite", args, hints);
 * 
 *        // Unhook the OperationNode as a sink of its source
 *        imageWriteNode.getSourceImage(0).removeSink(imageWriteNode);
 * 
* * The image is written by the first statement and no reference to the * rendering need be retained as before. * *

Image Properties in Rendered Mode

* * Image properties are used for metadata, thumbnails, and writer-related * information. The following properties may be set on the RenderedOp created * for the "ImageWrite" operation in rendered mode: * *

* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
Rendered Mode Image Properties
Property NameTypeComment
JAI.ImageWriteParamImageWriteParamSet to ImageWriteParam actually used which may differ from the one passed in.
JAI.ImageWriterImageWriterSet to ImageWriter actually used.
JAI.ImageMetadataIIOMetadataSet if and only if image metadata are available; may be transcoded.
JAI.StreamMetadataIIOMetadataSet if and only if stream metadata are available; may be transcoded.
JAI.ThumbnailsBufferedImage[]Set if and only thumbnails are provided and the writer supportes writing them.

* *

If a given property is not set, this implies of course that the names of * absent properties will not appear in the array returned by getPropertyNames() * and getProperty() invoked to obtain absent properties will return * java.awt.Image.UndefinedProperty as usual.

* *

The ImageWriter and ImageWriteParam may be used for subsequent invocations * of the operation or for informational purposes. Care should be taken in using * these property values with respect to the synchronization issues previously * discussed.

* *

Metadata properties will be set to those actually written to the output. They * may be derived either from input parameters or source properties depending on * the values of the StreamMetadata, ImageMetadata, and UseProperties parameters. * They will be transcoded data if Transcode is TRUE and the ImageWriter supports * transcoding.

* *

All properties will be set when the node is rendered.

* *

Renderable Mode

* * In renderable mode the "ImageWrite" operation requires a * {@link java.awt.image.renderable.RenderableImage} source and writes a * {@link java.awt.image.RenderedImage} to the specified output destination. * As the "immediate" designation specified by {@link #isImmediate()} * has no effect in renderable mode, no image will be written without further * action by the calling code. To write an image, createRendering(), * createScaledRendering(), or createDefaultRendering() * must be invoked. Each of these will create a RenderedImage by forwarding the * createRendering() or equivalent call to the source image. The resulting * RenderedImage will be written to the output according to the * rendered mode operation of "ImageWrite". * If a mapping of JAI.KEY_INTERPOLATION is supplied via a * RenderingHints passed to the operation, then the interpolation * type it specifies will be used to create the rendering if interpolation is * required. * *

Renderable Mode Parameters

* * The parameter list of the "ImageRead" operation in renderable mode is * identical to the rendered mode * parameter list. * *

Pixel Replacement in Renderable Mode

* * Pixel replacement pertains only to RenderedImages generated by rendering the * RenderableOp. It may occur if the same conditions apply as described for * pixel replacement in rendered mode. Due to the unspecified nature of the * underlying rendered sources of any rendering, this is not a recommended * procedure. * *

Image Properties in Renderable Mode

* * The RenderableOp node itself does not have any ImageWrite-related * properties. Any RenderedImages created by rendering the RenderableOp * (thereby writing an image to the output as described), may have * rendered mode properties set. * *

Collection Mode

* * In collection mode the "ImageWrite" operation requires a * {@link java.util.Collection} source and writes its contents to the * specified output destination. * *

The Collection is treated as a sequence of images which will be * extracted from the Collection in the order returned by a new Iterator. * Elements in the Collection which are not RenderedImages will be ignored. * The derived sequence of images will then be written to the output.

* *

If there is only one RenderedImage in the source Collection, this image * will be written as done in rendered mode operation. If there is more than * one RenderedImage, the sequence of RenderedImages will be written as an * image sequence. In the latter case the ImageWriter must be able to write * sequences.

* *

Collection Mode Parameters

* * Identical parameter list to rendered mode except: * *

* * * * * * * *
Collection Mode Parameter Differences
Name Class TypeDefault Value
ImageMetadata javax.imageio.metadataIIOMetadata[]null
Thumbnails java.awt.image.BufferedImage[][]null

* * * *

* The change to the ImageMetadata and Thumbnails parameters is that there can * now be a distinct image metadata object and thumbnail array for each image * in the Collection. The components of these respective arrays will be indexed * using the sequence of RenderedImages extracted from the source Collection by * the Iterator. It is the responsibility of the caller to ensure that this * sequencing is correct. In this context it is advisable to use a source * Collection which maintains the order of its elements such as a List. *

* *

Pixel Replacement in Collection Mode

* * If the value of the AllowPixelReplacement parameter is TRUE, then the * rendered Collection will contain RenderedImages which are registered as * listeners of their respective sources. Each image in the rendered Collection * will however be a rendering as opposed to a RenderedOp. This obviates the * need to unhook such a RenderedOp from its source as suggested. Two actions * on the part of the application are however necessary in this case: 1) the * sequence must be manually ended, and 2) the Collection node must be removed * as a sink of its source Collection. The first action is necessary as * pixels may be replaced at various times in various images in the sequence * and it is not possible to terminate the sequence at rendering time, and there * is no reliable mechanism to detect programmatically when this may later be * effected. The second action is necessary because a CollectionChangeEvent * received by the Collection node would cause the node to be re-rendered, i.e., * the collection data to be rewritten using the current state of all parameters. * This will in fact also happen when AllowPixelReplacement is FALSE. In effect * in both of these cases the behavior in response to a CollectionChangeEvent * is unspecified and the result will likely be unexpected. * *

* To ensure proper termination of the image sequence and avoid any inadvertent * overwriting of the destination as a result of events received by the * CollectionOp, the following usage is recommended when the objective is * automatic pixel replacement: * *

 *        // Sources, parameters, and hints.
 *        ParameterBlock args;
 *        RenderingHints hints;
 * 
 *        // Create the Collection.
 *        CollectionImage imageWriteCollection =
 *            (CollectionImage)JAI.createCollection("ImageWrite", args, hints);
 * 
 *        // Unhook the Collection node from the source to avoid
 *        // re-renderings caused by CollectionChangeEvents.
 *        if(args.getSource(0) instanceof CollectionImage) {
 *            CollectionImage sourceCollection =
 * 	       (CollectionImage)args.getSource(0);
 *            sourceCollection.removeSink(imageWriteCollection);
 *        }
 * 
 *        // !!! Pixel replacement activity happens here ... !!!
 * 
 *        // Get the ImageWriter.
 *        ImageWriter writer =
 *            (ImageWriter)imageWriteCollection.getProperty("JAI.ImageWriter");
 * 
 *        // End the sequence if necessary.
 *        if(writer.canWriteSequence()) {
 *            writer.endWriteSequence();
 *        }
 * 
*

* *

* Using the foregoing construct, all pixels in all images written to the output * sequence will remain current with the in-memory data of their respective * source provided all events are propagated as expected. Note that it is not * necessary to end the sequence manually if pixel replacement is not allowed or * is not supported. Also the sequence must be manually ended if and only if the * writer is capable of writing sequences. This permits pixel replacement to * work in the case where the source collection contains only a single image * and the writer supports pixel replacement but cannot write sequences. *

* *

* If pixel replacement is not the objective, i.e., AllowPixelReplacement is * FALSE, and inadvertent overwriting is to be avoided then the safest approach * would be the following: * *

 *        // Create the Collection.
 *        Collection imageWriteCollection =
 *            JAI.create("ImageWrite", args, hints);
 * 
 *        // Unhook the Collection node from the source to avoid
 *        // re-renderings caused by CollectionChangeEvents.
 *        if(args.getSource(0) instanceof CollectionImage) {
 *            CollectionImage sourceCollection =
 * 	       (CollectionImage)args.getSource(0);
 *            sourceCollection.removeSink(imageWriteCollection);
 *        }
 * 
* * The image is written by the first statement and no reference to the * rendering need be retained.

* *

Image Properties in Collection Mode

* * Contingent on parameter settings and the presence of the appropriate * metadata, the rendered Collection may have the "JAI.StreamMetadata", * "JAI.ImageReadParam", and "JAI.ImageReader" properties set. Each * RenderedImage in the Collection may contain *
rendered mode properties * contingent on parameter settings and data availability. Metadata * properties may be transcoded. * * @see javax.media.jai.OperationDescriptor * @see javax.imageio.ImageWriter * @see javax.imageio.ImageWriteParam * @see javax.imageio.metadata.IIOMetadata * @see javax.imageio.stream.ImageOutputStream */ public class ImageWriteDescriptor extends OperationDescriptorImpl { // Property name constants have package access for image factory use. /** ImageWriteParam property name "JAI.ImageWriteParam". */ public static final String PROPERTY_NAME_IMAGE_WRITE_PARAM = "JAI.ImageWriteParam"; /** ImageWriter property name "JAI.ImageWriter". */ public static final String PROPERTY_NAME_IMAGE_WRITER = "JAI.ImageWriter"; /** * Image metadata property name. Set to same value as * {@link ImageReadDescriptor#PROPERTY_NAME_METADATA_IMAGE}. */ public static final String PROPERTY_NAME_METADATA_IMAGE = ImageReadDescriptor.PROPERTY_NAME_METADATA_IMAGE; /** * Stream metadata property name. Set to same value as * {@link ImageReadDescriptor#PROPERTY_NAME_METADATA_STREAM}. */ public static final String PROPERTY_NAME_METADATA_STREAM = ImageReadDescriptor.PROPERTY_NAME_METADATA_STREAM; /** * Thumbnail property name. Set to same value as * {@link ImageReadDescriptor#PROPERTY_NAME_THUMBNAILS}. */ public static final String PROPERTY_NAME_THUMBNAILS = ImageReadDescriptor.PROPERTY_NAME_THUMBNAILS; /** * Test method. * * @param args {inputFile, outputFile [, mode]} * @throws Throwable any error. */ /* XXX public static void main(String[] args) throws Throwable { String inputFile = args[0]; String outputFile = args[1]; String modeName = args.length > 2 ? args[2] : RenderedRegistryMode.MODE_NAME; String formatName = args.length > 3 ? args[3] : null; ParameterBlock pb = new ParameterBlock(); pb.set(new java.io.File(outputFile), 0); if(formatName != null) { pb.set(formatName, 1); } java.awt.image.RenderedImage[] images = null; if(modeName.equalsIgnoreCase(RenderedRegistryMode.MODE_NAME)) { pb.addSource(ImageIO.read(new java.io.File(inputFile))); images = new java.awt.image.RenderedImage[1]; pb.set(new Dimension(128, 128), 6); images[0] = JAI.create("ImageWrite", pb, null); PrintProps.print((javax.media.jai.PropertySource)images[0]); } else if(modeName.equalsIgnoreCase(RenderableRegistryMode.MODE_NAME)) { ParameterBlock renderablePB = new ParameterBlock(); renderablePB.addSource(ImageIO.read(new java.io.File(inputFile))); pb.addSource(javax.media.jai.JAI.createRenderable("renderable", renderablePB)); java.awt.image.renderable.RenderableImage ri = JAI.createRenderable("ImageWrite", pb, null); PrintProps.print((javax.media.jai.PropertySource)ri); images = new java.awt.image.RenderedImage[1]; //java.awt.image.renderable.RenderContext rc = // new java.awt.image.renderable.RenderContext( // new java.awt.geom.AffineTransform(42, 0, 0, 42, 0, 0)); //images[0] = ri.createRendering(rc); images[0] = ri.createDefaultRendering(); PrintProps.print((javax.media.jai.PropertySource)images[0]); } else if(modeName.equalsIgnoreCase(CollectionRegistryMode.MODE_NAME)) { java.util.ArrayList sourceCollection = new java.util.ArrayList(); Object input = ImageIO.createImageInputStream(new java.io.File(inputFile)); javax.imageio.ImageReader reader = (javax.imageio.ImageReader)ImageIO.getImageReaders(input).next(); reader.setInput(input); int imageIndex = 0; do { try { RenderedImage nextImage = reader.read(imageIndex); sourceCollection.add(nextImage); } catch(IndexOutOfBoundsException e) { break; } imageIndex++; } while(true); pb.addSource(sourceCollection); java.util.Collection imageCollection = JAI.createCollection("ImageWrite", pb, null); PrintProps.print((javax.media.jai.PropertySource)imageCollection); images = new java.awt.image.RenderedImage[imageCollection.size()]; imageCollection.toArray(images); } else { throw new UnsupportedOperationException(modeName+" mode not supported"); } final java.awt.Frame frame = new java.awt.Frame(); frame.addWindowListener(new java.awt.event.WindowAdapter() { public void windowClosing(java.awt.event.WindowEvent e) { frame.setEnabled(false); frame.dispose(); } }); int gridSide = (int)(Math.sqrt(images.length) + 0.5); frame.setLayout(new java.awt.GridLayout(gridSide, gridSide)); java.awt.Dimension screenSize = java.awt.Toolkit.getDefaultToolkit().getScreenSize(); int width = Math.min(screenSize.width/gridSide, images[0].getWidth()); int height = Math.min(screenSize.height/gridSide, images[0].getHeight()); for(int i = 0; i < images.length; i++) { javax.media.jai.widget.ScrollingImagePanel panel = new javax.media.jai.widget.ScrollingImagePanel(images[i], width, //image.getWidth(), height);//image.getHeight()); frame.add(panel); } frame.pack(); frame.show(); } */ /** * The name of the operation. */ private static final String OPERATION_NAME = "ImageWrite"; /** * The resource strings that provide the general documentation and * specify the parameter list for the "ImageWrite" operation. */ private static final String[][] resources = { {"GlobalName", "ImageWrite"}, {"LocalName", "ImageWrite"}, {"Vendor", "com.sun.media.jai"}, {"Description", I18N.getString("ImageWriteDescriptor0")}, {"DocURL", "http://java.sun.com/products/java-media/jai/forDevelopers/jai-apidocs/javax/media/jai/operator/ImageWriteDescriptor.html"}, {"Version", I18N.getString("DescriptorVersion")}, {"arg0Desc", I18N.getString("ImageWriteDescriptor1")}, {"arg1Desc", I18N.getString("ImageWriteDescriptor2")}, {"arg2Desc", I18N.getString("ImageWriteDescriptor3")}, {"arg3Desc", I18N.getString("ImageWriteDescriptor4")}, {"arg4Desc", I18N.getString("ImageWriteDescriptor5")}, {"arg5Desc", I18N.getString("ImageWriteDescriptor6")}, {"arg6Desc", I18N.getString("ImageWriteDescriptor7")}, {"arg7Desc", I18N.getString("ImageWriteDescriptor8")}, {"arg8Desc", I18N.getString("ImageWriteDescriptor9")}, {"arg9Desc", I18N.getString("ImageWriteDescriptor10")}, {"arg10Desc", I18N.getString("ImageWriteDescriptor11")}, {"arg11Desc", I18N.getString("ImageWriteDescriptor12")}, {"arg12Desc", I18N.getString("ImageWriteDescriptor13")}, {"arg13Desc", I18N.getString("ImageWriteDescriptor14")} }; /** The parameter names for the "ImageWrite" operation. */ private static final String[] paramNames = { "Output", "Format", "UseProperties", "Transcode", "VerifyOutput", "AllowPixelReplacement", "TileSize", "StreamMetadata", "ImageMetadata", "Thumbnails", "Listeners", "Locale", "WriteParam", "Writer" }; /** The parameter class types for rendered mode of "ImageWrite". */ private static final Class[] renderedParamClasses = { java.lang.Object.class, // Output java.lang.String.class, // Format java.lang.Boolean.class, // UseProperties java.lang.Boolean.class, // Transcode java.lang.Boolean.class, // VerifyOutput java.lang.Boolean.class, // AllowPixelReplacement java.awt.Dimension.class, // TileSize javax.imageio.metadata.IIOMetadata.class, // StreamMetadata javax.imageio.metadata.IIOMetadata.class, // ImageMetadata java.awt.image.BufferedImage[].class, // Thumbnails java.util.EventListener[].class, // Listeners java.util.Locale.class, // Locale javax.imageio.ImageWriteParam.class, // WriteParam javax.imageio.ImageWriter.class // Writer }; /** The parameter default values for rendered mode of "ImageWrite". */ private static final Object[] renderedParamDefaults = { NO_PARAMETER_DEFAULT, // Output null, // Format Boolean.TRUE, // UseProperties Boolean.TRUE, // Transcode Boolean.TRUE, // VerifyOutput Boolean.FALSE, // AllowPixelReplacement null, // TileSize null, // StreamMetadata null, // ImageMetadata null, // Thumbnails null, // Listeners null, // Locale null, // WriteParam null // Writer }; /** The parameter class types for renderable mode of "ImageWrite". */ private static final Class[] renderableParamClasses = renderedParamClasses; /** The parameter default values for renderable mode of "ImageWrite". */ private static final Object[] renderableParamDefaults = renderedParamDefaults; /** The parameter class types for collection mode of "ImageWrite". */ private static final Class[] collectionParamClasses = { java.lang.Object.class, // Output java.lang.String.class, // Format java.lang.Boolean.class, // UseProperties java.lang.Boolean.class, // Transcode java.lang.Boolean.class, // VerifyOutput java.lang.Boolean.class, // AllowPixelReplacement java.awt.Dimension.class, // TileSize javax.imageio.metadata.IIOMetadata.class, // StreamMetadata javax.imageio.metadata.IIOMetadata[].class, // ImageMetadata java.awt.image.BufferedImage[][].class, // Thumbnails java.util.EventListener[].class, // Listeners java.util.Locale.class, // Locale javax.imageio.ImageWriteParam.class, // WriteParam javax.imageio.ImageWriter.class // Writer }; /** The parameter default values for collection mode of "ImageWrite". */ private static final Object[] collectionParamDefaults = renderedParamDefaults; /** Constructor. */ public ImageWriteDescriptor() { super(resources, new String[] {RenderedRegistryMode.MODE_NAME, RenderableRegistryMode.MODE_NAME, CollectionRegistryMode.MODE_NAME}, null, // sourceNames new Class[][] {{RenderedImage.class}, {RenderableImage.class}, {Collection.class}}, // sourceClasses paramNames, new Class[][] {renderedParamClasses, renderableParamClasses, collectionParamClasses}, new Object[][] {renderedParamDefaults, renderableParamDefaults, collectionParamDefaults}, new Object[][] {null, null, null}); // validParamValues } /** * Type-safe convenience method for creating a {@link RenderedOp} * representing the "ImageWrite" operation in rendered mode. The * method packs the source and parameters into a new * ParameterBlock and invokes * {@link JAI#create(String,ParameterBlock,RenderingHints)}. * * @param source The image to be written. * @param output The output destination. * @param format The format name of the output. * @param useProperties Whether to use image metadata properties as * fallbacks. * @param transcode Whether to transcode metadata before writing. * @param verifyOutput Whether to verify the validity of the output * destination. * @param allowPixelReplacement Whether to allow pixel replacement * in the output image. * @param tileSize The tile size of the output image. * @param streamMetadata Stream metadata to write to the output. * @param imageMetadata Image metadata to write to the output. * @param thumbnails Thumbnails to write to the output. * @param listeners EventListeners to be registered with the ImageWriter. * @param locale The Locale for the ImageWriter to use. * @param writeParam Java Image I/O write parameter instance. * @param writer Java Image I/O writer instance. * @param hints Operation hints. * @return a reference to the operation source. */ public static RenderedOp create(RenderedImage source, ImageOutputStream output, String format, Boolean useProperties, Boolean transcode, Boolean verifyOutput, Boolean allowPixelReplacement, Dimension tileSize, IIOMetadata streamMetadata, IIOMetadata imageMetadata, BufferedImage[] thumbnails, EventListener[] listeners, Locale locale, ImageWriteParam writeParam, ImageWriter writer, RenderingHints hints) { ParameterBlock args = new ParameterBlock(); args.addSource(source); args.add(output); args.add(format); args.add(useProperties); args.add(transcode); args.add(verifyOutput); args.add(allowPixelReplacement); args.add(tileSize); args.add(streamMetadata); args.add(imageMetadata); args.add(thumbnails); args.add(listeners); args.add(locale); args.add(writeParam); args.add(writer); return JAI.create(OPERATION_NAME, args, hints); } /** * Type-safe convenience method for creating a {@link Collection} * representing the "ImageWrite" operation in collection mode. The * method packs the source and parameters into a new * ParameterBlock and invokes * {@link JAI#createCollection(String,ParameterBlock,RenderingHints)}. * * @param source The collection to be written. * @param output The output destination. * @param format The format name of the output. * @param useProperties Whether to use image metadata properties as * fallbacks. * @param transcode Whether to transcode metadata before writing. * @param verifyOutput Whether to verify the validity of the output * destination. * @param allowPixelReplacement Whether to allow pixel replacement * in the output image. * @param tileSize The tile size of the output image. * @param streamMetadata Stream metadata to write to the output. * @param imageMetadata Image metadata to write to the output. * @param thumbnails Thumbnails to write to the output. * @param listeners EventListeners to be registered with the ImageWriter. * @param locale The Locale for the ImageWriter to use. * @param writeParam Java Image I/O write parameter instance. * @param writer Java Image I/O writer instance. * @param hints Operation hints. * @return a reference to the operation source. */ public static Collection createCollection(Collection source, ImageOutputStream output, String format, Boolean useProperties, Boolean transcode, Boolean verifyOutput, Boolean allowPixelReplacement, Dimension tileSize, IIOMetadata streamMetadata, IIOMetadata[] imageMetadata, BufferedImage[][] thumbnails, EventListener[] listeners, Locale locale, ImageWriteParam writeParam, ImageWriter writer, RenderingHints hints) { ParameterBlock args = new ParameterBlock(); args.addSource(source); args.add(output); args.add(format); args.add(useProperties); args.add(transcode); args.add(verifyOutput); args.add(allowPixelReplacement); args.add(tileSize); args.add(streamMetadata); args.add(imageMetadata); args.add(thumbnails); args.add(listeners); args.add(locale); args.add(writeParam); args.add(writer); return JAI.createCollection(OPERATION_NAME, args, hints); } /** * Type-safe convenience method for creating a {@link RenderableOp} * representing the "ImageWrite" operation in renderable mode. The * method packs the source and parameters into a new * ParameterBlock and invokes * {@link JAI#createRenderable(String,ParameterBlock,RenderingHints)}. * * @param source The renderable source to be written. * @param output The output destination. * @param format The format name of the output. * @param useProperties Whether to use image metadata properties as * fallbacks. * @param transcode Whether to transcode metadata before writing. * @param verifyOutput Whether to verify the validity of the output * destination. * @param allowPixelReplacement Whether to allow pixel replacement * in the output image. * @param tileSize The tile size of the output image. * @param streamMetadata Stream metadata to write to the output. * @param imageMetadata Image metadata to write to the output. * @param thumbnails Thumbnails to write to the output. * @param listeners EventListeners to be registered with the ImageWriter. * @param locale The Locale for the ImageWriter to use. * @param writeParam Java Image I/O write parameter instance. * @param writer Java Image I/O writer instance. * @param hints Operation hints. * @return a reference to the operation source. */ public static RenderableOp createRenderable(RenderableImage source, ImageOutputStream output, String format, Boolean useProperties, Boolean transcode, Boolean verifyOutput, Boolean allowPixelReplacement, Dimension tileSize, IIOMetadata streamMetadata, IIOMetadata imageMetadata, BufferedImage[] thumbnails, EventListener[] listeners, Locale locale, ImageWriteParam writeParam, ImageWriter writer, RenderingHints hints) { ParameterBlock args = new ParameterBlock(); args.addSource(source); args.add(output); args.add(format); args.add(useProperties); args.add(transcode); args.add(verifyOutput); args.add(allowPixelReplacement); args.add(tileSize); args.add(streamMetadata); args.add(imageMetadata); args.add(thumbnails); args.add(listeners); args.add(locale); args.add(writeParam); args.add(writer); return JAI.createRenderable(OPERATION_NAME, args, hints); } /** * Returns true indicating that the operation should be rendered * immediately during a call to JAI.create[]() or * JAI.createCollection[NS](). * * @see javax.media.jai.OperationDescriptor */ public boolean isImmediate() { return true; } /** * Validates the parameters in the supplied ParameterBlock. * *

In addition to the standard validation performed by the * corresponding superclass method, this method verifies the following: *

* * If the superclass method finds that the arguments are invalid, or if * this method determines that any of the foregoing conditions is true, * an error message will be appended to msg and * false will be returned; otherwise true will * be returned.

* * @param modeName The operation mode. * @param args The source and parameters of the operation. * @param msg A container for any error messages. * * @return Whether the supplied parameters are valid. */ protected boolean validateParameters(String modeName, ParameterBlock args, StringBuffer msg) { if (!super.validateParameters(modeName, args, msg)) { return false; } // Get the Output parameter. Object output = args.getObjectParameter(0); // Check the output if so requested by "VerifyOutput". Boolean verifyOutput = (Boolean)args.getObjectParameter(4); if (verifyOutput.booleanValue()){ if(output instanceof File || output instanceof String) { // Set file and path variables. File file = null; String path = null; if(output instanceof File) { file = (File)output; path = file.getPath(); } else if(output instanceof String) { path = (String)output; file = new File(path); } // Perform non-destructive test that the file // may be created and written. try { if (file.exists()) { if (!file.canWrite()) { // Cannot write to existing file. msg.append(file.getPath() + " " + I18N.getString("ImageWriteDescriptor15")); return false; } } else { if (!file.createNewFile()) { // Cannot create file. msg.append(file.getPath() + " " + I18N.getString("ImageWriteDescriptor16")); return false; } file.delete(); } } catch (IOException ioe) { // I/O exception during createNewFile(). msg.append(file.getPath() + " " + I18N.getString("ImageWriteDescriptor17") + " " + ioe.getMessage()); return false; } catch (SecurityException se) { // Security exception during exists(), canWrite(), // createNewFile(), or delete(). msg.append(file.getPath() + " " + I18N.getString("ImageWriteDescriptor18") + " " + se.getMessage()); return false; } } else if(output instanceof Socket) { Socket socket = (Socket)output; if(socket.isOutputShutdown()) { msg.append("\"" + socket + "\": " + I18N.getString("ImageWriteDescriptor19")); return false; } else if(socket.isClosed()) { msg.append("\"" + socket + "\": " + I18N.getString("ImageWriteDescriptor20")); return false; } else if(!socket.isBound()) { msg.append("\"" + socket + "\": " + I18N.getString("ImageWriteDescriptor21")); return false; } else if(!socket.isConnected()) { msg.append("\"" + socket + "\": " + I18N.getString("ImageWriteDescriptor22")); return false; } } } // Get the Format parameter. String format = (String)args.getObjectParameter(1); // Get the ImageWriter parameter. ImageWriter writer = (ImageWriter)args.getObjectParameter(13); if(format == null) { // Attempt to get the format from the ImageWriter provider. if(writer != null) { // Get the SPI. ImageWriterSpi spi = writer.getOriginatingProvider(); // Set from the SPI. if(spi != null) { format = spi.getFormatNames()[0]; } } // Attempt to deduce the format from the file suffix. if(format == null && (output instanceof File || output instanceof String)) { // Set the file name string. String name = output instanceof File ? ((File)output).getName() : (String)output; // Extract the suffix. String suffix = name.substring(name.lastIndexOf(".") + 1); // Get the writers of that suffix. Iterator writers = ImageIO.getImageWritersBySuffix(suffix); if(writers != null) { // Get the first writer. writer = (ImageWriter)writers.next(); if(writer != null) { // Get the SPI. ImageWriterSpi spi = writer.getOriginatingProvider(); // Set from the SPI. if(spi != null) { format = spi.getFormatNames()[0]; } } } } // Default to the most versatile core Java Image I/O writer. if(format == null) { format = "PNG"; } // Replace the format setting. if(format != null) { args.set(format, 1); } } // Check the tile size parameter if present. Dimension tileSize = (Dimension)args.getObjectParameter(6); if(tileSize != null && (tileSize.width <= 0 || tileSize.height <= 0)) { msg.append(I18N.getString("ImageWriteDescriptor23")); return false; } // For collection mode, verify that the source collection contains // at least one RenderedImage and that the writer can handle sequences // if there is more than one RenderedImage in the source collection. if(modeName.equalsIgnoreCase(CollectionRegistryMode.MODE_NAME)) { // Get the source collection. Collection source = (Collection)args.getSource(0); // If the source collection is a CollectionOp do not perform this // check as invoking source.size() will render the node. if(!(source instanceof CollectionOp)) { // Determine the number of RenderedImages in the Collection. int numRenderedImages = 0; Iterator iter = source.iterator(); while(iter.hasNext()) { if(iter.next() instanceof RenderedImage) { numRenderedImages++; } } if(numRenderedImages == 0) { msg.append(I18N.getString("ImageWriteDescriptor24")); return false; } else if(numRenderedImages > 1) { // Get the writer parameter. writer = (ImageWriter)args.getObjectParameter(13); // If the parameter writer is null, get one based on the // format. if(writer == null && format != null) { // Get the writers of that format. Iterator writers = ImageIO.getImageWritersByFormatName(format); if(writers != null) { // Get the first writer. writer = (ImageWriter)writers.next(); } } if(writer != null) { // Check that the writer can write sequences. if(!writer.canWriteSequence()) { msg.append(I18N.getString("ImageWriteDescriptor25")); return false; } } } } } return true; } } jai-imageio-core-1.2/src/share/classes/com/sun/media/jai/operator/properties0000664000175100017510000000552310203036165026173 0ustar tilletille# # $RCSfile: properties,v $ # # Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved. # # Use is subject to license terms. # # $Revision: 1.1 $ # $Date: 2005-02-11 05:01:57 $ # $State: Exp $ # # Internationalization file for com.sun.media.jai.operator DescriptorVersion=1.0 ImageReadDescriptor0=Reads an image using the Java Image I/O Framework. ImageReadDescriptor1=The input source. ImageReadDescriptor2=The index or indices of the image(s) to read. ImageReadDescriptor3=Whether metadata should be read if available. ImageReadDescriptor4=Whether thumbnails should be read if available. ImageReadDescriptor5=Whether to verify the validity of the input source. ImageReadDescriptor6=EventListeners to be registered with the ImageReader. ImageReadDescriptor7=The Locale for the ImageReader to use. ImageReadDescriptor8=Java Image I/O read parameter instance. ImageReadDescriptor9=Java Image I/O reader instance. ImageReadDescriptor10=Image index parameter must be non-negative. ImageReadDescriptor11=does not exist. ImageReadDescriptor12=is not readable. ImageReadDescriptor13=has its read-half shut down. ImageReadDescriptor14=is closed. ImageReadDescriptor15=is not bound to an address. ImageReadDescriptor16=is not connected. ImageWriteDescriptor0=Writes an image using the Java Image I/O Framework. ImageWriteDescriptor1=The output destination. ImageWriteDescriptor2=The format name of the output. ImageWriteDescriptor3=Whether to use image metadata properties as fallbacks. ImageWriteDescriptor4=Whether to transcode metadata before writing. ImageWriteDescriptor5=Whether to verify the validity of the output destination. ImageWriteDescriptor6=Whether to allow pixel replacement in the output image. ImageWriteDescriptor7=The tile size of the output image. ImageWriteDescriptor8=Stream metadata to write to the output. ImageWriteDescriptor9=Image metadata to write to the output. ImageWriteDescriptor10=Thumbnails to write to the output. ImageWriteDescriptor11=EventListeners to be registered with the ImageWriter. ImageWriteDescriptor12=The Locale for the ImageWriter to use. ImageWriteDescriptor13=Java Image I/O write parameter instance. ImageWriteDescriptor14=Java Image I/O writer instance. ImageWriteDescriptor15=exists but is not writable. ImageWriteDescriptor16=does not exist and cannot be created. ImageWriteDescriptor17=encountered IOException during createNewFile: ImageWriteDescriptor18=access denied by security manager: ImageWriteDescriptor19=has its write-half shut down. ImageWriteDescriptor20=is closed. ImageWriteDescriptor21=is not bound to an address. ImageWriteDescriptor22=is not connected. ImageWriteDescriptor23=Non-positive tile dimension specified. ImageWriteDescriptor24=No RenderedImages in the source Collection. ImageWriteDescriptor25=There is more than one RenderedImage in the source \ Collection and the supplied ImageWriter cannot write sequences. jai-imageio-core-1.2/src/share/classes/com/sun/media/jai/operator/PrintProps.java0000664000175100017510000000661510203036165027042 0ustar tilletille/* * $RCSfile: PrintProps.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.1 $ * $Date: 2005-02-11 05:01:57 $ * $State: Exp $ */ package com.sun.media.jai.operator; import java.util.Collection; import java.util.Iterator; import javax.media.jai.PropertySource; final class PrintProps { static final void print(PropertySource ps) { String[] propNames = ps.getPropertyNames(); if(propNames != null) { System.out.println("\nPROPERTIES OF "+ ps.getClass().getName()+"@"+ ps.hashCode()+":\n"); for(int j = 0; j < propNames.length; j++) { Object propVal = ps.getProperty(propNames[j]); if(propVal == null) { System.out.println(propNames[j]+" is NULL."); } else if(propVal == java.awt.Image.UndefinedProperty) { System.out.println(propNames[j]+" is UNDEFINED."); } else { System.out.println(propNames[j]+" = "+ propVal.getClass().getName()+"@"+ propVal.hashCode()); } } } else { System.out.println("\n"+ps+" has no properties."); } System.out.println("\n"); if(ps instanceof Collection) { Iterator iter = ((Collection)ps).iterator(); while(iter.hasNext()) { Object nextElement = iter.next(); if(nextElement instanceof PropertySource) { print((PropertySource)nextElement); } } } } } jai-imageio-core-1.2/src/share/classes/com/sun/media/jai/operator/I18N.java0000664000175100017510000000416010203036165025372 0ustar tilletille/* * $RCSfile: I18N.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.1 $ * $Date: 2005-02-11 05:01:56 $ * $State: Exp $ */ package com.sun.media.jai.operator; import com.sun.media.imageioimpl.common.I18NImpl; final class I18N extends I18NImpl { static String getString(String key) { return getString("com.sun.media.jai.operator.I18N", key); } } jai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/0000775000175100017510000000000011650556211023753 5ustar tilletillejai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/common/0000775000175100017510000000000011650556211025243 5ustar tilletillejai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/common/InvertedCMYKColorSpace.java0000664000175100017510000001066510423235255032334 0ustar tilletille/* * $RCSfile: InvertedCMYKColorSpace.java,v $ * * * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.1 $ * $Date: 2006-04-24 20:53:01 $ * $State: Exp $ */ package com.sun.media.imageioimpl.common; import java.awt.color.ColorSpace; /** * Singleton class representing a simple, mathematically defined * inverted CMYK color space. */ public final class InvertedCMYKColorSpace extends ColorSpace { private static ColorSpace theInstance = null; private ColorSpace csRGB; /** The exponent for gamma correction. */ private static final double power1 = 1.0 / 2.4; public static final synchronized ColorSpace getInstance() { if(theInstance == null) { theInstance = new InvertedCMYKColorSpace(); } return theInstance; } private InvertedCMYKColorSpace() { super(TYPE_CMYK, 4); csRGB = ColorSpace.getInstance(ColorSpace.CS_LINEAR_RGB); } public boolean equals(Object o) { return o != null && o instanceof InvertedCMYKColorSpace; } public float[] toRGB(float[] colorvalue) { float C = colorvalue[0]; float M = colorvalue[1]; float Y = colorvalue[2]; float K = colorvalue[3]; // Convert from CMYK to linear RGB. float[] rgbvalue = new float[] {K*C, K*M, K*Y}; // Convert from linear RGB to sRGB. for (int i = 0; i < 3; i++) { float v = rgbvalue[i]; if (v < 0.0F) v = 0.0F; if (v < 0.0031308F) { rgbvalue[i] = 12.92F * v; } else { if (v > 1.0F) v = 1.0F; rgbvalue[i] = (float)(1.055 * Math.pow(v, power1) - 0.055); } } return rgbvalue; } public float[] fromRGB(float[] rgbvalue) { // Convert from sRGB to linear RGB. for (int i = 0; i < 3; i++) { if (rgbvalue[i] < 0.040449936F) { rgbvalue[i] /= 12.92F; } else { rgbvalue[i] = (float)(Math.pow((rgbvalue[i] + 0.055)/1.055, 2.4)); } } // Convert from linear RGB to CMYK. float C = rgbvalue[0]; float M = rgbvalue[1]; float Y = rgbvalue[2]; float K = Math.max(C, Math.max(M, Y)); // If K == 0.0F, then C = M = Y = 0.0F. if(K != 0.0F) { C = C/K; M = M/K; Y = Y/K; } else { // K == 0.0F C = M = Y = 1.0F; } return new float[] {C, M, Y, K}; } public float[] toCIEXYZ(float[] colorvalue) { return csRGB.toCIEXYZ(toRGB(colorvalue)); } public float[] fromCIEXYZ(float[] xyzvalue) { return fromRGB(csRGB.fromCIEXYZ(xyzvalue)); } } jai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/common/ImageUtil.java0000664000175100017510000015775110665066462030017 0ustar tilletille/* * $RCSfile: ImageUtil.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.7 $ * $Date: 2007-08-28 18:45:06 $ * $State: Exp $ */ package com.sun.media.imageioimpl.common; import java.awt.Point; import java.awt.Rectangle; import java.awt.Transparency; import java.awt.color.ColorSpace; import java.awt.color.ICC_ColorSpace; import java.awt.image.BufferedImage; import java.awt.image.ColorModel; import java.awt.image.ComponentColorModel; import java.awt.image.ComponentSampleModel; import java.awt.image.DataBuffer; import java.awt.image.DataBufferByte; import java.awt.image.DataBufferInt; import java.awt.image.DataBufferShort; import java.awt.image.DataBufferUShort; import java.awt.image.DirectColorModel; import java.awt.image.IndexColorModel; import java.awt.image.MultiPixelPackedSampleModel; import java.awt.image.Raster; import java.awt.image.RenderedImage; import java.awt.image.SampleModel; import java.awt.image.SinglePixelPackedSampleModel; import java.awt.image.WritableRaster; import java.io.IOException; import java.util.Arrays; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Locale; //import javax.imageio.ImageTypeSpecifier; import javax.imageio.IIOException; import javax.imageio.IIOImage; import javax.imageio.ImageReadParam; import javax.imageio.ImageTypeSpecifier; import javax.imageio.ImageWriter; import javax.imageio.spi.IIORegistry; import javax.imageio.spi.ImageReaderSpi; import javax.imageio.spi.ImageReaderWriterSpi; import javax.imageio.spi.ImageWriterSpi; import javax.imageio.spi.ServiceRegistry; import javax.imageio.stream.ImageInputStream; public class ImageUtil { /* XXX testing only public static void main(String[] args) { ImageTypeSpecifier bilevel = ImageTypeSpecifier.createIndexed(new byte[] {(byte)0, (byte)255}, new byte[] {(byte)0, (byte)255}, new byte[] {(byte)0, (byte)255}, null, 1, DataBuffer.TYPE_BYTE); ImageTypeSpecifier gray = ImageTypeSpecifier.createGrayscale(8, DataBuffer.TYPE_BYTE, false); ImageTypeSpecifier grayAlpha = ImageTypeSpecifier.createGrayscale(8, DataBuffer.TYPE_BYTE, false, false); ImageTypeSpecifier rgb = ImageTypeSpecifier.createInterleaved(ColorSpace.getInstance(ColorSpace.CS_sRGB), new int[] {0, 1, 2}, DataBuffer.TYPE_BYTE, false, false); ImageTypeSpecifier rgba = ImageTypeSpecifier.createInterleaved(ColorSpace.getInstance(ColorSpace.CS_sRGB), new int[] {0, 1, 2, 3}, DataBuffer.TYPE_BYTE, true, false); ImageTypeSpecifier packed = ImageTypeSpecifier.createPacked(ColorSpace.getInstance(ColorSpace.CS_sRGB), 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff, DataBuffer.TYPE_BYTE, false); SampleModel bandedSM = new java.awt.image.BandedSampleModel(DataBuffer.TYPE_BYTE, 1, 1, 15); System.out.println(createColorModel(bilevel.getSampleModel())); System.out.println(createColorModel(gray.getSampleModel())); System.out.println(createColorModel(grayAlpha.getSampleModel())); System.out.println(createColorModel(rgb.getSampleModel())); System.out.println(createColorModel(rgba.getSampleModel())); System.out.println(createColorModel(packed.getSampleModel())); System.out.println(createColorModel(bandedSM)); } */ /** * Creates a ColorModel that may be used with the * specified SampleModel. If a suitable * ColorModel cannot be found, this method returns * null. * *

Suitable ColorModels are guaranteed to exist * for all instances of ComponentSampleModel. * For 1- and 3- banded SampleModels, the returned * ColorModel will be opaque. For 2- and 4-banded * SampleModels, the output will use alpha transparency * which is not premultiplied. 1- and 2-banded data will use a * grayscale ColorSpace, and 3- and 4-banded data a sRGB * ColorSpace. Data with 5 or more bands will have a * BogusColorSpace.

* *

An instance of DirectColorModel will be created for * instances of SinglePixelPackedSampleModel with no more * than 4 bands.

* *

An instance of IndexColorModel will be created for * instances of MultiPixelPackedSampleModel. The colormap * will be a grayscale ramp with 1 << numberOfBits * entries ranging from zero to at most 255.

* * @return An instance of ColorModel that is suitable for * the supplied SampleModel, or null. * * @throws IllegalArgumentException If sampleModel is * null. */ public static final ColorModel createColorModel(SampleModel sampleModel) { // Check the parameter. if(sampleModel == null) { throw new IllegalArgumentException("sampleModel == null!"); } // Get the data type. int dataType = sampleModel.getDataType(); // Check the data type switch(dataType) { case DataBuffer.TYPE_BYTE: case DataBuffer.TYPE_USHORT: case DataBuffer.TYPE_SHORT: case DataBuffer.TYPE_INT: case DataBuffer.TYPE_FLOAT: case DataBuffer.TYPE_DOUBLE: break; default: // Return null for other types. return null; } // The return variable. ColorModel colorModel = null; // Get the sample size. int[] sampleSize = sampleModel.getSampleSize(); // Create a Component ColorModel. if(sampleModel instanceof ComponentSampleModel) { // Get the number of bands. int numBands = sampleModel.getNumBands(); // Determine the color space. ColorSpace colorSpace = null; if(numBands <= 2) { colorSpace = ColorSpace.getInstance(ColorSpace.CS_GRAY); } else if(numBands <= 4) { colorSpace = ColorSpace.getInstance(ColorSpace.CS_sRGB); } else { colorSpace = new BogusColorSpace(numBands); } boolean hasAlpha = (numBands == 2) || (numBands == 4); boolean isAlphaPremultiplied = false; int transparency = hasAlpha ? Transparency.TRANSLUCENT : Transparency.OPAQUE; colorModel = new ComponentColorModel(colorSpace, sampleSize, hasAlpha, isAlphaPremultiplied, transparency, dataType); } else if (sampleModel.getNumBands() <= 4 && sampleModel instanceof SinglePixelPackedSampleModel) { SinglePixelPackedSampleModel sppsm = (SinglePixelPackedSampleModel)sampleModel; int[] bitMasks = sppsm.getBitMasks(); int rmask = 0; int gmask = 0; int bmask = 0; int amask = 0; int numBands = bitMasks.length; if (numBands <= 2) { rmask = gmask = bmask = bitMasks[0]; if (numBands == 2) { amask = bitMasks[1]; } } else { rmask = bitMasks[0]; gmask = bitMasks[1]; bmask = bitMasks[2]; if (numBands == 4) { amask = bitMasks[3]; } } int bits = 0; for (int i = 0; i < sampleSize.length; i++) { bits += sampleSize[i]; } return new DirectColorModel(bits, rmask, gmask, bmask, amask); } else if(sampleModel instanceof MultiPixelPackedSampleModel) { // Load the colormap with a ramp. int bitsPerSample = sampleSize[0]; int numEntries = 1 << bitsPerSample; byte[] map = new byte[numEntries]; for (int i = 0; i < numEntries; i++) { map[i] = (byte)(i*255/(numEntries - 1)); } colorModel = new IndexColorModel(bitsPerSample, numEntries, map, map, map); } return colorModel; } /** * For the case of binary data (isBinary() returns * true), return the binary data as a packed byte array. * The data will be packed as eight bits per byte with no bit offset, * i.e., the first bit in each image line will be the left-most of the * first byte of the line. The line stride in bytes will be * (int)((getWidth()+7)/8). The length of the returned * array will be the line stride multiplied by getHeight() * * @return the binary data as a packed array of bytes with zero offset * of null if the data are not binary. * @throws IllegalArgumentException if isBinary() returns * false with the SampleModel of the * supplied Raster as argument. */ public static byte[] getPackedBinaryData(Raster raster, Rectangle rect) { SampleModel sm = raster.getSampleModel(); if(!isBinary(sm)) { throw new IllegalArgumentException(I18N.getString("ImageUtil0")); } int rectX = rect.x; int rectY = rect.y; int rectWidth = rect.width; int rectHeight = rect.height; DataBuffer dataBuffer = raster.getDataBuffer(); int dx = rectX - raster.getSampleModelTranslateX(); int dy = rectY - raster.getSampleModelTranslateY(); MultiPixelPackedSampleModel mpp = (MultiPixelPackedSampleModel)sm; int lineStride = mpp.getScanlineStride(); int eltOffset = dataBuffer.getOffset() + mpp.getOffset(dx, dy); int bitOffset = mpp.getBitOffset(dx); int numBytesPerRow = (rectWidth + 7)/8; if(dataBuffer instanceof DataBufferByte && eltOffset == 0 && bitOffset == 0 && numBytesPerRow == lineStride && ((DataBufferByte)dataBuffer).getData().length == numBytesPerRow*rectHeight) { return ((DataBufferByte)dataBuffer).getData(); } byte[] binaryDataArray = new byte[numBytesPerRow*rectHeight]; int b = 0; if(bitOffset == 0) { if(dataBuffer instanceof DataBufferByte) { byte[] data = ((DataBufferByte)dataBuffer).getData(); int stride = numBytesPerRow; int offset = 0; for(int y = 0; y < rectHeight; y++) { System.arraycopy(data, eltOffset, binaryDataArray, offset, stride); offset += stride; eltOffset += lineStride; } } else if(dataBuffer instanceof DataBufferShort || dataBuffer instanceof DataBufferUShort) { short[] data = dataBuffer instanceof DataBufferShort ? ((DataBufferShort)dataBuffer).getData() : ((DataBufferUShort)dataBuffer).getData(); for(int y = 0; y < rectHeight; y++) { int xRemaining = rectWidth; int i = eltOffset; while(xRemaining > 8) { short datum = data[i++]; binaryDataArray[b++] = (byte)((datum >>> 8) & 0xFF); binaryDataArray[b++] = (byte)(datum & 0xFF); xRemaining -= 16; } if(xRemaining > 0) { binaryDataArray[b++] = (byte)((data[i] >>> 8) & 0XFF); } eltOffset += lineStride; } } else if(dataBuffer instanceof DataBufferInt) { int[] data = ((DataBufferInt)dataBuffer).getData(); for(int y = 0; y < rectHeight; y++) { int xRemaining = rectWidth; int i = eltOffset; while(xRemaining > 24) { int datum = data[i++]; binaryDataArray[b++] = (byte)((datum >>> 24) & 0xFF); binaryDataArray[b++] = (byte)((datum >>> 16) & 0xFF); binaryDataArray[b++] = (byte)((datum >>> 8) & 0xFF); binaryDataArray[b++] = (byte)(datum & 0xFF); xRemaining -= 32; } int shift = 24; while(xRemaining > 0) { binaryDataArray[b++] = (byte)((data[i] >>> shift) & 0xFF); shift -= 8; xRemaining -= 8; } eltOffset += lineStride; } } } else { // bitOffset != 0 if(dataBuffer instanceof DataBufferByte) { byte[] data = ((DataBufferByte)dataBuffer).getData(); if((bitOffset & 7) == 0) { int stride = numBytesPerRow; int offset = 0; for(int y = 0; y < rectHeight; y++) { System.arraycopy(data, eltOffset, binaryDataArray, offset, stride); offset += stride; eltOffset += lineStride; } } else { // bitOffset % 8 != 0 int leftShift = bitOffset & 7; int rightShift = 8 - leftShift; for(int y = 0; y < rectHeight; y++) { int i = eltOffset; int xRemaining = rectWidth; while(xRemaining > 0) { if(xRemaining > rightShift) { binaryDataArray[b++] = (byte)(((data[i++]&0xFF) << leftShift) | ((data[i]&0xFF) >>> rightShift)); } else { binaryDataArray[b++] = (byte)((data[i]&0xFF) << leftShift); } xRemaining -= 8; } eltOffset += lineStride; } } } else if(dataBuffer instanceof DataBufferShort || dataBuffer instanceof DataBufferUShort) { short[] data = dataBuffer instanceof DataBufferShort ? ((DataBufferShort)dataBuffer).getData() : ((DataBufferUShort)dataBuffer).getData(); for(int y = 0; y < rectHeight; y++) { int bOffset = bitOffset; for(int x = 0; x < rectWidth; x += 8, bOffset += 8) { int i = eltOffset + bOffset/16; int mod = bOffset % 16; int left = data[i] & 0xFFFF; if(mod <= 8) { binaryDataArray[b++] = (byte)(left >>> (8 - mod)); } else { int delta = mod - 8; int right = data[i+1] & 0xFFFF; binaryDataArray[b++] = (byte)((left << delta) | (right >>> (16 - delta))); } } eltOffset += lineStride; } } else if(dataBuffer instanceof DataBufferInt) { int[] data = ((DataBufferInt)dataBuffer).getData(); for(int y = 0; y < rectHeight; y++) { int bOffset = bitOffset; for(int x = 0; x < rectWidth; x += 8, bOffset += 8) { int i = eltOffset + bOffset/32; int mod = bOffset % 32; int left = data[i]; if(mod <= 24) { binaryDataArray[b++] = (byte)(left >>> (24 - mod)); } else { int delta = mod - 24; int right = data[i+1]; binaryDataArray[b++] = (byte)((left << delta) | (right >>> (32 - delta))); } } eltOffset += lineStride; } } } return binaryDataArray; } /** * Returns the binary data unpacked into an array of bytes. * The line stride will be the width of the Raster. * * @throws IllegalArgumentException if isBinary() returns * false with the SampleModel of the * supplied Raster as argument. */ public static byte[] getUnpackedBinaryData(Raster raster, Rectangle rect) { SampleModel sm = raster.getSampleModel(); if(!isBinary(sm)) { throw new IllegalArgumentException(I18N.getString("ImageUtil0")); } int rectX = rect.x; int rectY = rect.y; int rectWidth = rect.width; int rectHeight = rect.height; DataBuffer dataBuffer = raster.getDataBuffer(); int dx = rectX - raster.getSampleModelTranslateX(); int dy = rectY - raster.getSampleModelTranslateY(); MultiPixelPackedSampleModel mpp = (MultiPixelPackedSampleModel)sm; int lineStride = mpp.getScanlineStride(); int eltOffset = dataBuffer.getOffset() + mpp.getOffset(dx, dy); int bitOffset = mpp.getBitOffset(dx); byte[] bdata = new byte[rectWidth*rectHeight]; int maxY = rectY + rectHeight; int maxX = rectX + rectWidth; int k = 0; if(dataBuffer instanceof DataBufferByte) { byte[] data = ((DataBufferByte)dataBuffer).getData(); for(int y = rectY; y < maxY; y++) { int bOffset = eltOffset*8 + bitOffset; for(int x = rectX; x < maxX; x++) { byte b = data[bOffset/8]; bdata[k++] = (byte)((b >>> (7 - bOffset & 7)) & 0x0000001); bOffset++; } eltOffset += lineStride; } } else if(dataBuffer instanceof DataBufferShort || dataBuffer instanceof DataBufferUShort) { short[] data = dataBuffer instanceof DataBufferShort ? ((DataBufferShort)dataBuffer).getData() : ((DataBufferUShort)dataBuffer).getData(); for(int y = rectY; y < maxY; y++) { int bOffset = eltOffset*16 + bitOffset; for(int x = rectX; x < maxX; x++) { short s = data[bOffset/16]; bdata[k++] = (byte)((s >>> (15 - bOffset % 16)) & 0x0000001); bOffset++; } eltOffset += lineStride; } } else if(dataBuffer instanceof DataBufferInt) { int[] data = ((DataBufferInt)dataBuffer).getData(); for(int y = rectY; y < maxY; y++) { int bOffset = eltOffset*32 + bitOffset; for(int x = rectX; x < maxX; x++) { int i = data[bOffset/32]; bdata[k++] = (byte)((i >>> (31 - bOffset % 32)) & 0x0000001); bOffset++; } eltOffset += lineStride; } } return bdata; } /** * Sets the supplied Raster's data from an array * of packed binary data of the form returned by * getPackedBinaryData(). * * @throws IllegalArgumentException if isBinary() returns * false with the SampleModel of the * supplied Raster as argument. */ public static void setPackedBinaryData(byte[] binaryDataArray, WritableRaster raster, Rectangle rect) { SampleModel sm = raster.getSampleModel(); if(!isBinary(sm)) { throw new IllegalArgumentException(I18N.getString("ImageUtil0")); } int rectX = rect.x; int rectY = rect.y; int rectWidth = rect.width; int rectHeight = rect.height; DataBuffer dataBuffer = raster.getDataBuffer(); int dx = rectX - raster.getSampleModelTranslateX(); int dy = rectY - raster.getSampleModelTranslateY(); MultiPixelPackedSampleModel mpp = (MultiPixelPackedSampleModel)sm; int lineStride = mpp.getScanlineStride(); int eltOffset = dataBuffer.getOffset() + mpp.getOffset(dx, dy); int bitOffset = mpp.getBitOffset(dx); int b = 0; if(bitOffset == 0) { if(dataBuffer instanceof DataBufferByte) { byte[] data = ((DataBufferByte)dataBuffer).getData(); if(data == binaryDataArray) { // Optimal case: simply return. return; } int stride = (rectWidth + 7)/8; int offset = 0; for(int y = 0; y < rectHeight; y++) { System.arraycopy(binaryDataArray, offset, data, eltOffset, stride); offset += stride; eltOffset += lineStride; } } else if(dataBuffer instanceof DataBufferShort || dataBuffer instanceof DataBufferUShort) { short[] data = dataBuffer instanceof DataBufferShort ? ((DataBufferShort)dataBuffer).getData() : ((DataBufferUShort)dataBuffer).getData(); for(int y = 0; y < rectHeight; y++) { int xRemaining = rectWidth; int i = eltOffset; while(xRemaining > 8) { data[i++] = (short)(((binaryDataArray[b++] & 0xFF) << 8) | (binaryDataArray[b++] & 0xFF)); xRemaining -= 16; } if(xRemaining > 0) { data[i++] = (short)((binaryDataArray[b++] & 0xFF) << 8); } eltOffset += lineStride; } } else if(dataBuffer instanceof DataBufferInt) { int[] data = ((DataBufferInt)dataBuffer).getData(); for(int y = 0; y < rectHeight; y++) { int xRemaining = rectWidth; int i = eltOffset; while(xRemaining > 24) { data[i++] = (int)(((binaryDataArray[b++] & 0xFF) << 24) | ((binaryDataArray[b++] & 0xFF) << 16) | ((binaryDataArray[b++] & 0xFF) << 8) | (binaryDataArray[b++] & 0xFF)); xRemaining -= 32; } int shift = 24; while(xRemaining > 0) { data[i] |= (int)((binaryDataArray[b++] & 0xFF) << shift); shift -= 8; xRemaining -= 8; } eltOffset += lineStride; } } } else { // bitOffset != 0 int stride = (rectWidth + 7)/8; int offset = 0; if(dataBuffer instanceof DataBufferByte) { byte[] data = ((DataBufferByte)dataBuffer).getData(); if((bitOffset & 7) == 0) { for(int y = 0; y < rectHeight; y++) { System.arraycopy(binaryDataArray, offset, data, eltOffset, stride); offset += stride; eltOffset += lineStride; } } else { // bitOffset % 8 != 0 int rightShift = bitOffset & 7; int leftShift = 8 - rightShift; int leftShift8 = 8 + leftShift; int mask = (byte)(255< 0) { byte datum = binaryDataArray[b++]; if (xRemaining > leftShift8) { // when all the bits in this BYTE will be set // into the data buffer. data[i] = (byte)((data[i] & mask ) | ((datum&0xFF) >>> rightShift)); data[++i] = (byte)((datum & 0xFF) << leftShift); } else if (xRemaining > leftShift) { // All the "leftShift" high bits will be set // into the data buffer. But not all the // "rightShift" low bits will be set. data[i] = (byte)((data[i] & mask ) | ((datum&0xFF) >>> rightShift)); i++; data[i] = (byte)((data[i] & mask1) | ((datum & 0xFF) << leftShift)); } else { // Less than "leftShift" high bits will be set. int remainMask = (1 << leftShift - xRemaining) - 1; data[i] = (byte)((data[i] & (mask | remainMask)) | (datum&0xFF) >>> rightShift & ~remainMask); } xRemaining -= 8; } eltOffset += lineStride; } } } else if(dataBuffer instanceof DataBufferShort || dataBuffer instanceof DataBufferUShort) { short[] data = dataBuffer instanceof DataBufferShort ? ((DataBufferShort)dataBuffer).getData() : ((DataBufferUShort)dataBuffer).getData(); int rightShift = bitOffset & 7; int leftShift = 8 - rightShift; int leftShift16 = 16 + leftShift; int mask = (short)(~(255 << leftShift)); int mask1 = (short)(65535 << leftShift); int mask2 = (short)~mask1; for(int y = 0; y < rectHeight; y++) { int bOffset = bitOffset; int xRemaining = rectWidth; for(int x = 0; x < rectWidth; x += 8, bOffset += 8, xRemaining -= 8) { int i = eltOffset + (bOffset >> 4); int mod = bOffset & 15; int datum = binaryDataArray[b++] & 0xFF; if(mod <= 8) { // This BYTE is set into one SHORT if (xRemaining < 8) { // Mask the bits to be set. datum &= 255 << 8 - xRemaining; } data[i] = (short)((data[i] & mask) | (datum << leftShift)); } else if (xRemaining > leftShift16) { // This BYTE will be set into two SHORTs data[i] = (short)((data[i] & mask1) | ((datum >>> rightShift)&0xFFFF)); data[++i] = (short)((datum << leftShift)&0xFFFF); } else if (xRemaining > leftShift) { // This BYTE will be set into two SHORTs; // But not all the low bits will be set into SHORT data[i] = (short)((data[i] & mask1) | ((datum >>> rightShift)&0xFFFF)); i++; data[i] = (short)((data[i] & mask2) | ((datum << leftShift)&0xFFFF)); } else { // Only some of the high bits will be set into // SHORTs int remainMask = (1 << leftShift - xRemaining) - 1; data[i] = (short)((data[i] & (mask1 | remainMask)) | ((datum >>> rightShift)&0xFFFF & ~remainMask)); } } eltOffset += lineStride; } } else if(dataBuffer instanceof DataBufferInt) { int[] data = ((DataBufferInt)dataBuffer).getData(); int rightShift = bitOffset & 7; int leftShift = 8 - rightShift; int leftShift32 = 32 + leftShift; int mask = 0xFFFFFFFF << leftShift; int mask1 = ~mask; for(int y = 0; y < rectHeight; y++) { int bOffset = bitOffset; int xRemaining = rectWidth; for(int x = 0; x < rectWidth; x += 8, bOffset += 8, xRemaining -= 8) { int i = eltOffset + (bOffset >> 5); int mod = bOffset & 31; int datum = binaryDataArray[b++] & 0xFF; if(mod <= 24) { // This BYTE is set into one INT int shift = 24 - mod; if (xRemaining < 8) { // Mask the bits to be set. datum &= 255 << 8 - xRemaining; } data[i] = (data[i] & (~(255 << shift))) | (datum << shift); } else if (xRemaining > leftShift32) { // All the bits of this BYTE will be set into two INTs data[i] = (data[i] & mask) | (datum >>> rightShift); data[++i] = datum << leftShift; } else if (xRemaining > leftShift) { // This BYTE will be set into two INTs; // But not all the low bits will be set into INT data[i] = (data[i] & mask) | (datum >>> rightShift); i++; data[i] = (data[i] & mask1) | (datum << leftShift); } else { // Only some of the high bits will be set into INT int remainMask = (1 << leftShift - xRemaining) - 1; data[i] = (data[i] & (mask | remainMask)) | (datum >>> rightShift & ~remainMask); } } eltOffset += lineStride; } } } } /** * Copies data into the packed array of the Raster * from an array of unpacked data of the form returned by * getUnpackedBinaryData(). * *

If the data are binary, then the target bit will be set if * and only if the corresponding byte is non-zero. * * @throws IllegalArgumentException if isBinary() returns * false with the SampleModel of the * supplied Raster as argument. */ public static void setUnpackedBinaryData(byte[] bdata, WritableRaster raster, Rectangle rect) { SampleModel sm = raster.getSampleModel(); if(!isBinary(sm)) { throw new IllegalArgumentException(I18N.getString("ImageUtil0")); } int rectX = rect.x; int rectY = rect.y; int rectWidth = rect.width; int rectHeight = rect.height; DataBuffer dataBuffer = raster.getDataBuffer(); int dx = rectX - raster.getSampleModelTranslateX(); int dy = rectY - raster.getSampleModelTranslateY(); MultiPixelPackedSampleModel mpp = (MultiPixelPackedSampleModel)sm; int lineStride = mpp.getScanlineStride(); int eltOffset = dataBuffer.getOffset() + mpp.getOffset(dx, dy); int bitOffset = mpp.getBitOffset(dx); int k = 0; if(dataBuffer instanceof DataBufferByte) { byte[] data = ((DataBufferByte)dataBuffer).getData(); for(int y = 0; y < rectHeight; y++) { int bOffset = eltOffset*8 + bitOffset; for(int x = 0; x < rectWidth; x++) { if(bdata[k++] != (byte)0) { data[bOffset/8] |= (byte)(0x00000001 << (7 - bOffset & 7)); } bOffset++; } eltOffset += lineStride; } } else if(dataBuffer instanceof DataBufferShort || dataBuffer instanceof DataBufferUShort) { short[] data = dataBuffer instanceof DataBufferShort ? ((DataBufferShort)dataBuffer).getData() : ((DataBufferUShort)dataBuffer).getData(); for(int y = 0; y < rectHeight; y++) { int bOffset = eltOffset*16 + bitOffset; for(int x = 0; x < rectWidth; x++) { if(bdata[k++] != (byte)0) { data[bOffset/16] |= (short)(0x00000001 << (15 - bOffset % 16)); } bOffset++; } eltOffset += lineStride; } } else if(dataBuffer instanceof DataBufferInt) { int[] data = ((DataBufferInt)dataBuffer).getData(); for(int y = 0; y < rectHeight; y++) { int bOffset = eltOffset*32 + bitOffset; for(int x = 0; x < rectWidth; x++) { if(bdata[k++] != (byte)0) { data[bOffset/32] |= (int)(0x00000001 << (31 - bOffset % 32)); } bOffset++; } eltOffset += lineStride; } } } public static boolean isBinary(SampleModel sm) { return sm instanceof MultiPixelPackedSampleModel && ((MultiPixelPackedSampleModel)sm).getPixelBitStride() == 1 && sm.getNumBands() == 1; } public static ColorModel createColorModel(ColorSpace colorSpace, SampleModel sampleModel) { ColorModel colorModel = null; if(sampleModel == null) { throw new IllegalArgumentException(I18N.getString("ImageUtil1")); } int numBands = sampleModel.getNumBands(); if (numBands < 1 || numBands > 4) { return null; } int dataType = sampleModel.getDataType(); if (sampleModel instanceof ComponentSampleModel) { if (dataType < DataBuffer.TYPE_BYTE || //dataType == DataBuffer.TYPE_SHORT || dataType > DataBuffer.TYPE_DOUBLE) { return null; } if (colorSpace == null) colorSpace = numBands <= 2 ? ColorSpace.getInstance(ColorSpace.CS_GRAY) : ColorSpace.getInstance(ColorSpace.CS_sRGB); boolean useAlpha = (numBands == 2) || (numBands == 4); int transparency = useAlpha ? Transparency.TRANSLUCENT : Transparency.OPAQUE; boolean premultiplied = false; int dataTypeSize = DataBuffer.getDataTypeSize(dataType); int[] bits = new int[numBands]; for (int i = 0; i < numBands; i++) { bits[i] = dataTypeSize; } colorModel = new ComponentColorModel(colorSpace, bits, useAlpha, premultiplied, transparency, dataType); } else if (sampleModel instanceof SinglePixelPackedSampleModel) { SinglePixelPackedSampleModel sppsm = (SinglePixelPackedSampleModel)sampleModel; int[] bitMasks = sppsm.getBitMasks(); int rmask = 0; int gmask = 0; int bmask = 0; int amask = 0; numBands = bitMasks.length; if (numBands <= 2) { rmask = gmask = bmask = bitMasks[0]; if (numBands == 2) { amask = bitMasks[1]; } } else { rmask = bitMasks[0]; gmask = bitMasks[1]; bmask = bitMasks[2]; if (numBands == 4) { amask = bitMasks[3]; } } int[] sampleSize = sppsm.getSampleSize(); int bits = 0; for (int i = 0; i < sampleSize.length; i++) { bits += sampleSize[i]; } if (colorSpace == null) colorSpace = ColorSpace.getInstance(ColorSpace.CS_sRGB); colorModel = new DirectColorModel(colorSpace, bits, rmask, gmask, bmask, amask, false, sampleModel.getDataType()); } else if (sampleModel instanceof MultiPixelPackedSampleModel) { int bits = ((MultiPixelPackedSampleModel)sampleModel).getPixelBitStride(); int size = 1 << bits; byte[] comp = new byte[size]; for (int i = 0; i < size; i++) comp[i] = (byte)(255 * i / (size - 1)); colorModel = new IndexColorModel(bits, size, comp, comp, comp); } return colorModel; } public static int getElementSize(SampleModel sm) { int elementSize = DataBuffer.getDataTypeSize(sm.getDataType()); if (sm instanceof MultiPixelPackedSampleModel) { MultiPixelPackedSampleModel mppsm = (MultiPixelPackedSampleModel)sm; return mppsm.getSampleSize(0) * mppsm.getNumBands(); } else if (sm instanceof ComponentSampleModel) { return sm.getNumBands() * elementSize; } else if (sm instanceof SinglePixelPackedSampleModel) { return elementSize; } return elementSize * sm.getNumBands(); } public static long getTileSize(SampleModel sm) { int elementSize = DataBuffer.getDataTypeSize(sm.getDataType()); if (sm instanceof MultiPixelPackedSampleModel) { MultiPixelPackedSampleModel mppsm = (MultiPixelPackedSampleModel)sm; return (mppsm.getScanlineStride() * mppsm.getHeight() + (mppsm.getDataBitOffset() + elementSize -1) / elementSize) * ((elementSize + 7) / 8); } else if (sm instanceof ComponentSampleModel) { ComponentSampleModel csm = (ComponentSampleModel)sm; int[] bandOffsets = csm.getBandOffsets(); int maxBandOff = bandOffsets[0]; for (int i=1; i= 0) size += maxBandOff + 1; if (pixelStride > 0) size += pixelStride * (sm.getWidth() - 1); if (scanlineStride > 0) size += scanlineStride * (sm.getHeight() - 1); int[] bankIndices = csm.getBankIndices(); maxBandOff = bankIndices[0]; for (int i=1; i 0) size += pixelStride * (sm.getWidth() - 1); if (scanlineStride > 0) size += scanlineStride * (sm.getHeight() - 1); return size * ((elementSize + 7) / 8); } else return getTileSize(sm); } /** * Tests whether the color indices represent a gray-scale image with * the indicated number of bits over the color component range [0,255]. * The grayscale mapping may be inverted, i.e., 0 -> 255 and * mapSize -> 0. * * @param icm The gray-to-color mapping. * @return Whether the IndexColorModel maps index * i to ((255*i)/icm.getMapSize()-1). * @throws IllegalArgumentException if icm is * null. */ public static boolean isGrayscaleMapping(IndexColorModel icm) { if(icm == null) { throw new IllegalArgumentException("icm == null!"); } // Get colormap size and contents. int mapSize = icm.getMapSize(); byte[] r = new byte[mapSize]; byte[] g = new byte[mapSize]; byte[] b = new byte[mapSize]; icm.getReds(r); icm.getGreens(g); icm.getBlues(b); boolean isGrayToColor = true; // Check ascending ramp. for (int i = 0; i < mapSize; i++) { byte temp = (byte)(i*255/(mapSize - 1)); if (r[i] != temp || g[i] != temp || b[i] != temp) { isGrayToColor = false; break; } } if(!isGrayToColor) { isGrayToColor = true; // Check descending ramp. for (int i = 0, j = mapSize - 1; i < mapSize; i++, j--) { byte temp = (byte)(j*255/(mapSize - 1)); if (r[i] != temp || g[i] != temp || b[i] != temp) { isGrayToColor = false; break; } } } return isGrayToColor; } /** * Tests whether the color indices represent a gray-scale image. * * @param r The red channel color indices. * @param g The green channel color indices. * @param b The blue channel color indices. * @return If all the indices have 256 entries, and are identical mappings, * return true; otherwise, return false. */ public static boolean isIndicesForGrayscale(byte[] r, byte[] g, byte[] b) { if (r.length != g.length || r.length != b.length) return false; int size = r.length; if (size != 256) return false; for (int i = 0; i < size; i++) { byte temp = (byte) i; if (r[i] != temp || g[i] != temp || b[i] != temp) return false; } return true; } /** Converts the provided object to String */ public static String convertObjectToString(Object obj) { if (obj == null) return ""; String s = ""; if (obj instanceof byte[]) { byte[] bArray = (byte[])obj; for (int i = 0; i < bArray.length; i++) s += bArray[i] + " "; return s; } if (obj instanceof int[]) { int[] iArray = (int[])obj; for (int i = 0; i < iArray.length; i++) s += iArray[i] + " " ; return s; } if (obj instanceof short[]) { short[] sArray = (short[])obj; for (int i = 0; i < sArray.length; i++) s += sArray[i] + " " ; return s; } return obj.toString(); } /** Checks that the provided ImageWriter can encode * the provided ImageTypeSpecifier or not. If not, an * IIOException will be thrown. * @param writer The provided ImageWriter. * @param type The image to be tested. * @throws IIOException If the writer cannot encoded the provided image. */ public static final void canEncodeImage(ImageWriter writer, ImageTypeSpecifier type) throws IIOException { ImageWriterSpi spi = writer.getOriginatingProvider(); if(type != null && spi != null && !spi.canEncodeImage(type)) { throw new IIOException(I18N.getString("ImageUtil2")+" "+ writer.getClass().getName()); } } /** Checks that the provided ImageWriter can encode * the provided ColorModel and SampleModel. * If not, an IIOException will be thrown. * @param writer The provided ImageWriter. * @param colorModel The provided ColorModel. * @param sampleModel The provided SampleModel. * @throws IIOException If the writer cannot encoded the provided image. */ public static final void canEncodeImage(ImageWriter writer, ColorModel colorModel, SampleModel sampleModel) throws IIOException { ImageTypeSpecifier type = null; if (colorModel != null && sampleModel != null) type = new ImageTypeSpecifier(colorModel, sampleModel); canEncodeImage(writer, type); } /** * Returns whether the image has contiguous data across rows. */ public static final boolean imageIsContiguous(RenderedImage image) { SampleModel sm; if(image instanceof BufferedImage) { WritableRaster ras = ((BufferedImage)image).getRaster(); sm = ras.getSampleModel(); } else { sm = image.getSampleModel(); } if (sm instanceof ComponentSampleModel) { // Ensure image rows samples are stored contiguously // in a single bank. ComponentSampleModel csm = (ComponentSampleModel)sm; if (csm.getPixelStride() != csm.getNumBands()) { return false; } int[] bandOffsets = csm.getBandOffsets(); for (int i = 0; i < bandOffsets.length; i++) { if (bandOffsets[i] != i) { return false; } } int[] bankIndices = csm.getBankIndices(); for (int i = 0; i < bandOffsets.length; i++) { if (bankIndices[i] != 0) { return false; } } return true; } // Otherwise true if and only if it's a bilevel image with // a MultiPixelPackedSampleModel, 1 bit per pixel, and 1 bit // pixel stride. return ImageUtil.isBinary(sm); } /** * Gets the destination image type. */ // NOTE: Code shamelessly copied from ImageReader.getDestination(). public static final ImageTypeSpecifier getDestinationType(ImageReadParam param, Iterator imageTypes) throws IIOException { if (imageTypes == null || !imageTypes.hasNext()) { throw new IllegalArgumentException("imageTypes null or empty!"); } ImageTypeSpecifier imageType = null; // If param is non-null, use it if (param != null) { imageType = param.getDestinationType(); } // No info from param, use fallback image type if (imageType == null) { Object o = imageTypes.next(); if (!(o instanceof ImageTypeSpecifier)) { throw new IllegalArgumentException ("Non-ImageTypeSpecifier retrieved from imageTypes!"); } imageType = (ImageTypeSpecifier)o; } else { boolean foundIt = false; while (imageTypes.hasNext()) { ImageTypeSpecifier type = (ImageTypeSpecifier)imageTypes.next(); if (type.equals(imageType)) { foundIt = true; break; } } if (!foundIt) { throw new IIOException ("Destination type from ImageReadParam does not match!"); } } return imageType; } /** * Returns true if the given ColorSpace object * is an instance of ICC_ColorSpace but is not one of the * standard ColorSpaces returned by * ColorSpace.getInstance(). * * @param cs The ColorSpace to test. */ public static boolean isNonStandardICCColorSpace(ColorSpace cs) { boolean retval = false; try { // Check the standard ColorSpaces in decreasing order of // likelihood except check CS_PYCC last as in some JREs // PYCC.pf used not to be installed. retval = (cs instanceof ICC_ColorSpace) && !(cs.isCS_sRGB() || cs.equals(ColorSpace.getInstance(ColorSpace.CS_LINEAR_RGB)) || cs.equals(ColorSpace.getInstance(ColorSpace.CS_GRAY)) || cs.equals(ColorSpace.getInstance(ColorSpace.CS_CIEXYZ)) || cs.equals(ColorSpace.getInstance(ColorSpace.CS_PYCC))); } catch(IllegalArgumentException e) { // PYCC.pf not installed: ignore it - 'retval' is still 'false'. } return retval; } // Method to return JDK core ImageReaderSPI/ImageWriterSPI for a // given formatName. public static List getJDKImageReaderWriterSPI(ServiceRegistry registry, String formatName, boolean isReader) { IIORegistry iioRegistry = (IIORegistry)registry; Class spiClass; String descPart; if (isReader) { spiClass = ImageReaderSpi.class; descPart = " image reader"; } else { spiClass = ImageWriterSpi.class; descPart = " image writer"; } Iterator iter = iioRegistry.getServiceProviders(spiClass, true); // useOrdering String formatNames[]; ImageReaderWriterSpi provider; String desc = "standard " + formatName + descPart; String jiioPath = "com.sun.media.imageioimpl"; Locale locale = Locale.getDefault(); ArrayList list = new ArrayList(); while (iter.hasNext()) { provider = (ImageReaderWriterSpi)iter.next(); // Look for JDK core ImageWriterSpi's if (provider.getVendorName().startsWith("Sun Microsystems") && desc.equalsIgnoreCase(provider.getDescription(locale)) && // not JAI Image I/O plugins !provider.getPluginClassName().startsWith(jiioPath)) { // Get the formatNames supported by this Spi formatNames = provider.getFormatNames(); for (int i=0; i= deregisterJvmVersion && list.size() != 0) { // De-register JIIO's plug-in registry.deregisterServiceProvider(spi, category); } else { for (int i=0; i= priorityJvmVersion) { // Set JIIO plug-in to lower priority registry.setOrdering(category, list.get(i), spi); } else { // Set JIIO plug-in to higher priority registry.setOrdering(category, spi, list.get(i)); } } } } } public static int readMultiByteInteger(ImageInputStream iis) throws IOException { int value = iis.readByte(); int result = value & 0x7f; while((value & 0x80) == 0x80) { result <<= 7; value = iis.readByte(); result |= (value & 0x7f); } return result; } } jai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/common/SimpleRenderedImage.java0000664000175100017510000005112710203036165031753 0ustar tilletille/* * $RCSfile: SimpleRenderedImage.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.1 $ * $Date: 2005-02-11 05:01:23 $ * $State: Exp $ */ package com.sun.media.imageioimpl.common; import java.awt.Point; import java.awt.Rectangle; import java.awt.image.RenderedImage; import java.awt.image.ColorModel; import java.awt.image.SampleModel; import java.awt.image.Raster; import java.awt.image.WritableRaster; import java.util.Enumeration; import java.util.Hashtable; import java.util.Iterator; import java.util.Vector; public abstract class SimpleRenderedImage implements RenderedImage { /** The X coordinate of the image's upper-left pixel. */ protected int minX; /** The Y coordinate of the image's upper-left pixel. */ protected int minY; /** The image's width in pixels. */ protected int width; /** The image's height in pixels. */ protected int height; /** The width of a tile. */ protected int tileWidth; /** The height of a tile. */ protected int tileHeight; /** The X coordinate of the upper-left pixel of tile (0, 0). */ protected int tileGridXOffset = 0; /** The Y coordinate of the upper-left pixel of tile (0, 0). */ protected int tileGridYOffset = 0; /** The image's SampleModel. */ protected SampleModel sampleModel; /** The image's ColorModel. */ protected ColorModel colorModel; /** The image's sources, stored in a Vector. */ protected Vector sources = new Vector(); /** A Hashtable containing the image properties. */ protected Hashtable properties = new Hashtable(); /** Returns the X coordinate of the leftmost column of the image. */ public int getMinX() { return minX; } /** * Returns the X coordinate of the column immediatetely to the * right of the rightmost column of the image. getMaxX() is * implemented in terms of getMinX() and getWidth() and so does * not need to be implemented by subclasses. */ public final int getMaxX() { return getMinX() + getWidth(); } /** Returns the X coordinate of the uppermost row of the image. */ public int getMinY() { return minY; } /** * Returns the Y coordinate of the row immediately below the * bottom row of the image. getMaxY() is implemented in terms of * getMinY() and getHeight() and so does not need to be * implemented by subclasses. */ public final int getMaxY() { return getMinY() + getHeight(); } /** Returns the width of the image. */ public int getWidth() { return width; } /** Returns the height of the image. */ public int getHeight() { return height; } /** Returns a Rectangle indicating the image bounds. */ public Rectangle getBounds() { return new Rectangle(getMinX(), getMinY(), getWidth(), getHeight()); } /** Returns the width of a tile. */ public int getTileWidth() { return tileWidth; } /** Returns the height of a tile. */ public int getTileHeight() { return tileHeight; } /** * Returns the X coordinate of the upper-left pixel of tile (0, 0). */ public int getTileGridXOffset() { return tileGridXOffset; } /** * Returns the Y coordinate of the upper-left pixel of tile (0, 0). */ public int getTileGridYOffset() { return tileGridYOffset; } /** * Returns the horizontal index of the leftmost column of tiles. * getMinTileX() is implemented in terms of getMinX() * and so does not need to be implemented by subclasses. */ public int getMinTileX() { return XToTileX(getMinX()); } /** * Returns the horizontal index of the rightmost column of tiles. * getMaxTileX() is implemented in terms of getMaxX() * and so does not need to be implemented by subclasses. */ public int getMaxTileX() { return XToTileX(getMaxX() - 1); } /** * Returns the number of tiles along the tile grid in the * horizontal direction. getNumXTiles() is implemented in terms * of getMinTileX() and getMaxTileX() and so does not need to be * implemented by subclasses. */ public int getNumXTiles() { return getMaxTileX() - getMinTileX() + 1; } /** * Returns the vertical index of the uppermost row of tiles. getMinTileY() * is implemented in terms of getMinY() and so does not need to be * implemented by subclasses. */ public int getMinTileY() { return YToTileY(getMinY()); } /** * Returns the vertical index of the bottom row of tiles. getMaxTileY() * is implemented in terms of getMaxY() and so does not need to * be implemented by subclasses. */ public int getMaxTileY() { return YToTileY(getMaxY() - 1); } /** * Returns the number of tiles along the tile grid in the vertical * direction. getNumYTiles() is implemented in terms * of getMinTileY() and getMaxTileY() and so does not need to be * implemented by subclasses. */ public int getNumYTiles() { return getMaxTileY() - getMinTileY() + 1; } /** Returns the SampleModel of the image. */ public SampleModel getSampleModel() { return sampleModel; } /** Returns the ColorModel of the image. */ public ColorModel getColorModel() { return colorModel; } /** * Gets a property from the property set of this image. If the * property name is not recognized, * java.awt.Image.UndefinedProperty will be returned. * * @param name the name of the property to get, as a * String. @return a reference to the property * Object, or the value * java.awt.Image.UndefinedProperty. */ public Object getProperty(String name) { name = name.toLowerCase(); Object value = properties.get(name); return value != null ? value : java.awt.Image.UndefinedProperty; } /** * Returns a list of the properties recognized by this image. If * no properties are available, null will be * returned. * * @return an array of Strings representing valid * property names. */ public String[] getPropertyNames() { String[] names = null; if(properties.size() > 0) { names = new String[properties.size()]; int index = 0; Enumeration e = properties.keys(); while (e.hasMoreElements()) { String name = (String)e.nextElement(); names[index++] = name; } } return names; } /** * Returns an array of Strings recognized as names by * this property source that begin with the supplied prefix. If * no property names match, null will be returned. * The comparison is done in a case-independent manner. * *

The default implementation calls * getPropertyNames() and searches the list of names * for matches. * * @return an array of Strings giving the valid * property names. */ public String[] getPropertyNames(String prefix) { String propertyNames[] = getPropertyNames(); if (propertyNames == null) { return null; } prefix = prefix.toLowerCase(); Vector names = new Vector(); for (int i = 0; i < propertyNames.length; i++) { if (propertyNames[i].startsWith(prefix)) { names.addElement(propertyNames[i]); } } if (names.size() == 0) { return null; } // Copy the strings from the Vector over to a String array. String prefixNames[] = new String[names.size()]; int count = 0; for (Iterator it = names.iterator(); it.hasNext(); ) { prefixNames[count++] = (String)it.next(); } return prefixNames; } // Utility methods. /** * Converts a pixel's X coordinate into a horizontal tile index * relative to a given tile grid layout specified by its X offset * and tile width. */ public static int XToTileX(int x, int tileGridXOffset, int tileWidth) { x -= tileGridXOffset; if (x < 0) { x += 1 - tileWidth; // Force round to -infinity } return x/tileWidth; } /** * Converts a pixel's Y coordinate into a vertical tile index * relative to a given tile grid layout specified by its Y offset * and tile height. */ public static int YToTileY(int y, int tileGridYOffset, int tileHeight) { y -= tileGridYOffset; if (y < 0) { y += 1 - tileHeight; // Force round to -infinity } return y/tileHeight; } /** * Converts a pixel's X coordinate into a horizontal tile index. * This is a convenience method. No attempt is made to detect * out-of-range coordinates. * * @param x the X coordinate of a pixel. * @return the X index of the tile containing the pixel. */ public int XToTileX(int x) { return XToTileX(x, getTileGridXOffset(), getTileWidth()); } /** * Converts a pixel's Y coordinate into a vertical tile index. * This is a convenience method. No attempt is made to detect * out-of-range coordinates. * * @param y the Y coordinate of a pixel. * @return the Y index of the tile containing the pixel. */ public int YToTileY(int y) { return YToTileY(y, getTileGridYOffset(), getTileHeight()); } /** * Converts a horizontal tile index into the X coordinate of its * upper left pixel relative to a given tile grid layout specified * by its X offset and tile width. */ public static int tileXToX(int tx, int tileGridXOffset, int tileWidth) { return tx*tileWidth + tileGridXOffset; } /** * Converts a vertical tile index into the Y coordinate of * its upper left pixel relative to a given tile grid layout * specified by its Y offset and tile height. */ public static int tileYToY(int ty, int tileGridYOffset, int tileHeight) { return ty*tileHeight + tileGridYOffset; } /** * Converts a horizontal tile index into the X coordinate of its * upper left pixel. This is a convenience method. No attempt is made * to detect out-of-range indices. * * @param tx the horizontal index of a tile. * @return the X coordinate of the tile's upper left pixel. */ public int tileXToX(int tx) { return tx*tileWidth + tileGridXOffset; } /** * Converts a vertical tile index into the Y coordinate of its * upper left pixel. This is a convenience method. No attempt is made * to detect out-of-range indices. * * @param ty the vertical index of a tile. * @return the Y coordinate of the tile's upper left pixel. */ public int tileYToY(int ty) { return ty*tileHeight + tileGridYOffset; } public Vector getSources() { return null; } /** * Returns the entire image in a single Raster. For images with * multiple tiles this will require making a copy. * *

The returned Raster is semantically a copy. This means * that updates to the source image will not be reflected in the * returned Raster. For non-writable (immutable) source images, * the returned value may be a reference to the image's internal * data. The returned Raster should be considered non-writable; * any attempt to alter its pixel data (such as by casting it to * WritableRaster or obtaining and modifying its DataBuffer) may * result in undefined behavior. The copyData method should be * used if the returned Raster is to be modified. * * @return a Raster containing a copy of this image's data. */ public Raster getData() { Rectangle rect = new Rectangle(getMinX(), getMinY(), getWidth(), getHeight()); return getData(rect); } /** * Returns an arbitrary rectangular region of the RenderedImage * in a Raster. The rectangle of interest will be clipped against * the image bounds. * *

The returned Raster is semantically a copy. This means * that updates to the source image will not be reflected in the * returned Raster. For non-writable (immutable) source images, * the returned value may be a reference to the image's internal * data. The returned Raster should be considered non-writable; * any attempt to alter its pixel data (such as by casting it to * WritableRaster or obtaining and modifying its DataBuffer) may * result in undefined behavior. The copyData method should be * used if the returned Raster is to be modified. * * @param bounds the region of the RenderedImage to be returned. */ public Raster getData(Rectangle bounds) { // Get the image bounds. Rectangle imageBounds = getBounds(); // Check for parameter validity. if(bounds == null) { bounds = imageBounds; } else if(!bounds.intersects(imageBounds)) { throw new IllegalArgumentException(I18N.getString("SimpleRenderedImage0")); } // Determine tile limits for the prescribed bounds. int startX = XToTileX(bounds.x); int startY = YToTileY(bounds.y); int endX = XToTileX(bounds.x + bounds.width - 1); int endY = YToTileY(bounds.y + bounds.height - 1); // If the bounds are contained in a single tile, return a child // of that tile's Raster. if ((startX == endX) && (startY == endY)) { Raster tile = getTile(startX, startY); return tile.createChild(bounds.x, bounds.y, bounds.width, bounds.height, bounds.x, bounds.y, null); } else { // Recalculate the tile limits if the data bounds are not a // subset of the image bounds. if(!imageBounds.contains(bounds)) { Rectangle xsect = bounds.intersection(imageBounds); startX = XToTileX(xsect.x); startY = YToTileY(xsect.y); endX = XToTileX(xsect.x + xsect.width - 1); endY = YToTileY(xsect.y + xsect.height - 1); } // Create a WritableRaster of the desired size SampleModel sm = sampleModel.createCompatibleSampleModel(bounds.width, bounds.height); // Translate it WritableRaster dest = Raster.createWritableRaster(sm, bounds.getLocation()); // Loop over the tiles in the intersection. for (int j = startY; j <= endY; j++) { for (int i = startX; i <= endX; i++) { // Retrieve the tile. Raster tile = getTile(i, j); // Create a child of the tile for the intersection of // the tile bounds and the bounds of the requested area. Rectangle tileRect = tile.getBounds(); Rectangle intersectRect = bounds.intersection(tile.getBounds()); Raster liveRaster = tile.createChild(intersectRect.x, intersectRect.y, intersectRect.width, intersectRect.height, intersectRect.x, intersectRect.y, null); // Copy the data from the child. dest.setRect(liveRaster); } } return dest; } } /** * Copies an arbitrary rectangular region of the RenderedImage * into a caller-supplied WritableRaster. The region to be * computed is determined by clipping the bounds of the supplied * WritableRaster against the bounds of the image. The supplied * WritableRaster must have a SampleModel that is compatible with * that of the image. * *

If the raster argument is null, the entire image will * be copied into a newly-created WritableRaster with a SampleModel * that is compatible with that of the image. * * @param dest a WritableRaster to hold the returned portion of * the image. * @return a reference to the supplied WritableRaster, or to a * new WritableRaster if the supplied one was null. */ public WritableRaster copyData(WritableRaster dest) { // Get the image bounds. Rectangle imageBounds = getBounds(); Rectangle bounds; if (dest == null) { // Create a WritableRaster for the entire image. bounds = imageBounds; Point p = new Point(minX, minY); SampleModel sm = sampleModel.createCompatibleSampleModel(width, height); dest = Raster.createWritableRaster(sm, p); } else { bounds = dest.getBounds(); } // Determine tile limits for the intersection of the prescribed // bounds with the image bounds. Rectangle xsect = imageBounds.contains(bounds) ? bounds : bounds.intersection(imageBounds); int startX = XToTileX(xsect.x); int startY = YToTileY(xsect.y); int endX = XToTileX(xsect.x + xsect.width - 1); int endY = YToTileY(xsect.y + xsect.height - 1); // Loop over the tiles in the intersection. for (int j = startY; j <= endY; j++) { for (int i = startX; i <= endX; i++) { // Retrieve the tile. Raster tile = getTile(i, j); // Create a child of the tile for the intersection of // the tile bounds and the bounds of the requested area. Rectangle tileRect = tile.getBounds(); Rectangle intersectRect = bounds.intersection(tile.getBounds()); Raster liveRaster = tile.createChild(intersectRect.x, intersectRect.y, intersectRect.width, intersectRect.height, intersectRect.x, intersectRect.y, null); // Copy the data from the child. dest.setRect(liveRaster); } } return dest; } } jai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/common/LZWStringTable.java0000664000175100017510000002127210203036165030717 0ustar tilletille/* * $RCSfile: LZWStringTable.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.1 $ * $Date: 2005-02-11 05:01:23 $ * $State: Exp $ */ package com.sun.media.imageioimpl.common; import java.io.PrintStream; /** * General purpose LZW String Table. * Extracted from GIFEncoder by Adam Doppelt * Comments added by Robin Luiten * expandCode added by Robin Luiten * The strLen_ table to give quick access to the lenght of an expanded * code for use by the expandCode method added by Robin. **/ public class LZWStringTable { /** codesize + Reserved Codes */ private final static int RES_CODES = 2; private final static short HASH_FREE = (short)0xFFFF; private final static short NEXT_FIRST = (short)0xFFFF; private final static int MAXBITS = 12; private final static int MAXSTR = (1 << MAXBITS); private final static short HASHSIZE = 9973; private final static short HASHSTEP = 2039; byte[] strChr_; // after predecessor character short[] strNxt_; // predecessor string short[] strHsh_; // hash table to find predecessor + char pairs short numStrings_; // next code if adding new prestring + char /** * each entry corresponds to a code and contains the length of data * that the code expands to when decoded. **/ int[] strLen_; /** * Constructor allocate memory for string store data **/ public LZWStringTable() { strChr_ = new byte[MAXSTR]; strNxt_ = new short[MAXSTR]; strLen_ = new int[MAXSTR]; strHsh_ = new short[HASHSIZE]; } /** * @param index value of -1 indicates no predecessor [used in initialisation] * @param b the byte [character] to add to the string store which follows * the predecessor string specified the index. * @return 0xFFFF if no space in table left for addition of predecesor * index and byte b. Else return the code allocated for combination index + b. **/ public int AddCharString(short index, byte b) { int hshidx; if (numStrings_ >= MAXSTR) // if used up all codes { return 0xFFFF; } hshidx = Hash(index, b); while (strHsh_[hshidx] != HASH_FREE) hshidx = (hshidx + HASHSTEP) % HASHSIZE; strHsh_[hshidx] = numStrings_; strChr_[numStrings_] = b; if (index == HASH_FREE) { strNxt_[numStrings_] = NEXT_FIRST; strLen_[numStrings_] = 1; } else { strNxt_[numStrings_] = index; strLen_[numStrings_] = strLen_[index] + 1; } return numStrings_++; // return the code and inc for next code } /** * @param index index to prefix string * @param b the character that follws the index prefix * @return b if param index is HASH_FREE. Else return the code * for this prefix and byte successor **/ public short FindCharString(short index, byte b) { int hshidx, nxtidx; if (index == HASH_FREE) return (short)(b & 0xFF); // Rob fixed used to sign extend hshidx = Hash(index, b); while ((nxtidx = strHsh_[hshidx]) != HASH_FREE) // search { if (strNxt_[nxtidx] == index && strChr_[nxtidx] == b) return (short)nxtidx; hshidx = (hshidx + HASHSTEP) % HASHSIZE; } return (short)0xFFFF; } /** * @param codesize the size of code to be preallocated for the * string store. **/ public void ClearTable(int codesize) { numStrings_ = 0; for (int q = 0; q < HASHSIZE; q++) strHsh_[q] = HASH_FREE; int w = (1 << codesize) + RES_CODES; for (int q = 0; q < w; q++) AddCharString((short)0xFFFF, (byte)q); // init with no prefix } static public int Hash(short index, byte lastbyte) { return ((int)((short)(lastbyte << 8) ^ index) & 0xFFFF) % HASHSIZE; } /** * If expanded data doesnt fit into array only what will fit is written * to buf and the return value indicates how much of the expanded code has * been written to the buf. The next call to expandCode() should be with * the same code and have the skip parameter set the negated value of the * previous return. Succesive negative return values should be negated and * added together for next skip parameter value with same code. * * @param buf buffer to place expanded data into * @param offset offset to place expanded data * @param code the code to expand to the byte array it represents. * PRECONDITION This code must allready be in the LZSS * @param skipHead is the number of bytes at the start of the expanded code to * be skipped before data is written to buf. It is possible that skipHead is * equal to codeLen. * @return the length of data expanded into buf. If the expanded code is longer * than space left in buf then the value returned is a negative number which when * negated is equal to the number of bytes that were used of the code being expanded. * This negative value also indicates the buffer is full. **/ public int expandCode(byte[] buf, int offset, short code, int skipHead) { if (offset == -2) { if (skipHead == 1) skipHead = 0; } if (code == (short)0xFFFF || // just in case skipHead == strLen_[code]) // DONE no more unpacked return 0; int expandLen; // how much data we are actually expanding int codeLen = strLen_[code] - skipHead; // length of expanded code left int bufSpace = buf.length - offset; // how much space left if (bufSpace > codeLen) expandLen = codeLen; // only got this many to unpack else expandLen = bufSpace; int skipTail = codeLen - expandLen; // only > 0 if codeLen > bufSpace [left overs] int idx = offset + expandLen; // initialise to exclusive end address of buffer area // NOTE: data unpacks in reverse direction and we are placing the // unpacked data directly into the array in the correct location. while ((idx > offset) && (code != (short)0xFFFF)) { if (--skipTail < 0) // skip required of expanded data { buf[--idx] = strChr_[code]; } code = strNxt_[code]; // to predecessor code } if (codeLen > expandLen) return -expandLen; // indicate what part of codeLen used else return expandLen; // indicate length of dat unpacked } public void dump(PrintStream out) { int i; for (i = 258; i < numStrings_; ++i) out.println( " strNxt_[" + i + "] = " + strNxt_[i] + " strChr_ " + Integer.toHexString(strChr_[i] & 0xFF) + " strLen_ " + Integer.toHexString(strLen_[i])); } } jai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/common/LZWCompressor.java0000664000175100017510000001316410203036165030636 0ustar tilletille/* * $RCSfile: LZWCompressor.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.1 $ * $Date: 2005-02-11 05:01:22 $ * $State: Exp $ */ package com.sun.media.imageioimpl.common; import java.io.IOException; import java.io.PrintStream; import javax.imageio.stream.ImageOutputStream; /** * Modified from original LZWCompressor to change interface to passing a * buffer of data to be compressed. **/ public class LZWCompressor { /** base underlying code size of data being compressed 8 for TIFF, 1 to 8 for GIF **/ int codeSize_; /** reserved clear code based on code size **/ int clearCode_; /** reserved end of data code based on code size **/ int endOfInfo_; /** current number bits output for each code **/ int numBits_; /** limit at which current number of bits code size has to be increased **/ int limit_; /** the prefix code which represents the predecessor string to current input point **/ short prefix_; /** output destination for bit codes **/ BitFile bf_; /** general purpose LZW string table **/ LZWStringTable lzss_; /** modify the limits of the code values in LZW encoding due to TIFF bug / feature **/ boolean tiffFudge_; /** * @param out destination for compressed data * @param codeSize the initial code size for the LZW compressor * @param TIFF flag indicating that TIFF lzw fudge needs to be applied * @exception IOException if underlying output stream error **/ public LZWCompressor(ImageOutputStream out, int codeSize, boolean TIFF) throws IOException { bf_ = new BitFile(out, !TIFF); // set flag for GIF as NOT tiff codeSize_ = codeSize; tiffFudge_ = TIFF; clearCode_ = 1 << codeSize_; endOfInfo_ = clearCode_ + 1; numBits_ = codeSize_ + 1; limit_ = (1 << numBits_) - 1; if (tiffFudge_) --limit_; prefix_ = (short)0xFFFF; lzss_ = new LZWStringTable(); lzss_.ClearTable(codeSize_); bf_.writeBits(clearCode_, numBits_); } /** * @param buf data to be compressed to output stream * @exception IOException if underlying output stream error **/ public void compress(byte[] buf, int offset, int length) throws IOException { int idx; byte c; short index; int maxOffset = offset + length; for (idx = offset; idx < maxOffset; ++idx) { c = buf[idx]; if ((index = lzss_.FindCharString(prefix_, c)) != -1) prefix_ = index; else { bf_.writeBits(prefix_, numBits_); if (lzss_.AddCharString(prefix_, c) > limit_) { if (numBits_ == 12) { bf_.writeBits(clearCode_, numBits_); lzss_.ClearTable(codeSize_); numBits_ = codeSize_ + 1; } else ++numBits_; limit_ = (1 << numBits_) - 1; if (tiffFudge_) --limit_; } prefix_ = (short)((short)c & 0xFF); } } } /** * Indicate to compressor that no more data to go so write out * any remaining buffered data. * * @exception IOException if underlying output stream error **/ public void flush() throws IOException { if (prefix_ != -1) bf_.writeBits(prefix_, numBits_); bf_.writeBits(endOfInfo_, numBits_); bf_.flush(); } public void dump(PrintStream out) { lzss_.dump(out); } } jai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/common/properties0000664000175100017510000000101310203036165027347 0ustar tilletille# # $RCSfile: properties,v $ # # Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved. # # Use is subject to license terms. # # $Revision: 1.1 $ # $Date: 2005-02-11 05:01:24 $ # $State: Exp $ # # Internationalization file for com.sun.media.imageioimpl.common ImageUtil0=The supplied Raster does not represent a binary data set. ImageUtil1=The provided sample model is null. ImageUtil2=The provided image cannot be encoded using: SimpleRenderedImage0=The provided region doesn't intersect with the image bounds. jai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/common/PackageUtil.java0000664000175100017510000001173010413303155030272 0ustar tilletille/* * $RCSfile: PackageUtil.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.3 $ * $Date: 2006-03-31 19:43:38 $ * $State: Exp $ */ package com.sun.media.imageioimpl.common; import java.security.AccessController; import java.security.PrivilegedAction; import com.sun.medialib.codec.jiio.Util; public class PackageUtil { /** * Flag indicating whether codecLib is available. */ private static boolean isCodecLibAvailable = false; /** * Implementation version derived from Manifest. */ private static String version = "1.0"; /** * Implementation vendor derived from Manifest. */ private static String vendor = "Sun Microsystems, Inc."; /** * Specification Title derived from Manifest. */ private static String specTitle = "Java Advanced Imaging Image I/O Tools"; /** * Set static flags. */ static { // Set codecLib flag. try { // Check for codecLib availability. isCodecLibAvailable = Util.isCodecLibAvailable(); } catch(Throwable e) { // A Throwable is equivalent to unavailable. Throwable is used // in case an Error rather than an Exception is thrown. isCodecLibAvailable = false; } // Set version and vendor strings. try { Class thisClass = Class.forName("com.sun.media.imageioimpl.common.PackageUtil"); Package thisPackage = thisClass.getPackage(); version = thisPackage.getImplementationVersion(); vendor = thisPackage.getImplementationVendor(); specTitle = thisPackage.getSpecificationTitle(); } catch(ClassNotFoundException e) { } } /** * Returns a boolean indicating whether codecLib is available. */ public static final boolean isCodecLibAvailable() { // Retrieve value of system property here to allow this to be // modified dynamically. Boolean result = (Boolean) AccessController.doPrivileged(new PrivilegedAction() { public Object run() { String property = null; try { property = System.getProperty("com.sun.media.imageio.disableCodecLib"); } catch(SecurityException se) { // Do nothing: leave 'property' null. } return (property != null && property.equalsIgnoreCase("true")) ? Boolean.TRUE : Boolean.FALSE; } }); boolean isCodecLibDisabled = result.booleanValue(); return isCodecLibAvailable && !isCodecLibDisabled; } /** * Return a version string for the package. */ public static final String getVersion() { return version; } /** * Return a vendor string for the package. */ public static final String getVendor() { return vendor; } /** * Return the Specification Title string for the package. */ public static final String getSpecificationTitle() { return specTitle; } } jai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/common/I18NImpl.java0000664000175100017510000000631110203036165027402 0ustar tilletille/* * $RCSfile: I18NImpl.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.1 $ * $Date: 2005-02-11 05:01:22 $ * $State: Exp $ */ package com.sun.media.imageioimpl.common; import java.io.InputStream; import java.util.PropertyResourceBundle; /** * Class to simplify use of internationalization message strings. * Property files are constructed in terms of content as for JAI with * one "key=value" pair per line. All such files however have the same * name "properties". The resource extractor resolves the extraction of * the file from the jar as the package name is included automatically. * *

Extenders need only provide a static method * getString(String) which calls the static method in this * class with the name of the invoking class and returns a * String. */ public class I18NImpl { /** * Returns the message string with the specified key from the * "properties" file in the package containing the class with * the specified name. */ protected static final String getString(String className, String key) { PropertyResourceBundle bundle = null; try { InputStream stream = Class.forName(className).getResourceAsStream("properties"); bundle = new PropertyResourceBundle(stream); } catch(Throwable e) { throw new RuntimeException(e); // Chain the exception. } return (String)bundle.handleGetObject(key); } } jai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/common/SimpleCMYKColorSpace.java0000664000175100017510000001115510375417450032005 0ustar tilletille/* * $RCSfile: SimpleCMYKColorSpace.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.5 $ * $Date: 2006-02-17 19:08:24 $ * $State: Exp $ */ package com.sun.media.imageioimpl.common; import java.awt.color.ColorSpace; /** * Singleton class representing a simple, mathematically defined CMYK * color space. */ public final class SimpleCMYKColorSpace extends ColorSpace { private static ColorSpace theInstance = null; private ColorSpace csRGB; /** The exponent for gamma correction. */ private static final double power1 = 1.0 / 2.4; public static final synchronized ColorSpace getInstance() { if(theInstance == null) { theInstance = new SimpleCMYKColorSpace(); } return theInstance; } private SimpleCMYKColorSpace() { super(TYPE_CMYK, 4); csRGB = ColorSpace.getInstance(ColorSpace.CS_LINEAR_RGB); } public boolean equals(Object o) { return o != null && o instanceof SimpleCMYKColorSpace; } public float[] toRGB(float[] colorvalue) { float C = colorvalue[0]; float M = colorvalue[1]; float Y = colorvalue[2]; float K = colorvalue[3]; float K1 = 1.0F - K; // Convert from CMYK to linear RGB. float[] rgbvalue = new float[] {K1*(1.0F - C), K1*(1.0F - M), K1*(1.0F - Y)}; // Convert from linear RGB to sRGB. for (int i = 0; i < 3; i++) { float v = rgbvalue[i]; if (v < 0.0F) v = 0.0F; if (v < 0.0031308F) { rgbvalue[i] = 12.92F * v; } else { if (v > 1.0F) v = 1.0F; rgbvalue[i] = (float)(1.055 * Math.pow(v, power1) - 0.055); } } return rgbvalue; } public float[] fromRGB(float[] rgbvalue) { // Convert from sRGB to linear RGB. for (int i = 0; i < 3; i++) { if (rgbvalue[i] < 0.040449936F) { rgbvalue[i] /= 12.92F; } else { rgbvalue[i] = (float)(Math.pow((rgbvalue[i] + 0.055)/1.055, 2.4)); } } // Convert from linear RGB to CMYK. float C = 1.0F - rgbvalue[0]; float M = 1.0F - rgbvalue[1]; float Y = 1.0F - rgbvalue[2]; float K = Math.min(C, Math.min(M, Y)); // If K == 1.0F, then C = M = Y = 1.0F. if(K != 1.0F) { float K1 = 1.0F - K; C = (C - K)/K1; M = (M - K)/K1; Y = (Y - K)/K1; } else { C = M = Y = 0.0F; } return new float[] {C, M, Y, K}; } public float[] toCIEXYZ(float[] colorvalue) { return csRGB.toCIEXYZ(toRGB(colorvalue)); } public float[] fromCIEXYZ(float[] xyzvalue) { return fromRGB(csRGB.fromCIEXYZ(xyzvalue)); } } ././@LongLink0000000000000000000000000000014500000000000011565 Lustar rootrootjai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/common/SingleTileRenderedImage.javajai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/common/SingleTileRenderedImage.java0000664000175100017510000000617110203036165032560 0ustar tilletille/* * $RCSfile: SingleTileRenderedImage.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.1 $ * $Date: 2005-02-11 05:01:23 $ * $State: Exp $ */ package com.sun.media.imageioimpl.common; import java.awt.image.ColorModel; import java.awt.image.Raster; /** * A simple class that provides RenderedImage functionality * given a Raster and a ColorModel. */ public class SingleTileRenderedImage extends SimpleRenderedImage { Raster ras; /** * Constructs a SingleTileRenderedImage based on a Raster * and a ColorModel. * * @param ras A Raster that will define tile (0, 0) of the image. * @param cm A ColorModel that will serve as the image's * ColorModel. */ public SingleTileRenderedImage(Raster ras, ColorModel colorModel) { this.ras = ras; this.tileGridXOffset = this.minX = ras.getMinX(); this.tileGridYOffset = this.minY = ras.getMinY(); this.tileWidth = this.width = ras.getWidth(); this.tileHeight = this.height = ras.getHeight(); this.sampleModel = ras.getSampleModel(); this.colorModel = colorModel; } /** * Returns the image's Raster as tile (0, 0). */ public Raster getTile(int tileX, int tileY) { if (tileX != 0 || tileY != 0) { throw new IllegalArgumentException("tileX != 0 || tileY != 0"); } return ras; } } jai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/common/BitFile.java0000664000175100017510000001414310203036165027421 0ustar tilletille/* * $RCSfile: BitFile.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.1 $ * $Date: 2005-02-11 05:01:21 $ * $State: Exp $ */ package com.sun.media.imageioimpl.common; import java.io.IOException; import javax.imageio.stream.ImageOutputStream; /** * Came from GIFEncoder initially. * Modified - to allow for output compressed data without the block counts * which breakup the compressed data stream for GIF. **/ public class BitFile { ImageOutputStream output_; byte buffer_[]; int index_; int bitsLeft_; // bits left at current index that are avail. /** note this also indicates gif format BITFile. **/ boolean blocks_ = false; /** * @param output destination for output data * @param blocks GIF LZW requires block counts for output data **/ public BitFile(ImageOutputStream output, boolean blocks) { output_ = output; blocks_ = blocks; buffer_ = new byte[256]; index_ = 0; bitsLeft_ = 8; } public void flush() throws IOException { int numBytes = index_ + (bitsLeft_ == 8 ? 0 : 1); if (numBytes > 0) { if (blocks_) output_.write(numBytes); output_.write(buffer_, 0, numBytes); buffer_[0] = 0; index_ = 0; bitsLeft_ = 8; } } public void writeBits(int bits, int numbits) throws IOException { int bitsWritten = 0; int numBytes = 255; // gif block count do { // This handles the GIF block count stuff if ((index_ == 254 && bitsLeft_ == 0) || index_ > 254) { if (blocks_) output_.write(numBytes); output_.write(buffer_, 0, numBytes); buffer_[0] = 0; index_ = 0; bitsLeft_ = 8; } if (numbits <= bitsLeft_) // bits contents fit in current index byte { if (blocks_) // GIF { buffer_[index_] |= (bits & ((1 << numbits) - 1)) << (8 - bitsLeft_); bitsWritten += numbits; bitsLeft_ -= numbits; numbits = 0; } else { buffer_[index_] |= (bits & ((1 << numbits) - 1)) << (bitsLeft_ - numbits); bitsWritten += numbits; bitsLeft_ -= numbits; numbits = 0; } } else // bits overflow from current byte to next. { if (blocks_) // GIF { // if bits > space left in current byte then the lowest order bits // of code are taken and put in current byte and rest put in next. buffer_[index_] |= (bits & ((1 << bitsLeft_) - 1)) << (8 - bitsLeft_); bitsWritten += bitsLeft_; bits >>= bitsLeft_; numbits -= bitsLeft_; buffer_[++index_] = 0; bitsLeft_ = 8; } else { // if bits > space left in current byte then the highest order bits // of code are taken and put in current byte and rest put in next. // at highest order bit location !! int topbits = (bits >>> (numbits - bitsLeft_)) & ((1 << bitsLeft_) - 1); buffer_[index_] |= topbits; numbits -= bitsLeft_; // ok this many bits gone off the top bitsWritten += bitsLeft_; buffer_[++index_] = 0; // next index bitsLeft_ = 8; } } } while (numbits != 0); } } jai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/common/I18N.java0000664000175100017510000000411010203036165026553 0ustar tilletille/* * $RCSfile: I18N.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.1 $ * $Date: 2005-02-11 05:01:22 $ * $State: Exp $ */ package com.sun.media.imageioimpl.common; final class I18N extends I18NImpl { static String getString(String key) { return getString("com.sun.media.imageioimpl.common.I18N", key); } } jai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/common/PaletteBuilder.java0000775000175100017510000003571410665655550031043 0ustar tilletille/* * $RCSfile: PaletteBuilder.java,v $ * * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.3 $ * $Date: 2007-08-31 00:06:00 $ * $State: Exp $ */ package com.sun.media.imageioimpl.common; import java.awt.Transparency; import java.awt.image.BufferedImage; import java.awt.image.RenderedImage; import java.awt.image.ColorModel; import java.awt.image.IndexColorModel; import java.awt.image.Raster; import java.awt.image.WritableRaster; import java.awt.Color; import javax.imageio.ImageTypeSpecifier; /** * This class implements the octree quantization method * as it is described in the "Graphics Gems" * (ISBN 0-12-286166-3, Chapter 4, pages 297-293) */ public class PaletteBuilder { /** * maximum of tree depth */ protected static final int MAXLEVEL = 8; protected RenderedImage src; protected ColorModel srcColorModel; protected Raster srcRaster; protected int requiredSize; protected ColorNode root; protected int numNodes; protected int maxNodes; protected int currLevel; protected int currSize; protected ColorNode[] reduceList; protected ColorNode[] palette; protected int transparency; protected ColorNode transColor; /** * Creates an image representing given image * src using IndexColorModel. * * Lossless conversion is not always possible (e.g. if number * of colors in the given image exceeds maximum palette size). * Result image then is an approximation constructed by octree * quantization method. * * @exception IllegalArgumentException if src is * null. * * @exception UnsupportedOperationException if implemented method * is unable to create approximation of src * and canCreatePalette returns false. * * @see createIndexColorModel * * @see canCreatePalette * */ public static RenderedImage createIndexedImage(RenderedImage src) { PaletteBuilder pb = new PaletteBuilder(src); pb.buildPalette(); return pb.getIndexedImage(); } /** * Creates an palette representing colors from given image * img. If number of colors in the given image exceeds * maximum palette size closest colors would be merged. * * @exception IllegalArgumentException if img is * null. * * @exception UnsupportedOperationException if implemented method * is unable to create approximation of img * and canCreatePalette returns false. * * @see createIndexedImage * * @see canCreatePalette * */ public static IndexColorModel createIndexColorModel(RenderedImage img) { PaletteBuilder pb = new PaletteBuilder(img); pb.buildPalette(); return pb.getIndexColorModel(); } /** * Returns true if PaletteBuilder is able to create * palette for given image type. * * @param type an instance of ImageTypeSpecifier to be * indexed. * * @return true if the PaletteBuilder * is likely to be able to create palette for this image type. * * @exception IllegalArgumentException if type * is null. */ public static boolean canCreatePalette(ImageTypeSpecifier type) { if (type == null) { throw new IllegalArgumentException("type == null"); } return true; } /** * Returns true if PaletteBuilder is able to create * palette for given rendered image. * * @param image an instance of RenderedImage to be * indexed. * * @return true if the PaletteBuilder * is likely to be able to create palette for this image type. * * @exception IllegalArgumentException if image * is null. */ public static boolean canCreatePalette(RenderedImage image) { if (image == null) { throw new IllegalArgumentException("image == null"); } ImageTypeSpecifier type = new ImageTypeSpecifier(image); return canCreatePalette(type); } protected RenderedImage getIndexedImage() { IndexColorModel icm = getIndexColorModel(); BufferedImage dst = new BufferedImage(src.getWidth(), src.getHeight(), BufferedImage.TYPE_BYTE_INDEXED, icm); WritableRaster wr = dst.getRaster(); int minX = src.getMinX(); int minY = src.getMinY(); for (int y =0; y < dst.getHeight(); y++) { for (int x = 0; x < dst.getWidth(); x++) { Color aColor = getSrcColor(x + minX, y + minY); wr.setSample(x, y, 0, findColorIndex(root, aColor)); } } return dst; } protected PaletteBuilder(RenderedImage src) { this(src, 256); } protected PaletteBuilder(RenderedImage src, int size) { this.src = src; this.srcColorModel = src.getColorModel(); this.srcRaster = src.getData(); this.transparency = srcColorModel.getTransparency(); if (transparency != Transparency.OPAQUE) { this.requiredSize = size - 1; transColor = new ColorNode(); transColor.isLeaf = true; } else { this.requiredSize = size; } } private Color getSrcColor(int x, int y) { int argb = srcColorModel.getRGB(srcRaster.getDataElements(x, y, null)); return new Color(argb, transparency != Transparency.OPAQUE); } protected int findColorIndex(ColorNode aNode, Color aColor) { if (transparency != Transparency.OPAQUE && aColor.getAlpha() != 0xff) { return 0; // default transparnt pixel } if (aNode.isLeaf) { return aNode.paletteIndex; } else { int childIndex = getBranchIndex(aColor, aNode.level); return findColorIndex(aNode.children[childIndex], aColor); } } protected void buildPalette() { reduceList = new ColorNode[MAXLEVEL + 1]; for (int i = 0; i < reduceList.length; i++) { reduceList[i] = null; } numNodes = 0; maxNodes = 0; root = null; currSize = 0; currLevel = MAXLEVEL; /* from the book */ int w = src.getWidth(); int h = src.getHeight(); int minX = src.getMinX(); int minY = src.getMinY(); for (int y = 0; y < h; y++) { for (int x = 0; x < w; x++) { Color aColor = getSrcColor(w - x + minX - 1, h - y + minY - 1); /* * If transparency of given image is not opaque we assume all * colors with alpha less than 1.0 as fully transparent. */ if (transparency != Transparency.OPAQUE && aColor.getAlpha() != 0xff) { transColor = insertNode(transColor, aColor, 0); } else { root = insertNode(root, aColor, 0); } if (currSize > requiredSize) { reduceTree(); } } } } protected ColorNode insertNode(ColorNode aNode, Color aColor, int aLevel) { if (aNode == null) { aNode = new ColorNode(); numNodes++; if (numNodes > maxNodes) { maxNodes = numNodes; } aNode.level = aLevel; aNode.isLeaf = (aLevel > MAXLEVEL); if (aNode.isLeaf) { currSize++; } } aNode.colorCount++; aNode.red += aColor.getRed(); aNode.green += aColor.getGreen(); aNode.blue += aColor.getBlue(); if (!aNode.isLeaf) { int branchIndex = getBranchIndex(aColor, aLevel); if (aNode.children[branchIndex] == null) { aNode.childCount++; if (aNode.childCount == 2) { aNode.nextReducible = reduceList[aLevel]; reduceList[aLevel] = aNode; } } aNode.children[branchIndex] = insertNode(aNode.children[branchIndex], aColor, aLevel + 1); } return aNode; } protected IndexColorModel getIndexColorModel() { int size = currSize; if (transparency != Transparency.OPAQUE) { size ++; // we need place for transparent color; } byte[] red = new byte[size]; byte[] green = new byte[size]; byte[] blue = new byte[size]; int index = 0; palette = new ColorNode[size]; if (transparency != Transparency.OPAQUE) { index ++; } int lastIndex = findPaletteEntry(root, index, red, green, blue); IndexColorModel icm = null; if (transparency != Transparency.OPAQUE) { icm = new IndexColorModel(8, size, red, green, blue, 0); } else { icm = new IndexColorModel(8, currSize, red, green, blue); } return icm; } protected int findPaletteEntry(ColorNode aNode, int index, byte[] red, byte[] green, byte[] blue) { if (aNode.isLeaf) { red[index] = (byte)(aNode.red/aNode.colorCount); green[index] = (byte)(aNode.green/aNode.colorCount); blue[index] = (byte)(aNode.blue/aNode.colorCount); aNode.paletteIndex = index; palette[index] = aNode; index++; } else { for (int i = 0; i < 8; i++) { if (aNode.children[i] != null) { index = findPaletteEntry(aNode.children[i], index, red, green, blue); } } } return index; } protected int getBranchIndex(Color aColor, int aLevel) { if (aLevel > MAXLEVEL || aLevel < 0) { throw new IllegalArgumentException("Invalid octree node depth: " + aLevel); } int shift = MAXLEVEL - aLevel; int red_index = 0x1 & ((0xff & aColor.getRed()) >> shift); int green_index = 0x1 & ((0xff & aColor.getGreen()) >> shift); int blue_index = 0x1 & ((0xff & aColor.getBlue()) >> shift); int index = (red_index << 2) | (green_index << 1) | blue_index; return index; } protected void reduceTree() { int level = reduceList.length - 1; while (reduceList[level] == null && level >= 0) { level--; } ColorNode thisNode = reduceList[level]; if (thisNode == null) { // nothing to reduce return; } // look for element with lower color count ColorNode pList = thisNode; int minColorCount = pList.colorCount; int cnt = 1; while (pList.nextReducible != null) { if (minColorCount > pList.nextReducible.colorCount) { thisNode = pList; minColorCount = pList.colorCount; } pList = pList.nextReducible; cnt++; } // save pointer to first reducible node // NB: current color count for node could be changed in future if (thisNode == reduceList[level]) { reduceList[level] = thisNode.nextReducible; } else { pList = thisNode.nextReducible; // we need to process it thisNode.nextReducible = pList.nextReducible; thisNode = pList; } if (thisNode.isLeaf) { return; } // reduce node int leafChildCount = thisNode.getLeafChildCount(); thisNode.isLeaf = true; currSize -= (leafChildCount - 1); int aDepth = thisNode.level; for (int i = 0; i < 8; i++) { thisNode.children[i] = freeTree(thisNode.children[i]); } thisNode.childCount = 0; } protected ColorNode freeTree(ColorNode aNode) { if (aNode == null) { return null; } for (int i = 0; i < 8; i++) { aNode.children[i] = freeTree(aNode.children[i]); } numNodes--; return null; } /** * The node of color tree. */ protected class ColorNode { public boolean isLeaf; public int childCount; ColorNode[] children; public int colorCount; public long red; public long blue; public long green; public int paletteIndex; public int level; ColorNode nextReducible; public ColorNode() { isLeaf = false; level = 0; childCount = 0; children = new ColorNode[8]; for (int i = 0; i < 8; i++) { children[i] = null; } colorCount = 0; red = green = blue = 0; paletteIndex = 0; } public int getLeafChildCount() { if (isLeaf) { return 0; } int cnt = 0; for (int i = 0; i < children.length; i++) { if (children[i] != null) { if (children[i].isLeaf) { cnt ++; } else { cnt += children[i].getLeafChildCount(); } } } return cnt; } public int getRGB() { int r = (int)red/colorCount; int g = (int)green/colorCount; int b = (int)blue/colorCount; int c = 0xff << 24 | (0xff&r) << 16 | (0xff&g) << 8 | (0xff&b); return c; } } } jai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/common/BogusColorSpace.java0000664000175100017510000001214010203036165031130 0ustar tilletille/* * $RCSfile: BogusColorSpace.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.1 $ * $Date: 2005-02-11 05:01:22 $ * $State: Exp $ */ package com.sun.media.imageioimpl.common; import java.awt.color.ColorSpace; /** * A dummy ColorSpace to enable ColorModel * for image data which do not have an innate color representation. */ public class BogusColorSpace extends ColorSpace { /** * Return the type given the number of components. * * @param numComponents The number of components in the * ColorSpace. * @exception IllegalArgumentException if numComponents * is less than 1. */ private static int getType(int numComponents) { if(numComponents < 1) { throw new IllegalArgumentException("numComponents < 1!"); } int type; switch(numComponents) { case 1: type = ColorSpace.TYPE_GRAY; break; default: // Based on the constant definitions TYPE_2CLR=12 through // TYPE_FCLR=25. This will return unknown types for // numComponents > 15. type = numComponents + 10; } return type; } /** * Constructs a bogus ColorSpace. * * @param numComponents The number of components in the * ColorSpace. * @exception IllegalArgumentException if numComponents * is less than 1. */ public BogusColorSpace(int numComponents) { super(getType(numComponents), numComponents); } // // The following methods simply copy the input array to the // output array while otherwise attempting to adhere to the // specified behavior of the methods vis-a-vis exceptions. // public float[] toRGB(float[] colorvalue) { if(colorvalue.length < getNumComponents()) { throw new ArrayIndexOutOfBoundsException ("colorvalue.length < getNumComponents()"); } float[] rgbvalue = new float[3]; System.arraycopy(colorvalue, 0, rgbvalue, 0, Math.min(3, getNumComponents())); return colorvalue; } public float[] fromRGB(float[] rgbvalue) { if(rgbvalue.length < 3) { throw new ArrayIndexOutOfBoundsException ("rgbvalue.length < 3"); } float[] colorvalue = new float[getNumComponents()]; System.arraycopy(rgbvalue, 0, colorvalue, 0, Math.min(3, colorvalue.length)); return rgbvalue; } public float[] toCIEXYZ(float[] colorvalue) { if(colorvalue.length < getNumComponents()) { throw new ArrayIndexOutOfBoundsException ("colorvalue.length < getNumComponents()"); } float[] xyzvalue = new float[3]; System.arraycopy(colorvalue, 0, xyzvalue, 0, Math.min(3, getNumComponents())); return colorvalue; } public float[] fromCIEXYZ(float[] xyzvalue) { if(xyzvalue.length < 3) { throw new ArrayIndexOutOfBoundsException ("xyzvalue.length < 3"); } float[] colorvalue = new float[getNumComponents()]; System.arraycopy(xyzvalue, 0, colorvalue, 0, Math.min(3, colorvalue.length)); return xyzvalue; } } jai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/stream/0000775000175100017510000000000011650556211025246 5ustar tilletille././@LongLink0000000000000000000000000000015000000000000011561 Lustar rootrootjai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/stream/ChannelImageInputStreamSpi.javajai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/stream/ChannelImageInputStreamSpi.j0000664000175100017510000000711110203036165032576 0ustar tilletille/* * $RCSfile: ChannelImageInputStreamSpi.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.1 $ * $Date: 2005-02-11 05:01:53 $ * $State: Exp $ */ package com.sun.media.imageioimpl.stream; import java.io.File; import java.io.InputStream; import java.io.IOException; import java.nio.channels.Channels; import java.nio.channels.FileChannel; import java.nio.channels.ReadableByteChannel; import java.util.Locale; import javax.imageio.spi.ImageInputStreamSpi; import javax.imageio.stream.FileCacheImageInputStream; import javax.imageio.stream.ImageInputStream; import javax.imageio.stream.MemoryCacheImageInputStream; import com.sun.media.imageio.stream.FileChannelImageInputStream; import com.sun.media.imageioimpl.common.PackageUtil; public class ChannelImageInputStreamSpi extends ImageInputStreamSpi { public ChannelImageInputStreamSpi() { super(PackageUtil.getVendor(), PackageUtil.getVersion(), ReadableByteChannel.class); } public ImageInputStream createInputStreamInstance(Object input, boolean useCache, File cacheDir) throws IOException { if(input == null || !(input instanceof ReadableByteChannel)) { throw new IllegalArgumentException("XXX"); } ImageInputStream stream = null; if(input instanceof FileChannel) { stream = new FileChannelImageInputStream((FileChannel)input); } else { InputStream inStream = Channels.newInputStream((ReadableByteChannel)input); if(useCache) { try { stream = new FileCacheImageInputStream(inStream, cacheDir); } catch(IOException e) { // Cache file could not be created. } } if(stream == null) { stream = new MemoryCacheImageInputStream(inStream); } } return stream; } public String getDescription(Locale locale) { return "NIO Channel ImageInputStream"; } } ././@LongLink0000000000000000000000000000015100000000000011562 Lustar rootrootjai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/stream/ChannelImageOutputStreamSpi.javajai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/stream/ChannelImageOutputStreamSpi.0000664000175100017510000001020510203036165032623 0ustar tilletille/* * $RCSfile: ChannelImageOutputStreamSpi.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.1 $ * $Date: 2005-02-11 05:01:53 $ * $State: Exp $ */ package com.sun.media.imageioimpl.stream; import java.io.File; import java.io.OutputStream; import java.io.IOException; import java.nio.channels.Channels; import java.nio.channels.FileChannel; import java.nio.channels.NonReadableChannelException; import java.nio.channels.WritableByteChannel; import java.util.Locale; import javax.imageio.spi.ImageOutputStreamSpi; import javax.imageio.stream.FileCacheImageOutputStream; import javax.imageio.stream.ImageOutputStream; import javax.imageio.stream.MemoryCacheImageOutputStream; import com.sun.media.imageio.stream.FileChannelImageOutputStream; import com.sun.media.imageioimpl.common.PackageUtil; public class ChannelImageOutputStreamSpi extends ImageOutputStreamSpi { public ChannelImageOutputStreamSpi() { super(PackageUtil.getVendor(), PackageUtil.getVersion(), WritableByteChannel.class); } public ImageOutputStream createOutputStreamInstance(Object output, boolean useCache, File cacheDir) throws IOException { if(output == null || !(output instanceof WritableByteChannel)) { throw new IllegalArgumentException ("Cannot create ImageOutputStream from "+ output.getClass().getName()); } ImageOutputStream stream = null; if(output instanceof FileChannel) { FileChannel channel = (FileChannel)output; try { // The Channel must be readable. channel.map(FileChannel.MapMode.READ_ONLY, channel.position(), 1); stream = new FileChannelImageOutputStream((FileChannel)output); } catch(NonReadableChannelException nrce) { // Ignore it. } } if(stream == null) { OutputStream outStream = Channels.newOutputStream((WritableByteChannel)output); if(useCache) { try { stream = new FileCacheImageOutputStream(outStream, cacheDir); } catch(IOException e) { // Cache file could not be created. } } if(stream == null) { stream = new MemoryCacheImageOutputStream(outStream); } } return stream; } public String getDescription(Locale locale) { return "NIO Channel ImageOutputStream"; } } jai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/0000775000175100017510000000000011650556211025434 5ustar tilletillejai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/pcx/0000775000175100017510000000000011650556211026226 5ustar tilletillejai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/pcx/PCXMetadata.java0000664000175100017510000002027710670321231031165 0ustar tilletille/* * $RCSfile: PCXMetadata.java,v $ * * * Copyright (c) 2007 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.2 $ * $Date: 2007-09-07 19:12:25 $ * $State: Exp $ */ package com.sun.media.imageioimpl.plugins.pcx; import javax.imageio.metadata.IIOInvalidTreeException; import javax.imageio.metadata.IIOMetadata; import javax.imageio.metadata.IIOMetadataFormatImpl; import javax.imageio.metadata.IIOMetadataNode; import org.w3c.dom.NamedNodeMap; import org.w3c.dom.Node; import com.sun.media.imageioimpl.common.ImageUtil; public class PCXMetadata extends IIOMetadata implements Cloneable, PCXConstants { short version; byte bitsPerPixel; boolean gotxmin, gotymin; short xmin, ymin; int vdpi, hdpi; int hsize,vsize; PCXMetadata() { super(true, null, null, null, null); reset(); } public Node getAsTree(String formatName) { if (formatName.equals(IIOMetadataFormatImpl.standardMetadataFormatName)) { return getStandardTree(); } else { throw new IllegalArgumentException("Not a recognized format!"); } } public boolean isReadOnly() { return false; } public void mergeTree(String formatName, Node root) throws IIOInvalidTreeException { if (formatName.equals(IIOMetadataFormatImpl.standardMetadataFormatName)) { if (root == null) { throw new IllegalArgumentException("root == null!"); } mergeStandardTree(root); } else { throw new IllegalArgumentException("Not a recognized format!"); } } public void reset() { version = VERSION_3_0; bitsPerPixel = 0; gotxmin = false; gotymin = false; xmin = 0; ymin = 0; vdpi = 72; hdpi = 72; hsize = 0; vsize = 0; } public IIOMetadataNode getStandardDocumentNode() { String versionString; switch(version) { case VERSION_2_5: versionString = "2.5"; break; case VERSION_2_8_W_PALETTE: versionString = "2.8 with palette"; break; case VERSION_2_8_WO_PALETTE: versionString = "2.8 without palette"; break; case VERSION_PC_WINDOWS: versionString = "PC Paintbrush for Windows"; break; case VERSION_3_0: versionString = "3.0"; break; default: // unknown versionString = null; } IIOMetadataNode documentNode = null; if(versionString != null) { documentNode = new IIOMetadataNode("Document"); IIOMetadataNode node = new IIOMetadataNode("FormatVersion"); node.setAttribute("value", versionString); documentNode.appendChild(node); } return documentNode; } public IIOMetadataNode getStandardDimensionNode() { IIOMetadataNode dimensionNode = new IIOMetadataNode("Dimension"); IIOMetadataNode node = null; // scratch node node = new IIOMetadataNode("HorizontalPixelOffset"); node.setAttribute("value", String.valueOf(xmin)); dimensionNode.appendChild(node); node = new IIOMetadataNode("VerticalPixelOffset"); node.setAttribute("value", String.valueOf(ymin)); dimensionNode.appendChild(node); node = new IIOMetadataNode("HorizontalPixelSize"); node.setAttribute("value", String.valueOf(254.0/hdpi)); dimensionNode.appendChild(node); node = new IIOMetadataNode("VerticalPixelSize"); node.setAttribute("value", String.valueOf(254.0/vdpi)); dimensionNode.appendChild(node); if(hsize != 0) { node = new IIOMetadataNode("HorizontalScreenSize"); node.setAttribute("value", String.valueOf(hsize)); dimensionNode.appendChild(node); } if(vsize != 0) { node = new IIOMetadataNode("VerticalScreenSize"); node.setAttribute("value", String.valueOf(vsize)); dimensionNode.appendChild(node); } return dimensionNode; } private void mergeStandardTree(Node root) throws IIOInvalidTreeException { Node node = root; if (!node.getNodeName().equals(IIOMetadataFormatImpl.standardMetadataFormatName)) throw new IIOInvalidTreeException("Root must be " + IIOMetadataFormatImpl.standardMetadataFormatName, node); node = node.getFirstChild(); while (node != null) { String name = node.getNodeName(); if (name.equals("Dimension")) { Node child = node.getFirstChild(); while (child != null) { String childName = child.getNodeName(); if (childName.equals("HorizontalPixelOffset")) { String hpo = getAttribute(child, "value"); xmin = Short.valueOf(hpo).shortValue(); gotxmin = true; } else if (childName.equals("VerticalPixelOffset")) { String vpo = getAttribute(child, "value"); ymin = Short.valueOf(vpo).shortValue(); gotymin = true; } else if (childName.equals("HorizontalPixelSize")) { String hps = getAttribute(child, "value"); hdpi = (int)(254.0F/Float.parseFloat(hps) + 0.5F); } else if (childName.equals("VerticalPixelSize")) { String vps = getAttribute(child, "value"); vdpi = (int)(254.0F/Float.parseFloat(vps) + 0.5F); } else if (childName.equals("HorizontalScreenSize")) { String hss = getAttribute(child, "value"); hsize = Integer.valueOf(hss).intValue(); } else if (childName.equals("VerticalScreenSize")) { String vss = getAttribute(child, "value"); vsize = Integer.valueOf(vss).intValue(); } child = child.getNextSibling(); } } node = node.getNextSibling(); } } private static String getAttribute(Node node, String attrName) { NamedNodeMap attrs = node.getAttributes(); Node attr = attrs.getNamedItem(attrName); return attr != null ? attr.getNodeValue() : null; } } jai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/pcx/PCXImageWriter.java0000664000175100017510000003035410671577166031706 0ustar tilletille/* * $RCSfile: PCXImageWriter.java,v $ * * * Copyright (c) 2007 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.2 $ * $Date: 2007-09-11 20:45:42 $ * $State: Exp $ */ package com.sun.media.imageioimpl.plugins.pcx; import java.awt.Rectangle; import java.awt.color.ColorSpace; import java.awt.image.*; import java.io.IOException; import java.nio.ByteOrder; import javax.imageio.*; import javax.imageio.metadata.IIOMetadata; import javax.imageio.stream.ImageOutputStream; import com.sun.media.imageioimpl.common.ImageUtil; public class PCXImageWriter extends ImageWriter implements PCXConstants { private ImageOutputStream ios; private Rectangle sourceRegion; private Rectangle destinationRegion; private int colorPlanes,bytesPerLine; private Raster inputRaster = null; private int scaleX,scaleY; public PCXImageWriter(PCXImageWriterSpi imageWriterSpi) { super(imageWriterSpi); } public void setOutput(Object output) { super.setOutput(output); // validates output if (output != null) { if (!(output instanceof ImageOutputStream)) throw new IllegalArgumentException("output not instance of ImageOutputStream"); ios = (ImageOutputStream) output; ios.setByteOrder(ByteOrder.LITTLE_ENDIAN); } else ios = null; } public IIOMetadata convertImageMetadata(IIOMetadata inData, ImageTypeSpecifier imageType, ImageWriteParam param) { if(inData instanceof PCXMetadata) return inData; return null; } public IIOMetadata convertStreamMetadata(IIOMetadata inData, ImageWriteParam param) { return null; } public IIOMetadata getDefaultImageMetadata(ImageTypeSpecifier imageType, ImageWriteParam param) { PCXMetadata md = new PCXMetadata(); md.bitsPerPixel = (byte) imageType.getSampleModel().getSampleSize()[0]; return md; } public IIOMetadata getDefaultStreamMetadata(ImageWriteParam param) { return null; } public void write(IIOMetadata streamMetadata, IIOImage image, ImageWriteParam param) throws IOException { if (ios == null) { throw new IllegalStateException("output stream is null"); } if (image == null) { throw new IllegalArgumentException("image is null"); } clearAbortRequest(); processImageStarted(0); if (param == null) param = getDefaultWriteParam(); boolean writeRaster = image.hasRaster(); sourceRegion = param.getSourceRegion(); SampleModel sampleModel = null; ColorModel colorModel = null; if (writeRaster) { inputRaster = image.getRaster(); sampleModel = inputRaster.getSampleModel(); colorModel = ImageUtil.createColorModel(null, sampleModel); if (sourceRegion == null) sourceRegion = inputRaster.getBounds(); else sourceRegion = sourceRegion.intersection(inputRaster.getBounds()); } else { RenderedImage input = image.getRenderedImage(); inputRaster = input.getData(); sampleModel = input.getSampleModel(); colorModel = input.getColorModel(); Rectangle rect = new Rectangle(input.getMinX(), input.getMinY(), input.getWidth(), input.getHeight()); if (sourceRegion == null) sourceRegion = rect; else sourceRegion = sourceRegion.intersection(rect); } if (sourceRegion.isEmpty()) throw new IllegalArgumentException("source region is empty"); IIOMetadata imageMetadata = image.getMetadata(); PCXMetadata pcxImageMetadata = null; ImageTypeSpecifier imageType = new ImageTypeSpecifier(colorModel, sampleModel); if(imageMetadata != null) { // Convert metadata. pcxImageMetadata = (PCXMetadata)convertImageMetadata(imageMetadata, imageType, param); } else { // Use default. pcxImageMetadata = (PCXMetadata)getDefaultImageMetadata(imageType, param); } scaleX = param.getSourceXSubsampling(); scaleY = param.getSourceYSubsampling(); int xOffset = param.getSubsamplingXOffset(); int yOffset = param.getSubsamplingYOffset(); // cache the data type; int dataType = sampleModel.getDataType(); sourceRegion.translate(xOffset, yOffset); sourceRegion.width -= xOffset; sourceRegion.height -= yOffset; int minX = sourceRegion.x / scaleX; int minY = sourceRegion.y / scaleY; int w = (sourceRegion.width + scaleX - 1) / scaleX; int h = (sourceRegion.height + scaleY - 1) / scaleY; xOffset = sourceRegion.x % scaleX; yOffset = sourceRegion.y % scaleY; destinationRegion = new Rectangle(minX, minY, w, h); boolean noTransform = destinationRegion.equals(sourceRegion); // Raw data can only handle bytes, everything greater must be ASCII. int[] sourceBands = param.getSourceBands(); boolean noSubband = true; int numBands = sampleModel.getNumBands(); if (sourceBands != null) { sampleModel = sampleModel.createSubsetSampleModel(sourceBands); colorModel = null; noSubband = false; numBands = sampleModel.getNumBands(); } else { sourceBands = new int[numBands]; for (int i = 0; i < numBands; i++) sourceBands[i] = i; } ios.writeByte(MANUFACTURER); ios.writeByte(VERSION_3_0); ios.writeByte(ENCODING); int bitsPerPixel = sampleModel.getSampleSize(0); ios.writeByte(bitsPerPixel); ios.writeShort(destinationRegion.x); // xmin ios.writeShort(destinationRegion.y); // ymin ios.writeShort(destinationRegion.x+destinationRegion.width-1); // xmax ios.writeShort(destinationRegion.y+destinationRegion.height-1); // ymax ios.writeShort(pcxImageMetadata.hdpi); ios.writeShort(pcxImageMetadata.vdpi); byte[] smallpalette = createSmallPalette(colorModel); ios.write(smallpalette); ios.writeByte(0); // reserved colorPlanes = sampleModel.getNumBands(); ios.writeByte(colorPlanes); bytesPerLine = destinationRegion.width*bitsPerPixel/8; bytesPerLine += bytesPerLine %2; ios.writeShort(bytesPerLine); if(colorModel.getColorSpace().getType()==ColorSpace.TYPE_GRAY) ios.writeShort(PALETTE_GRAYSCALE); else ios.writeShort(PALETTE_COLOR); ios.writeShort(pcxImageMetadata.hsize); ios.writeShort(pcxImageMetadata.vsize); for(int i=0;i<54;i++) ios.writeByte(0); // write image data if(colorPlanes==1 && bitsPerPixel==1) { write1Bit(); } else if(colorPlanes==1 && bitsPerPixel==4) { write4Bit(); } else { write8Bit(); } // write 256 color palette if needed if(colorPlanes==1 && bitsPerPixel==8 && colorModel.getColorSpace().getType()!=ColorSpace.TYPE_GRAY){ ios.writeByte(12); // Magic number preceding VGA 256 Color Palette Information ios.write(createLargePalette(colorModel)); } if (abortRequested()) { processWriteAborted(); } else { processImageComplete(); } } private void write4Bit() throws IOException { int[] unpacked = new int[sourceRegion.width]; int[] samples = new int[bytesPerLine]; for (int line = 0; line < sourceRegion.height; line += scaleY) { inputRaster.getSamples(sourceRegion.x, line + sourceRegion.y, sourceRegion.width, 1, 0, unpacked); int val=0,dst=0; for(int x=0,nibble=0;x= 1) { writeRLE(last, count); } processImageProgress(100.0F * line / sourceRegion.height); } } private void write1Bit() throws IOException { int[] unpacked = new int[sourceRegion.width]; int[] samples = new int[bytesPerLine]; for (int line = 0; line < sourceRegion.height; line += scaleY) { inputRaster.getSamples(sourceRegion.x, line + sourceRegion.y, sourceRegion.width, 1, 0, unpacked); int val=0,dst=0; for(int x=0,bit=1<<7;x0) val = val | bit; if(bit==1) { samples[dst++]=val; bit=1<<7; val=0; } else { bit = bit >> 1; } } int last = samples[0]; int count = 0; for (int x = 0; x < bytesPerLine; x += scaleX) { int sample = samples[x]; if (sample != last || count == 63) { writeRLE(last, count); count = 1; last = sample; } else count++; } if (count >= 1) { writeRLE(last, count); } processImageProgress(100.0F * line / sourceRegion.height); } } private void write8Bit() throws IOException { int[][] samples = new int[colorPlanes][bytesPerLine]; for(int line=0;line=1) { writeRLE(last,count); } processImageProgress(100.0F * line / sourceRegion.height); } } private void writeRLE(int val,int count) throws IOException{ if(count==1 && (val & 0xC0) != 0xC0) { ios.writeByte(val); } else { ios.writeByte(0xC0 | count); ios.writeByte(val); } } private byte[] createSmallPalette(ColorModel cm){ byte[] palette = new byte[16*3]; if(!(cm instanceof IndexColorModel)) return palette; IndexColorModel icm = (IndexColorModel) cm; if(icm.getMapSize()>16) return palette; for(int i=0,offset=0;i> 3; srcOff[j] = 7 - (x & 7); destPos[j] = i >> 3; destOff[j] = 7 - (i & 7); } int k = destinationRegion.y * lineStride; for (int line = 0; line < sourceRegion.height; line++) { readScanLine(scanline); if (line % scaleY == 0) { for (int i = 0; i < destinationRegion.width; i++) { //get the bit and assign to the data buffer of the raster int v = (scanline[srcPos[i]] >> srcOff[i]) & 1; data[k + destPos[i]] |= v << destOff[i]; } k += lineStride; } processImageProgress(100.0F * line / sourceRegion.height); } } catch (EOFException e) { } } private void read4Bit(byte[] data) throws IOException { byte[] scanline = new byte[bytesPerLine]; try { int lineStride = ((MultiPixelPackedSampleModel)sampleModel).getScanlineStride(); // cache the values to avoid duplicated computation int[] srcOff = new int[destinationRegion.width]; int[] destOff = new int[destinationRegion.width]; int[] srcPos = new int[destinationRegion.width]; int[] destPos = new int[destinationRegion.width]; for (int i = destinationRegion.x, x = sourceRegion.x, j = 0; i < destinationRegion.x + destinationRegion.width; i++, j++, x += scaleX) { srcPos[j] = x >> 1; srcOff[j] = (1 - (x & 1)) << 2; destPos[j] = i >> 1; destOff[j] = (1 - (i & 1)) << 2; } int k = destinationRegion.y * lineStride; for (int line = 0; line < sourceRegion.height; line++) { readScanLine(scanline); if (abortRequested()) break; if (line % scaleY == 0) { for (int i = 0; i < destinationRegion.width; i++) { //get the bit and assign to the data buffer of the raster int v = (scanline[srcPos[i]] >> srcOff[i]) & 0x0F; data[k + destPos[i]] |= v << destOff[i]; } k += lineStride; } processImageProgress(100.0F * line / sourceRegion.height); } }catch(EOFException e){ } } /* also handles 24 bit (three 8 bit planes) */ private void read8Bit(byte[] data) throws IOException { byte[] scanline = new byte[colorPlanes * bytesPerLine]; try { // skip until source region for (int line = 0; line < sourceRegion.y; line++) { readScanLine(scanline); } int dstOffset = destinationRegion.y * (destinationRegion.x + destinationRegion.width) * colorPlanes; for (int line = 0; line < sourceRegion.height; line++) { readScanLine(scanline); if (line % scaleY == 0) { int srcOffset = sourceRegion.x; for (int band = 0; band < colorPlanes; band++) { dstOffset += destinationRegion.x; for (int x = 0; x < destinationRegion.width; x += scaleX) { data[dstOffset++] = scanline[srcOffset + x]; } srcOffset += bytesPerLine; } } processImageProgress(100.0F * line / sourceRegion.height); } } catch (EOFException e) { } } private void readScanLine(byte[] buffer) throws IOException { int max = bytesPerLine * colorPlanes; for (int j = 0; j < max;) { int val = iis.readUnsignedByte(); if ((val & 0xC0) == 0xC0) { int count = val & ~0xC0; val = iis.readUnsignedByte(); for (int k = 0; k < count && j < max; k++) { buffer[j++] = (byte) (val & 0xFF); } } else { buffer[j++] = (byte) (val & 0xFF); } } } private void checkIndex(int imageIndex) { if (imageIndex != 0) { throw new IndexOutOfBoundsException("only one image exists in the stream"); } } private void readHeader() throws IOException { if (gotHeader) { iis.seek(128); return; } metadata = new PCXMetadata(); manufacturer = iis.readByte(); // manufacturer if (manufacturer != MANUFACTURER) throw new IllegalStateException("image is not a PCX file"); metadata.version = iis.readByte(); // version encoding = iis.readByte(); // encoding if (encoding != ENCODING) throw new IllegalStateException("image is not a PCX file, invalid encoding " + encoding); metadata.bitsPerPixel = iis.readByte(); metadata.xmin = iis.readShort(); metadata.ymin = iis.readShort(); xmax = iis.readShort(); ymax = iis.readShort(); metadata.hdpi = iis.readShort(); metadata.vdpi = iis.readShort(); iis.readFully(smallPalette); iis.readByte(); // reserved colorPlanes = iis.readByte(); bytesPerLine = iis.readShort(); paletteType = iis.readShort(); metadata.hsize = iis.readShort(); metadata.vsize = iis.readShort(); iis.skipBytes(54); // skip filler width = xmax - metadata.xmin + 1; height = ymax - metadata.ymin + 1; if (colorPlanes == 1) { if (paletteType == PALETTE_GRAYSCALE) { ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_GRAY); int[] nBits = { 8 }; colorModel = new ComponentColorModel(cs, nBits, false, false, Transparency.OPAQUE, DataBuffer.TYPE_BYTE); sampleModel = new ComponentSampleModel(DataBuffer.TYPE_BYTE, width, height, 1, width, new int[] { 0 }); } else { if (metadata.bitsPerPixel == 8) { // read palette from end of file, then reset back to image data iis.mark(); if (iis.length() == -1) { // read until eof, and work backwards while (iis.read() != -1) ; iis.seek(iis.getStreamPosition() - 256 * 3 - 1); } else { iis.seek(iis.length() - 256 * 3 - 1); } int palletteMagic = iis.read(); if(palletteMagic != 12) processWarningOccurred("Expected palette magic number 12; instead read "+ palletteMagic+" from this image."); iis.readFully(largePalette); iis.reset(); colorModel = new IndexColorModel(metadata.bitsPerPixel, 256, largePalette, 0, false); sampleModel = colorModel.createCompatibleSampleModel(width, height); } else { int msize = metadata.bitsPerPixel == 1 ? 2 : 16; colorModel = new IndexColorModel(metadata.bitsPerPixel, msize, smallPalette, 0, false); sampleModel = colorModel.createCompatibleSampleModel(width, height); } } } else { ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_sRGB); int[] nBits = { 8, 8, 8 }; colorModel = new ComponentColorModel(cs, nBits, false, false, Transparency.OPAQUE, DataBuffer.TYPE_BYTE); sampleModel = new ComponentSampleModel(DataBuffer.TYPE_BYTE, width, height, 1, width * colorPlanes, new int[] { 0, width, width * 2 }); } originalSampleModel = sampleModel; originalColorModel = colorModel; gotHeader = true; } } jai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/pcx/PCXImageWriterSpi.java0000664000175100017510000001013510667373164032352 0ustar tilletille/* * $RCSfile: PCXImageWriterSpi.java,v $ * * * Copyright (c) 2007 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.1 $ * $Date: 2007-09-05 00:21:08 $ * $State: Exp $ */ package com.sun.media.imageioimpl.plugins.pcx; import java.awt.image.*; import java.util.Locale; import javax.imageio.*; import javax.imageio.spi.*; import com.sun.media.imageioimpl.common.PackageUtil; public class PCXImageWriterSpi extends ImageWriterSpi { private static String [] readerSpiNames = {"com.sun.media.imageioimpl.plugins.pcx.PCXImageReaderSpi"}; private static String[] formatNames = {"pcx", "PCX"}; private static String[] extensions = {"pcx"}; private static String[] mimeTypes = { "image/pcx", "image/x-pcx", "image/x-windows-pcx", "image/x-pc-paintbrush" }; private boolean registered = false; public PCXImageWriterSpi() { super(PackageUtil.getVendor(), PackageUtil.getVersion(), formatNames, extensions, mimeTypes, "com.sun.media.imageioimpl.plugins.pcx.PCXImageWriter", STANDARD_OUTPUT_TYPE, readerSpiNames, false, null, null, null, null, true, null, null, null, null); } public String getDescription(Locale locale) { String desc = PackageUtil.getSpecificationTitle() + " PCX Image Writer"; return desc; } public void onRegistration(ServiceRegistry registry, Class category) { if (registered) { return; } registered = true; } public boolean canEncodeImage(ImageTypeSpecifier type) { int dataType= type.getSampleModel().getDataType(); if (dataType < DataBuffer.TYPE_BYTE || dataType > DataBuffer.TYPE_INT) return false; SampleModel sm = type.getSampleModel(); int numBands = sm.getNumBands(); if (!(numBands == 1 || numBands == 3)) return false; if (numBands == 1 && dataType != DataBuffer.TYPE_BYTE) return false; if (dataType > DataBuffer.TYPE_BYTE && !(sm instanceof SinglePixelPackedSampleModel)) return false; return true; } public ImageWriter createWriterInstance(Object extension) throws IIOException { return new PCXImageWriter(this); } } jai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/pcx/PCXImageReaderSpi.java0000664000175100017510000000751310667373164032306 0ustar tilletille/* * $RCSfile: PCXImageReaderSpi.java,v $ * * * Copyright (c) 2007 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.1 $ * $Date: 2007-09-05 00:21:08 $ * $State: Exp $ */ package com.sun.media.imageioimpl.plugins.pcx; import java.io.IOException; import java.util.Locale; import javax.imageio.*; import javax.imageio.spi.*; import javax.imageio.stream.ImageInputStream; import com.sun.media.imageioimpl.common.PackageUtil; public class PCXImageReaderSpi extends ImageReaderSpi { private static String [] writerSpiNames = {"com.sun.media.imageioimpl.plugins.pcx.PCXImageWriterSpi"}; private static String[] formatNames = {"pcx", "PCX"}; private static String[] extensions = {"pcx"}; private static String[] mimeTypes = { "image/pcx", "image/x-pcx", "image/x-windows-pcx", "image/x-pc-paintbrush" }; private boolean registered = false; public PCXImageReaderSpi() { super(PackageUtil.getVendor(), PackageUtil.getVersion(), formatNames, extensions, mimeTypes, "com.sun.media.imageioimpl.plugins.pcx.PCXImageReader", STANDARD_INPUT_TYPE, writerSpiNames, false, null, null, null, null, true, null, null, null, null); } public void onRegistration(ServiceRegistry registry, Class category) { if (registered) { return; } registered = true; } public String getDescription(Locale locale) { String desc = PackageUtil.getSpecificationTitle() + " PCX Image Reader"; return desc; } public boolean canDecodeInput(Object source) throws IOException { if (!(source instanceof ImageInputStream)) { return false; } ImageInputStream stream = (ImageInputStream)source; stream.mark(); byte b = stream.readByte(); stream.reset(); return (b==0x0A); } public ImageReader createReaderInstance(Object extension) throws IIOException { return new PCXImageReader(this); } } jai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/gif/0000775000175100017510000000000011650556207026206 5ustar tilletille././@LongLink0000000000000000000000000000015400000000000011565 Lustar rootrootjai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/gif/GIFWritableStreamMetadata.javajai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/gif/GIFWritableStreamMetada0000664000175100017510000003014610411071363032511 0ustar tilletille/* * $RCSfile: GIFWritableStreamMetadata.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.2 $ * $Date: 2006-03-24 22:30:11 $ * $State: Exp $ */ package com.sun.media.imageioimpl.plugins.gif; /* * The source for this class was copied verbatim from the source for * package com.sun.imageio.plugins.gif.GIFImageMetadata and then modified * to make the class read-write capable. */ import javax.imageio.ImageTypeSpecifier; import javax.imageio.metadata.IIOInvalidTreeException; import javax.imageio.metadata.IIOMetadata; import javax.imageio.metadata.IIOMetadataNode; import javax.imageio.metadata.IIOMetadataFormat; import javax.imageio.metadata.IIOMetadataFormatImpl; import org.w3c.dom.Node; class GIFWritableStreamMetadata extends GIFStreamMetadata { // package scope static final String NATIVE_FORMAT_NAME = "javax_imageio_gif_stream_1.0"; public GIFWritableStreamMetadata() { super(true, NATIVE_FORMAT_NAME, "com.sun.media.imageioimpl.plugins.gif.GIFStreamMetadataFormat", null, null); // initialize metadata fields by default values reset(); } public boolean isReadOnly() { return false; } public void mergeTree(String formatName, Node root) throws IIOInvalidTreeException { if (formatName.equals(nativeMetadataFormatName)) { if (root == null) { throw new IllegalArgumentException("root == null!"); } mergeNativeTree(root); } else if (formatName.equals (IIOMetadataFormatImpl.standardMetadataFormatName)) { if (root == null) { throw new IllegalArgumentException("root == null!"); } mergeStandardTree(root); } else { throw new IllegalArgumentException("Not a recognized format!"); } } public void reset() { version = null; logicalScreenWidth = UNDEFINED_INTEGER_VALUE; logicalScreenHeight = UNDEFINED_INTEGER_VALUE; colorResolution = UNDEFINED_INTEGER_VALUE; pixelAspectRatio = 0; backgroundColorIndex = 0; sortFlag = false; globalColorTable = null; } protected void mergeNativeTree(Node root) throws IIOInvalidTreeException { Node node = root; if (!node.getNodeName().equals(nativeMetadataFormatName)) { fatal(node, "Root must be " + nativeMetadataFormatName); } node = node.getFirstChild(); while (node != null) { String name = node.getNodeName(); if (name.equals("Version")) { version = getStringAttribute(node, "value", null, true, versionStrings); } else if (name.equals("LogicalScreenDescriptor")) { /* NB: At the moment we use empty strings to support undefined * integer values in tree representation. * We need to add better support for undefined/default values * later. */ logicalScreenWidth = getIntAttribute(node, "logicalScreenWidth", UNDEFINED_INTEGER_VALUE, true, true, 1, 65535); logicalScreenHeight = getIntAttribute(node, "logicalScreenHeight", UNDEFINED_INTEGER_VALUE, true, true, 1, 65535); colorResolution = getIntAttribute(node, "colorResolution", UNDEFINED_INTEGER_VALUE, true, true, 1, 8); pixelAspectRatio = getIntAttribute(node, "pixelAspectRatio", 0, true, true, 0, 255); } else if (name.equals("GlobalColorTable")) { int sizeOfGlobalColorTable = getIntAttribute(node, "sizeOfGlobalColorTable", true, 2, 256); if (sizeOfGlobalColorTable != 2 && sizeOfGlobalColorTable != 4 && sizeOfGlobalColorTable != 8 && sizeOfGlobalColorTable != 16 && sizeOfGlobalColorTable != 32 && sizeOfGlobalColorTable != 64 && sizeOfGlobalColorTable != 128 && sizeOfGlobalColorTable != 256) { fatal(node, "Bad value for GlobalColorTable attribute sizeOfGlobalColorTable!"); } backgroundColorIndex = getIntAttribute(node, "backgroundColorIndex", 0, true, true, 0, 255); sortFlag = getBooleanAttribute(node, "sortFlag", false, true); globalColorTable = getColorTable(node, "ColorTableEntry", true, sizeOfGlobalColorTable); } else { fatal(node, "Unknown child of root node!"); } node = node.getNextSibling(); } } protected void mergeStandardTree(Node root) throws IIOInvalidTreeException { Node node = root; if (!node.getNodeName() .equals(IIOMetadataFormatImpl.standardMetadataFormatName)) { fatal(node, "Root must be " + IIOMetadataFormatImpl.standardMetadataFormatName); } node = node.getFirstChild(); while (node != null) { String name = node.getNodeName(); if (name.equals("Chroma")) { Node childNode = node.getFirstChild(); while(childNode != null) { String childName = childNode.getNodeName(); if (childName.equals("Palette")) { globalColorTable = getColorTable(childNode, "PaletteEntry", false, -1); } else if (childName.equals("BackgroundIndex")) { backgroundColorIndex = getIntAttribute(childNode, "value", -1, true, true, 0, 255); } childNode = childNode.getNextSibling(); } } else if (name.equals("Data")) { Node childNode = node.getFirstChild(); while(childNode != null) { String childName = childNode.getNodeName(); if (childName.equals("BitsPerSample")) { colorResolution = getIntAttribute(childNode, "value", -1, true, true, 1, 8); break; } childNode = childNode.getNextSibling(); } } else if (name.equals("Dimension")) { Node childNode = node.getFirstChild(); while(childNode != null) { String childName = childNode.getNodeName(); if (childName.equals("PixelAspectRatio")) { float aspectRatio = getFloatAttribute(childNode, "value"); if (aspectRatio == 1.0F) { pixelAspectRatio = 0; } else { int ratio = (int)(aspectRatio*64.0F - 15.0F); pixelAspectRatio = Math.max(Math.min(ratio, 255), 0); } } else if (childName.equals("HorizontalScreenSize")) { logicalScreenWidth = getIntAttribute(childNode, "value", -1, true, true, 1, 65535); } else if (childName.equals("VerticalScreenSize")) { logicalScreenHeight = getIntAttribute(childNode, "value", -1, true, true, 1, 65535); } childNode = childNode.getNextSibling(); } } else if (name.equals("Document")) { Node childNode = node.getFirstChild(); while(childNode != null) { String childName = childNode.getNodeName(); if (childName.equals("FormatVersion")) { String formatVersion = getStringAttribute(childNode, "value", null, true, null); for (int i = 0; i < versionStrings.length; i++) { if (formatVersion.equals(versionStrings[i])) { version = formatVersion; break; } } break; } childNode = childNode.getNextSibling(); } } node = node.getNextSibling(); } } public void setFromTree(String formatName, Node root) throws IIOInvalidTreeException { reset(); mergeTree(formatName, root); } } jai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/gif/GIFStreamMetadata.java0000775000175100017510000003112410411071363032264 0ustar tilletille/* * $RCSfile: GIFStreamMetadata.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.1 $ * $Date: 2006-03-24 22:30:10 $ * $State: Exp $ */ package com.sun.media.imageioimpl.plugins.gif; import javax.imageio.ImageTypeSpecifier; import javax.imageio.metadata.IIOInvalidTreeException; import javax.imageio.metadata.IIOMetadata; import javax.imageio.metadata.IIOMetadataNode; import javax.imageio.metadata.IIOMetadataFormat; import javax.imageio.metadata.IIOMetadataFormatImpl; import org.w3c.dom.Node; // TODO - document elimination of globalColorTableFlag /** * @version 0.5 */ public class GIFStreamMetadata extends GIFMetadata { // package scope static final String nativeMetadataFormatName = "javax_imageio_gif_stream_1.0"; public static final String[] versionStrings = { "87a", "89a" }; public String version; // 87a or 89a public int logicalScreenWidth; public int logicalScreenHeight; public int colorResolution; // 1 to 8 public int pixelAspectRatio; public int backgroundColorIndex; // Valid if globalColorTable != null public boolean sortFlag; // Valid if globalColorTable != null public static final String[] colorTableSizes = { "2", "4", "8", "16", "32", "64", "128", "256" }; // Set global color table flag in header to 0 if null, 1 otherwise public byte[] globalColorTable = null; protected GIFStreamMetadata(boolean standardMetadataFormatSupported, String nativeMetadataFormatName, String nativeMetadataFormatClassName, String[] extraMetadataFormatNames, String[] extraMetadataFormatClassNames) { super(standardMetadataFormatSupported, nativeMetadataFormatName, nativeMetadataFormatClassName, extraMetadataFormatNames, extraMetadataFormatClassNames); } public GIFStreamMetadata() { this(true, nativeMetadataFormatName, "com.sun.media.imageioimpl.plugins.gif.GIFStreamMetadataFormat", null, null); } public boolean isReadOnly() { return true; } public Node getAsTree(String formatName) { if (formatName.equals(nativeMetadataFormatName)) { return getNativeTree(); } else if (formatName.equals (IIOMetadataFormatImpl.standardMetadataFormatName)) { return getStandardTree(); } else { throw new IllegalArgumentException("Not a recognized format!"); } } private Node getNativeTree() { IIOMetadataNode node; // scratch node IIOMetadataNode root = new IIOMetadataNode(nativeMetadataFormatName); node = new IIOMetadataNode("Version"); node.setAttribute("value", version); root.appendChild(node); // Image descriptor node = new IIOMetadataNode("LogicalScreenDescriptor"); /* NB: At the moment we use empty strings to support undefined * integer values in tree representation. * We need to add better support for undefined/default values later. */ node.setAttribute("logicalScreenWidth", logicalScreenWidth == UNDEFINED_INTEGER_VALUE ? "" : Integer.toString(logicalScreenWidth)); node.setAttribute("logicalScreenHeight", logicalScreenHeight == UNDEFINED_INTEGER_VALUE ? "" : Integer.toString(logicalScreenHeight)); // Stored value plus one node.setAttribute("colorResolution", colorResolution == UNDEFINED_INTEGER_VALUE ? "" : Integer.toString(colorResolution)); node.setAttribute("pixelAspectRatio", Integer.toString(pixelAspectRatio)); root.appendChild(node); if (globalColorTable != null) { node = new IIOMetadataNode("GlobalColorTable"); int numEntries = globalColorTable.length/3; node.setAttribute("sizeOfGlobalColorTable", Integer.toString(numEntries)); node.setAttribute("backgroundColorIndex", Integer.toString(backgroundColorIndex)); node.setAttribute("sortFlag", sortFlag ? "TRUE" : "FALSE"); for (int i = 0; i < numEntries; i++) { IIOMetadataNode entry = new IIOMetadataNode("ColorTableEntry"); entry.setAttribute("index", Integer.toString(i)); int r = globalColorTable[3*i] & 0xff; int g = globalColorTable[3*i + 1] & 0xff; int b = globalColorTable[3*i + 2] & 0xff; entry.setAttribute("red", Integer.toString(r)); entry.setAttribute("green", Integer.toString(g)); entry.setAttribute("blue", Integer.toString(b)); node.appendChild(entry); } root.appendChild(node); } return root; } public IIOMetadataNode getStandardChromaNode() { IIOMetadataNode chroma_node = new IIOMetadataNode("Chroma"); IIOMetadataNode node = null; // scratch node node = new IIOMetadataNode("ColorSpaceType"); node.setAttribute("name", "RGB"); chroma_node.appendChild(node); node = new IIOMetadataNode("BlackIsZero"); node.setAttribute("value", "TRUE"); chroma_node.appendChild(node); // NumChannels not in stream // Gamma not in format if (globalColorTable != null) { node = new IIOMetadataNode("Palette"); int numEntries = globalColorTable.length/3; for (int i = 0; i < numEntries; i++) { IIOMetadataNode entry = new IIOMetadataNode("PaletteEntry"); entry.setAttribute("index", Integer.toString(i)); entry.setAttribute("red", Integer.toString(globalColorTable[3*i] & 0xff)); entry.setAttribute("green", Integer.toString(globalColorTable[3*i + 1] & 0xff)); entry.setAttribute("blue", Integer.toString(globalColorTable[3*i + 2] & 0xff)); node.appendChild(entry); } chroma_node.appendChild(node); // backgroundColorIndex is valid iff there is a color table node = new IIOMetadataNode("BackgroundIndex"); node.setAttribute("value", Integer.toString(backgroundColorIndex)); chroma_node.appendChild(node); } return chroma_node; } public IIOMetadataNode getStandardCompressionNode() { IIOMetadataNode compression_node = new IIOMetadataNode("Compression"); IIOMetadataNode node = null; // scratch node node = new IIOMetadataNode("CompressionTypeName"); node.setAttribute("value", "lzw"); compression_node.appendChild(node); node = new IIOMetadataNode("Lossless"); node.setAttribute("value", "true"); compression_node.appendChild(node); // NumProgressiveScans not in stream // BitRate not in format return compression_node; } public IIOMetadataNode getStandardDataNode() { IIOMetadataNode data_node = new IIOMetadataNode("Data"); IIOMetadataNode node = null; // scratch node // PlanarConfiguration node = new IIOMetadataNode("SampleFormat"); node.setAttribute("value", "Index"); data_node.appendChild(node); node = new IIOMetadataNode("BitsPerSample"); node.setAttribute("value", colorResolution == UNDEFINED_INTEGER_VALUE ? "" : Integer.toString(colorResolution)); data_node.appendChild(node); // SignificantBitsPerSample // SampleMSB return data_node; } public IIOMetadataNode getStandardDimensionNode() { IIOMetadataNode dimension_node = new IIOMetadataNode("Dimension"); IIOMetadataNode node = null; // scratch node node = new IIOMetadataNode("PixelAspectRatio"); float aspectRatio = 1.0F; if (pixelAspectRatio != 0) { aspectRatio = (pixelAspectRatio + 15)/64.0F; } node.setAttribute("value", Float.toString(aspectRatio)); dimension_node.appendChild(node); node = new IIOMetadataNode("ImageOrientation"); node.setAttribute("value", "Normal"); dimension_node.appendChild(node); // HorizontalPixelSize not in format // VerticalPixelSize not in format // HorizontalPhysicalPixelSpacing not in format // VerticalPhysicalPixelSpacing not in format // HorizontalPosition not in format // VerticalPosition not in format // HorizontalPixelOffset not in stream // VerticalPixelOffset not in stream node = new IIOMetadataNode("HorizontalScreenSize"); node.setAttribute("value", logicalScreenWidth == UNDEFINED_INTEGER_VALUE ? "" : Integer.toString(logicalScreenWidth)); dimension_node.appendChild(node); node = new IIOMetadataNode("VerticalScreenSize"); node.setAttribute("value", logicalScreenHeight == UNDEFINED_INTEGER_VALUE ? "" : Integer.toString(logicalScreenHeight)); dimension_node.appendChild(node); return dimension_node; } public IIOMetadataNode getStandardDocumentNode() { IIOMetadataNode document_node = new IIOMetadataNode("Document"); IIOMetadataNode node = null; // scratch node node = new IIOMetadataNode("FormatVersion"); node.setAttribute("value", version); document_node.appendChild(node); // SubimageInterpretation not in format // ImageCreationTime not in format // ImageModificationTime not in format return document_node; } public IIOMetadataNode getStandardTextNode() { // Not in stream return null; } public IIOMetadataNode getStandardTransparencyNode() { // Not in stream return null; } public void setFromTree(String formatName, Node root) throws IIOInvalidTreeException { throw new IllegalStateException("Metadata is read-only!"); } protected void mergeNativeTree(Node root) throws IIOInvalidTreeException { throw new IllegalStateException("Metadata is read-only!"); } protected void mergeStandardTree(Node root) throws IIOInvalidTreeException { throw new IllegalStateException("Metadata is read-only!"); } public void reset() { throw new IllegalStateException("Metadata is read-only!"); } } ././@LongLink0000000000000000000000000000015200000000000011563 Lustar rootrootjai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/gif/GIFStreamMetadataFormat.javajai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/gif/GIFStreamMetadataFormat0000775000175100017510000001224210411071363032515 0ustar tilletille/* * $RCSfile: GIFStreamMetadataFormat.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.1 $ * $Date: 2006-03-24 22:30:10 $ * $State: Exp $ */ package com.sun.media.imageioimpl.plugins.gif; import java.util.Arrays; import javax.imageio.ImageTypeSpecifier; import javax.imageio.metadata.IIOMetadataFormat; import javax.imageio.metadata.IIOMetadataFormatImpl; public class GIFStreamMetadataFormat extends IIOMetadataFormatImpl { private static IIOMetadataFormat instance = null; private GIFStreamMetadataFormat() { super(GIFStreamMetadata.nativeMetadataFormatName, CHILD_POLICY_SOME); // root -> Version addElement("Version", GIFStreamMetadata.nativeMetadataFormatName, CHILD_POLICY_EMPTY); addAttribute("Version", "value", DATATYPE_STRING, true, null, Arrays.asList(GIFStreamMetadata.versionStrings)); // root -> LogicalScreenDescriptor addElement("LogicalScreenDescriptor", GIFStreamMetadata.nativeMetadataFormatName, CHILD_POLICY_EMPTY); addAttribute("LogicalScreenDescriptor", "logicalScreenWidth", DATATYPE_INTEGER, true, null, "1", "65535", true, true); addAttribute("LogicalScreenDescriptor", "logicalScreenHeight", DATATYPE_INTEGER, true, null, "1", "65535", true, true); addAttribute("LogicalScreenDescriptor", "colorResolution", DATATYPE_INTEGER, true, null, "1", "8", true, true); addAttribute("LogicalScreenDescriptor", "pixelAspectRatio", DATATYPE_INTEGER, true, null, "0", "255", true, true); // root -> GlobalColorTable addElement("GlobalColorTable", GIFStreamMetadata.nativeMetadataFormatName, 2, 256); addAttribute("GlobalColorTable", "sizeOfGlobalColorTable", DATATYPE_INTEGER, true, null, Arrays.asList(GIFStreamMetadata.colorTableSizes)); addAttribute("GlobalColorTable", "backgroundColorIndex", DATATYPE_INTEGER, true, null, "0", "255", true, true); addBooleanAttribute("GlobalColorTable", "sortFlag", false, false); // root -> GlobalColorTable -> ColorTableEntry addElement("ColorTableEntry", "GlobalColorTable", CHILD_POLICY_EMPTY); addAttribute("ColorTableEntry", "index", DATATYPE_INTEGER, true, null, "0", "255", true, true); addAttribute("ColorTableEntry", "red", DATATYPE_INTEGER, true, null, "0", "255", true, true); addAttribute("ColorTableEntry", "green", DATATYPE_INTEGER, true, null, "0", "255", true, true); addAttribute("ColorTableEntry", "blue", DATATYPE_INTEGER, true, null, "0", "255", true, true); } public boolean canNodeAppear(String elementName, ImageTypeSpecifier imageType) { return true; } public static synchronized IIOMetadataFormat getInstance() { if (instance == null) { instance = new GIFStreamMetadataFormat(); } return instance; } } jai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/gif/GIFMetadata.java0000664000175100017510000003100610411071363031104 0ustar tilletille/* * $RCSfile: GIFMetadata.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.2 $ * $Date: 2006-03-24 22:30:10 $ * $State: Exp $ */ package com.sun.media.imageioimpl.plugins.gif; import javax.imageio.metadata.IIOInvalidTreeException; import javax.imageio.metadata.IIOMetadata; import javax.imageio.metadata.IIOMetadataFormatImpl; import org.w3c.dom.Node; /** * Class which adds utility DOM element attribute access methods to * IIOMetadata for subclass use. */ abstract class GIFMetadata extends IIOMetadata { /** * Represents an undefined value of integer attributes. */ static final int UNDEFINED_INTEGER_VALUE = -1; // // Note: These attribute methods were shamelessly lifted from // com.sun.imageio.plugins.png.PNGMetadata and modified. // // Shorthand for throwing an IIOInvalidTreeException protected static void fatal(Node node, String reason) throws IIOInvalidTreeException { throw new IIOInvalidTreeException(reason, node); } // Get an integer-valued attribute protected static String getStringAttribute(Node node, String name, String defaultValue, boolean required, String[] range) throws IIOInvalidTreeException { Node attr = node.getAttributes().getNamedItem(name); if (attr == null) { if (!required) { return defaultValue; } else { fatal(node, "Required attribute " + name + " not present!"); } } String value = attr.getNodeValue(); if (range != null) { if (value == null) { fatal(node, "Null value for "+node.getNodeName()+ " attribute "+name+"!"); } boolean validValue = false; int len = range.length; for (int i = 0; i < len; i++) { if (value.equals(range[i])) { validValue = true; break; } } if (!validValue) { fatal(node, "Bad value for "+node.getNodeName()+ " attribute "+name+"!"); } } return value; } // Get an integer-valued attribute protected static int getIntAttribute(Node node, String name, int defaultValue, boolean required, boolean bounded, int min, int max) throws IIOInvalidTreeException { String value = getStringAttribute(node, name, null, required, null); if (value == null || "".equals(value)) { return defaultValue; } int intValue = defaultValue; try { intValue = Integer.parseInt(value); } catch (NumberFormatException e) { fatal(node, "Bad value for "+node.getNodeName()+ " attribute "+name+"!"); } if (bounded && (intValue < min || intValue > max)) { fatal(node, "Bad value for "+node.getNodeName()+ " attribute "+name+"!"); } return intValue; } // Get a float-valued attribute protected static float getFloatAttribute(Node node, String name, float defaultValue, boolean required) throws IIOInvalidTreeException { String value = getStringAttribute(node, name, null, required, null); if (value == null) { return defaultValue; } return Float.parseFloat(value); } // Get a required integer-valued attribute protected static int getIntAttribute(Node node, String name, boolean bounded, int min, int max) throws IIOInvalidTreeException { return getIntAttribute(node, name, -1, true, bounded, min, max); } // Get a required float-valued attribute protected static float getFloatAttribute(Node node, String name) throws IIOInvalidTreeException { return getFloatAttribute(node, name, -1.0F, true); } // Get a boolean-valued attribute protected static boolean getBooleanAttribute(Node node, String name, boolean defaultValue, boolean required) throws IIOInvalidTreeException { Node attr = node.getAttributes().getNamedItem(name); if (attr == null) { if (!required) { return defaultValue; } else { fatal(node, "Required attribute " + name + " not present!"); } } String value = attr.getNodeValue(); // XXX Should be able to use equals() here instead of // equalsIgnoreCase() but some boolean attributes are incorrectly // set to "true" or "false" by the J2SE core metadata classes // getAsTree() method (which are duplicated above). See bug 5082756. if (value.equalsIgnoreCase("TRUE")) { return true; } else if (value.equalsIgnoreCase("FALSE")) { return false; } else { fatal(node, "Attribute " + name + " must be 'TRUE' or 'FALSE'!"); return false; } } // Get a required boolean-valued attribute protected static boolean getBooleanAttribute(Node node, String name) throws IIOInvalidTreeException { return getBooleanAttribute(node, name, false, true); } // Get an enumerated attribute as an index into a String array protected static int getEnumeratedAttribute(Node node, String name, String[] legalNames, int defaultValue, boolean required) throws IIOInvalidTreeException { Node attr = node.getAttributes().getNamedItem(name); if (attr == null) { if (!required) { return defaultValue; } else { fatal(node, "Required attribute " + name + " not present!"); } } String value = attr.getNodeValue(); for (int i = 0; i < legalNames.length; i++) { if(value.equals(legalNames[i])) { return i; } } fatal(node, "Illegal value for attribute " + name + "!"); return -1; } // Get a required enumerated attribute as an index into a String array protected static int getEnumeratedAttribute(Node node, String name, String[] legalNames) throws IIOInvalidTreeException { return getEnumeratedAttribute(node, name, legalNames, -1, true); } // Get a String-valued attribute protected static String getAttribute(Node node, String name, String defaultValue, boolean required) throws IIOInvalidTreeException { Node attr = node.getAttributes().getNamedItem(name); if (attr == null) { if (!required) { return defaultValue; } else { fatal(node, "Required attribute " + name + " not present!"); } } return attr.getNodeValue(); } // Get a required String-valued attribute protected static String getAttribute(Node node, String name) throws IIOInvalidTreeException { return getAttribute(node, name, null, true); } protected GIFMetadata(boolean standardMetadataFormatSupported, String nativeMetadataFormatName, String nativeMetadataFormatClassName, String[] extraMetadataFormatNames, String[] extraMetadataFormatClassNames) { super(standardMetadataFormatSupported, nativeMetadataFormatName, nativeMetadataFormatClassName, extraMetadataFormatNames, extraMetadataFormatClassNames); } public void mergeTree(String formatName, Node root) throws IIOInvalidTreeException { if (formatName.equals(nativeMetadataFormatName)) { if (root == null) { throw new IllegalArgumentException("root == null!"); } mergeNativeTree(root); } else if (formatName.equals (IIOMetadataFormatImpl.standardMetadataFormatName)) { if (root == null) { throw new IllegalArgumentException("root == null!"); } mergeStandardTree(root); } else { throw new IllegalArgumentException("Not a recognized format!"); } } protected byte[] getColorTable(Node colorTableNode, String entryNodeName, boolean lengthExpected, int expectedLength) throws IIOInvalidTreeException { byte[] red = new byte[256]; byte[] green = new byte[256]; byte[] blue = new byte[256]; int maxIndex = -1; Node entry = colorTableNode.getFirstChild(); if (entry == null) { fatal(colorTableNode, "Palette has no entries!"); } while (entry != null) { if (!entry.getNodeName().equals(entryNodeName)) { fatal(colorTableNode, "Only a "+entryNodeName+" may be a child of a "+ entry.getNodeName()+"!"); } int index = getIntAttribute(entry, "index", true, 0, 255); if (index > maxIndex) { maxIndex = index; } red[index] = (byte)getIntAttribute(entry, "red", true, 0, 255); green[index] = (byte)getIntAttribute(entry, "green", true, 0, 255); blue[index] = (byte)getIntAttribute(entry, "blue", true, 0, 255); entry = entry.getNextSibling(); } int numEntries = maxIndex + 1; if (lengthExpected && numEntries != expectedLength) { fatal(colorTableNode, "Unexpected length for palette!"); } byte[] colorTable = new byte[3*numEntries]; for (int i = 0, j = 0; i < numEntries; i++) { colorTable[j++] = red[i]; colorTable[j++] = green[i]; colorTable[j++] = blue[i]; } return colorTable; } protected abstract void mergeNativeTree(Node root) throws IIOInvalidTreeException; protected abstract void mergeStandardTree(Node root) throws IIOInvalidTreeException; } jai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/gif/GIFImageWriterSpi.java0000664000175100017510000001170410413303155032261 0ustar tilletille/* * $RCSfile: GIFImageWriterSpi.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.3 $ * $Date: 2006-03-31 19:43:39 $ * $State: Exp $ */ package com.sun.media.imageioimpl.plugins.gif; import java.awt.image.ColorModel; import java.awt.image.SampleModel; import java.util.Locale; import javax.imageio.ImageTypeSpecifier; import javax.imageio.ImageWriter; import javax.imageio.spi.ImageWriterSpi; import javax.imageio.spi.ServiceRegistry; import com.sun.media.imageioimpl.common.PaletteBuilder; import com.sun.media.imageioimpl.common.ImageUtil; import com.sun.media.imageioimpl.common.PackageUtil; public class GIFImageWriterSpi extends ImageWriterSpi { private static final String vendorName = "Sun Microsystems, Inc."; private static final String version = "1.0"; private static final String[] names = { "gif", "GIF" }; private static final String[] suffixes = { "gif" }; private static final String[] MIMETypes = { "image/gif" }; private static final String writerClassName = "com.sun.media.imageioimpl.plugins.gif.GIFImageWriter"; private static final String[] readerSpiNames = { "com.sun.imageio.plugins.gif.GIFImageReaderSpi" }; private boolean registered = false; public GIFImageWriterSpi() { super(vendorName, version, names, suffixes, MIMETypes, writerClassName, STANDARD_OUTPUT_TYPE, readerSpiNames, true, GIFWritableStreamMetadata.NATIVE_FORMAT_NAME, "com.sun.media.imageioimpl.plugins.gif.GIFStreamMetadataFormat", null, null, true, GIFWritableImageMetadata.NATIVE_FORMAT_NAME, "com.sun.media.imageioimpl.plugins.gif.GIFStreamMetadataFormat", null, null ); } public boolean canEncodeImage(ImageTypeSpecifier type) { if (type == null) { throw new IllegalArgumentException("type == null!"); } SampleModel sm = type.getSampleModel(); ColorModel cm = type.getColorModel(); boolean canEncode = sm.getNumBands() == 1 && sm.getSampleSize(0) <= 8 && sm.getWidth() <= 65535 && sm.getHeight() <= 65535 && (cm == null || cm.getComponentSize()[0] <= 8); if (canEncode) { return true; } else { return PaletteBuilder.canCreatePalette(type); } } public String getDescription(Locale locale) { String desc = PackageUtil.getSpecificationTitle() + " GIF Image Writer"; return desc; } public void onRegistration(ServiceRegistry registry, Class category) { if (registered) { return; } registered = true; // By JDK 1.8, the GIFImageWriter will have been in JDK core for // atleast two FCS releases, so we can set JIIO's to lower priority // With JDK 1.9, we can entirely de-register the JIIO one ImageUtil.processOnRegistration(registry, category, "GIF", this, 9, 8); // JDK version 1.9, 1.8 } public ImageWriter createWriterInstance(Object extension) { return new GIFImageWriter(this); } } ././@LongLink0000000000000000000000000000015100000000000011562 Lustar rootrootjai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/gif/GIFImageMetadataFormat.javajai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/gif/GIFImageMetadataFormat.0000775000175100017510000002035110411071363032362 0ustar tilletille/* * $RCSfile: GIFImageMetadataFormat.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.1 $ * $Date: 2006-03-24 22:30:10 $ * $State: Exp $ */ package com.sun.media.imageioimpl.plugins.gif; import java.util.Arrays; import javax.imageio.ImageTypeSpecifier; import javax.imageio.metadata.IIOMetadataFormat; import javax.imageio.metadata.IIOMetadataFormatImpl; public class GIFImageMetadataFormat extends IIOMetadataFormatImpl { private static IIOMetadataFormat instance = null; private GIFImageMetadataFormat() { super(GIFImageMetadata.nativeMetadataFormatName, CHILD_POLICY_SOME); // root -> ImageDescriptor addElement("ImageDescriptor", GIFImageMetadata.nativeMetadataFormatName, CHILD_POLICY_EMPTY); addAttribute("ImageDescriptor", "imageLeftPosition", DATATYPE_INTEGER, true, null, "0", "65535", true, true); addAttribute("ImageDescriptor", "imageTopPosition", DATATYPE_INTEGER, true, null, "0", "65535", true, true); addAttribute("ImageDescriptor", "imageWidth", DATATYPE_INTEGER, true, null, "1", "65535", true, true); addAttribute("ImageDescriptor", "imageHeight", DATATYPE_INTEGER, true, null, "1", "65535", true, true); addBooleanAttribute("ImageDescriptor", "interlaceFlag", false, false); // root -> LocalColorTable addElement("LocalColorTable", GIFImageMetadata.nativeMetadataFormatName, 2, 256); addAttribute("LocalColorTable", "sizeOfLocalColorTable", DATATYPE_INTEGER, true, null, Arrays.asList(GIFStreamMetadata.colorTableSizes)); addBooleanAttribute("LocalColorTable", "sortFlag", false, false); // root -> LocalColorTable -> ColorTableEntry addElement("ColorTableEntry", "LocalColorTable", CHILD_POLICY_EMPTY); addAttribute("ColorTableEntry", "index", DATATYPE_INTEGER, true, null, "0", "255", true, true); addAttribute("ColorTableEntry", "red", DATATYPE_INTEGER, true, null, "0", "255", true, true); addAttribute("ColorTableEntry", "green", DATATYPE_INTEGER, true, null, "0", "255", true, true); addAttribute("ColorTableEntry", "blue", DATATYPE_INTEGER, true, null, "0", "255", true, true); // root -> GraphicControlExtension addElement("GraphicControlExtension", GIFImageMetadata.nativeMetadataFormatName, CHILD_POLICY_EMPTY); addAttribute("GraphicControlExtension", "disposalMethod", DATATYPE_STRING, true, null, Arrays.asList(GIFImageMetadata.disposalMethodNames)); addBooleanAttribute("GraphicControlExtension", "userInputFlag", false, false); addBooleanAttribute("GraphicControlExtension", "transparentColorFlag", false, false); addAttribute("GraphicControlExtension", "delayTime", DATATYPE_INTEGER, true, null, "0", "65535", true, true); addAttribute("GraphicControlExtension", "transparentColorIndex", DATATYPE_INTEGER, true, null, "0", "255", true, true); // root -> PlainTextExtension addElement("PlainTextExtension", GIFImageMetadata.nativeMetadataFormatName, CHILD_POLICY_EMPTY); addAttribute("PlainTextExtension", "textGridLeft", DATATYPE_INTEGER, true, null, "0", "65535", true, true); addAttribute("PlainTextExtension", "textGridTop", DATATYPE_INTEGER, true, null, "0", "65535", true, true); addAttribute("PlainTextExtension", "textGridWidth", DATATYPE_INTEGER, true, null, "1", "65535", true, true); addAttribute("PlainTextExtension", "textGridHeight", DATATYPE_INTEGER, true, null, "1", "65535", true, true); addAttribute("PlainTextExtension", "characterCellWidth", DATATYPE_INTEGER, true, null, "1", "65535", true, true); addAttribute("PlainTextExtension", "characterCellHeight", DATATYPE_INTEGER, true, null, "1", "65535", true, true); addAttribute("PlainTextExtension", "textForegroundColor", DATATYPE_INTEGER, true, null, "0", "255", true, true); addAttribute("PlainTextExtension", "textBackgroundColor", DATATYPE_INTEGER, true, null, "0", "255", true, true); // root -> ApplicationExtensions addElement("ApplicationExtensions", GIFImageMetadata.nativeMetadataFormatName, 1, Integer.MAX_VALUE); // root -> ApplicationExtensions -> ApplicationExtension addElement("ApplicationExtension", "ApplicationExtensions", CHILD_POLICY_EMPTY); addAttribute("ApplicationExtension", "applicationID", DATATYPE_STRING, true, null); addAttribute("ApplicationExtension", "authenticationCode", DATATYPE_STRING, true, null); addObjectValue("ApplicationExtension", byte.class, 0, Integer.MAX_VALUE); // root -> CommentExtensions addElement("CommentExtensions", GIFImageMetadata.nativeMetadataFormatName, 1, Integer.MAX_VALUE); // root -> CommentExtensions -> CommentExtension addElement("CommentExtension", "CommentExtensions", CHILD_POLICY_EMPTY); addAttribute("CommentExtension", "value", DATATYPE_STRING, true, null); } public boolean canNodeAppear(String elementName, ImageTypeSpecifier imageType) { return true; } public static synchronized IIOMetadataFormat getInstance() { if (instance == null) { instance = new GIFImageMetadataFormat(); } return instance; } } jai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/gif/GIFImageMetadata.java0000775000175100017510000004151710411071363032062 0ustar tilletille/* * $RCSfile: GIFImageMetadata.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.1 $ * $Date: 2006-03-24 22:30:09 $ * $State: Exp $ */ package com.sun.media.imageioimpl.plugins.gif; import java.io.UnsupportedEncodingException; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import javax.imageio.ImageTypeSpecifier; import javax.imageio.metadata.IIOInvalidTreeException; import javax.imageio.metadata.IIOMetadata; import javax.imageio.metadata.IIOMetadataNode; import javax.imageio.metadata.IIOMetadataFormat; import javax.imageio.metadata.IIOMetadataFormatImpl; import org.w3c.dom.Node; /** * @version 0.5 */ public class GIFImageMetadata extends GIFMetadata { // package scope static final String nativeMetadataFormatName = "javax_imageio_gif_image_1.0"; static final String[] disposalMethodNames = { "none", "doNotDispose", "restoreToBackgroundColor", "restoreToPrevious", "undefinedDisposalMethod4", "undefinedDisposalMethod5", "undefinedDisposalMethod6", "undefinedDisposalMethod7" }; // Fields from Image Descriptor public int imageLeftPosition; public int imageTopPosition; public int imageWidth; public int imageHeight; public boolean interlaceFlag = false; public boolean sortFlag = false; public byte[] localColorTable = null; // Fields from Graphic Control Extension public int disposalMethod = 0; public boolean userInputFlag = false; public boolean transparentColorFlag = false; public int delayTime = 0; public int transparentColorIndex = 0; // Fields from Plain Text Extension public boolean hasPlainTextExtension = false; public int textGridLeft; public int textGridTop; public int textGridWidth; public int textGridHeight; public int characterCellWidth; public int characterCellHeight; public int textForegroundColor; public int textBackgroundColor; public byte[] text; // Fields from ApplicationExtension // List of byte[] public List applicationIDs = null; // new ArrayList(); // List of byte[] public List authenticationCodes = null; // new ArrayList(); // List of byte[] public List applicationData = null; // new ArrayList(); // Fields from CommentExtension // List of byte[] public List comments = null; // new ArrayList(); protected GIFImageMetadata(boolean standardMetadataFormatSupported, String nativeMetadataFormatName, String nativeMetadataFormatClassName, String[] extraMetadataFormatNames, String[] extraMetadataFormatClassNames) { super(standardMetadataFormatSupported, nativeMetadataFormatName, nativeMetadataFormatClassName, extraMetadataFormatNames, extraMetadataFormatClassNames); } public GIFImageMetadata() { this(true, nativeMetadataFormatName, "com.sun.media.imageioimpl.plugins.gif.GIFImageMetadataFormat", null, null); } public boolean isReadOnly() { return true; } public Node getAsTree(String formatName) { if (formatName.equals(nativeMetadataFormatName)) { return getNativeTree(); } else if (formatName.equals (IIOMetadataFormatImpl.standardMetadataFormatName)) { return getStandardTree(); } else { throw new IllegalArgumentException("Not a recognized format!"); } } private String toISO8859(byte[] data) { try { return new String(data, "ISO-8859-1"); } catch (UnsupportedEncodingException e) { return ""; } } private Node getNativeTree() { IIOMetadataNode node; // scratch node IIOMetadataNode root = new IIOMetadataNode(nativeMetadataFormatName); // Image descriptor node = new IIOMetadataNode("ImageDescriptor"); node.setAttribute("imageLeftPosition", Integer.toString(imageLeftPosition)); node.setAttribute("imageTopPosition", Integer.toString(imageTopPosition)); node.setAttribute("imageWidth", Integer.toString(imageWidth)); node.setAttribute("imageHeight", Integer.toString(imageHeight)); node.setAttribute("interlaceFlag", interlaceFlag ? "true" : "false"); root.appendChild(node); // Local color table if (localColorTable != null) { node = new IIOMetadataNode("LocalColorTable"); int numEntries = localColorTable.length/3; node.setAttribute("sizeOfLocalColorTable", Integer.toString(numEntries)); node.setAttribute("sortFlag", sortFlag ? "TRUE" : "FALSE"); for (int i = 0; i < numEntries; i++) { IIOMetadataNode entry = new IIOMetadataNode("ColorTableEntry"); entry.setAttribute("index", Integer.toString(i)); int r = localColorTable[3*i] & 0xff; int g = localColorTable[3*i + 1] & 0xff; int b = localColorTable[3*i + 2] & 0xff; entry.setAttribute("red", Integer.toString(r)); entry.setAttribute("green", Integer.toString(g)); entry.setAttribute("blue", Integer.toString(b)); node.appendChild(entry); } root.appendChild(node); } // Graphic control extension node = new IIOMetadataNode("GraphicControlExtension"); node.setAttribute("disposalMethod", disposalMethodNames[disposalMethod]); node.setAttribute("userInputFlag", userInputFlag ? "true" : "false"); node.setAttribute("transparentColorFlag", transparentColorFlag ? "true" : "false"); node.setAttribute("delayTime", Integer.toString(delayTime)); node.setAttribute("transparentColorIndex", Integer.toString(transparentColorIndex)); root.appendChild(node); if (hasPlainTextExtension) { node = new IIOMetadataNode("PlainTextExtension"); node.setAttribute("textGridLeft", Integer.toString(textGridLeft)); node.setAttribute("textGridTop", Integer.toString(textGridTop)); node.setAttribute("textGridWidth", Integer.toString(textGridWidth)); node.setAttribute("textGridHeight", Integer.toString(textGridHeight)); node.setAttribute("characterCellWidth", Integer.toString(characterCellWidth)); node.setAttribute("characterCellHeight", Integer.toString(characterCellHeight)); node.setAttribute("textForegroundColor", Integer.toString(textForegroundColor)); node.setAttribute("textBackgroundColor", Integer.toString(textBackgroundColor)); node.setAttribute("text", toISO8859(text)); root.appendChild(node); } // Application extensions int numAppExtensions = applicationIDs == null ? 0 : applicationIDs.size(); if (numAppExtensions > 0) { node = new IIOMetadataNode("ApplicationExtensions"); for (int i = 0; i < numAppExtensions; i++) { IIOMetadataNode appExtNode = new IIOMetadataNode("ApplicationExtension"); byte[] applicationID = (byte[])applicationIDs.get(i); appExtNode.setAttribute("applicationID", toISO8859(applicationID)); byte[] authenticationCode = (byte[])authenticationCodes.get(i); appExtNode.setAttribute("authenticationCode", toISO8859(authenticationCode)); byte[] appData = (byte[])applicationData.get(i); appExtNode.setUserObject((byte[])appData.clone()); node.appendChild(appExtNode); } root.appendChild(node); } // Comment extensions int numComments = comments == null ? 0 : comments.size(); if (numComments > 0) { node = new IIOMetadataNode("CommentExtensions"); for (int i = 0; i < numComments; i++) { IIOMetadataNode commentNode = new IIOMetadataNode("CommentExtension"); byte[] comment = (byte[])comments.get(i); commentNode.setAttribute("value", toISO8859(comment)); node.appendChild(commentNode); } root.appendChild(node); } return root; } public IIOMetadataNode getStandardChromaNode() { IIOMetadataNode chroma_node = new IIOMetadataNode("Chroma"); IIOMetadataNode node = null; // scratch node node = new IIOMetadataNode("ColorSpaceType"); node.setAttribute("name", "RGB"); chroma_node.appendChild(node); node = new IIOMetadataNode("NumChannels"); node.setAttribute("value", transparentColorFlag ? "4" : "3"); chroma_node.appendChild(node); // Gamma not in format node = new IIOMetadataNode("BlackIsZero"); node.setAttribute("value", "TRUE"); chroma_node.appendChild(node); if (localColorTable != null) { node = new IIOMetadataNode("Palette"); int numEntries = localColorTable.length/3; for (int i = 0; i < numEntries; i++) { IIOMetadataNode entry = new IIOMetadataNode("PaletteEntry"); entry.setAttribute("index", Integer.toString(i)); entry.setAttribute("red", Integer.toString(localColorTable[3*i] & 0xff)); entry.setAttribute("green", Integer.toString(localColorTable[3*i + 1] & 0xff)); entry.setAttribute("blue", Integer.toString(localColorTable[3*i + 2] & 0xff)); node.appendChild(entry); } chroma_node.appendChild(node); } // BackgroundIndex not in image // BackgroundColor not in format return chroma_node; } public IIOMetadataNode getStandardCompressionNode() { IIOMetadataNode compression_node = new IIOMetadataNode("Compression"); IIOMetadataNode node = null; // scratch node node = new IIOMetadataNode("CompressionTypeName"); node.setAttribute("value", "lzw"); compression_node.appendChild(node); node = new IIOMetadataNode("Lossless"); node.setAttribute("value", "TRUE"); compression_node.appendChild(node); node = new IIOMetadataNode("NumProgressiveScans"); node.setAttribute("value", interlaceFlag ? "4" : "1"); compression_node.appendChild(node); // BitRate not in format return compression_node; } public IIOMetadataNode getStandardDataNode() { IIOMetadataNode data_node = new IIOMetadataNode("Data"); IIOMetadataNode node = null; // scratch node // PlanarConfiguration not in format node = new IIOMetadataNode("SampleFormat"); node.setAttribute("value", "Index"); data_node.appendChild(node); // BitsPerSample not in image // SignificantBitsPerSample not in format // SampleMSB not in format return data_node; } public IIOMetadataNode getStandardDimensionNode() { IIOMetadataNode dimension_node = new IIOMetadataNode("Dimension"); IIOMetadataNode node = null; // scratch node // PixelAspectRatio not in image node = new IIOMetadataNode("ImageOrientation"); node.setAttribute("value", "Normal"); dimension_node.appendChild(node); // HorizontalPixelSize not in format // VerticalPixelSize not in format // HorizontalPhysicalPixelSpacing not in format // VerticalPhysicalPixelSpacing not in format // HorizontalPosition not in format // VerticalPosition not in format node = new IIOMetadataNode("HorizontalPixelOffset"); node.setAttribute("value", Integer.toString(imageLeftPosition)); dimension_node.appendChild(node); node = new IIOMetadataNode("VerticalPixelOffset"); node.setAttribute("value", Integer.toString(imageTopPosition)); dimension_node.appendChild(node); // HorizontalScreenSize not in image // VerticalScreenSize not in image return dimension_node; } // Document not in image public IIOMetadataNode getStandardTextNode() { if (comments == null) { return null; } Iterator commentIter = comments.iterator(); if (!commentIter.hasNext()) { return null; } IIOMetadataNode text_node = new IIOMetadataNode("Text"); IIOMetadataNode node = null; // scratch node while (commentIter.hasNext()) { byte[] comment = (byte[])commentIter.next(); String s = null; try { s = new String(comment, "ISO-8859-1"); } catch (UnsupportedEncodingException e) { throw new RuntimeException("Encoding ISO-8859-1 unknown!"); } node = new IIOMetadataNode("TextEntry"); node.setAttribute("value", s); node.setAttribute("encoding", "ISO-8859-1"); node.setAttribute("compression", "none"); text_node.appendChild(node); } return text_node; } public IIOMetadataNode getStandardTransparencyNode() { if (!transparentColorFlag) { return null; } IIOMetadataNode transparency_node = new IIOMetadataNode("Transparency"); IIOMetadataNode node = null; // scratch node // Alpha not in format node = new IIOMetadataNode("TransparentIndex"); node.setAttribute("value", Integer.toString(transparentColorIndex)); transparency_node.appendChild(node); // TransparentColor not in format // TileTransparencies not in format // TileOpacities not in format return transparency_node; } public void setFromTree(String formatName, Node root) throws IIOInvalidTreeException { throw new IllegalStateException("Metadata is read-only!"); } protected void mergeNativeTree(Node root) throws IIOInvalidTreeException { throw new IllegalStateException("Metadata is read-only!"); } protected void mergeStandardTree(Node root) throws IIOInvalidTreeException { throw new IllegalStateException("Metadata is read-only!"); } public void reset() { throw new IllegalStateException("Metadata is read-only!"); } } jai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/gif/GIFImageWriter.java0000664000175100017510000014044510411071363031613 0ustar tilletille/* * $RCSfile: GIFImageWriter.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.3 $ * $Date: 2006-03-24 22:30:10 $ * $State: Exp $ */ package com.sun.media.imageioimpl.plugins.gif; import java.awt.Dimension; import java.awt.Rectangle; import java.awt.image.ColorModel; import java.awt.image.ComponentSampleModel; import java.awt.image.DataBufferByte; import java.awt.image.IndexColorModel; import java.awt.image.Raster; import java.awt.image.RenderedImage; import java.awt.image.SampleModel; import java.awt.image.WritableRaster; import java.io.IOException; import java.nio.ByteOrder; import java.util.Arrays; import java.util.Iterator; import java.util.Locale; import javax.imageio.IIOException; import javax.imageio.IIOImage; import javax.imageio.ImageTypeSpecifier; import javax.imageio.ImageWriteParam; import javax.imageio.ImageWriter; import javax.imageio.spi.ImageWriterSpi; import javax.imageio.metadata.IIOInvalidTreeException; import javax.imageio.metadata.IIOMetadata; import javax.imageio.metadata.IIOMetadataFormatImpl; import javax.imageio.metadata.IIOMetadataNode; import javax.imageio.stream.ImageOutputStream; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import com.sun.media.imageioimpl.common.LZWCompressor; import com.sun.media.imageioimpl.common.PaletteBuilder; public class GIFImageWriter extends ImageWriter { private static final boolean DEBUG = false; // XXX false for release! static final String STANDARD_METADATA_NAME = IIOMetadataFormatImpl.standardMetadataFormatName; static final String STREAM_METADATA_NAME = GIFWritableStreamMetadata.NATIVE_FORMAT_NAME; static final String IMAGE_METADATA_NAME = GIFWritableImageMetadata.NATIVE_FORMAT_NAME; /** * The output case to an ImageOutputStream. */ private ImageOutputStream stream = null; /** * Whether a sequence is being written. */ private boolean isWritingSequence = false; /** * Whether the header has been written. */ private boolean wroteSequenceHeader = false; /** * The stream metadata of a sequence. */ private GIFWritableStreamMetadata theStreamMetadata = null; /** * The index of the image being written. */ private int imageIndex = 0; /** * The number of bits represented by the value which should be a * legal length for a color table. */ private static int getNumBits(int value) throws IOException { int numBits; switch(value) { case 2: numBits = 1; break; case 4: numBits = 2; break; case 8: numBits = 3; break; case 16: numBits = 4; break; case 32: numBits = 5; break; case 64: numBits = 6; break; case 128: numBits = 7; break; case 256: numBits = 8; break; default: throw new IOException("Bad palette length: "+value+"!"); } return numBits; } /** * Compute the source region and destination dimensions taking any * parameter settings into account. */ private static void computeRegions(Rectangle sourceBounds, Dimension destSize, ImageWriteParam p) { ImageWriteParam param; int periodX = 1; int periodY = 1; if (p != null) { int[] sourceBands = p.getSourceBands(); if (sourceBands != null && (sourceBands.length != 1 || sourceBands[0] != 0)) { throw new IllegalArgumentException("Cannot sub-band image!"); } // Get source region and subsampling factors Rectangle sourceRegion = p.getSourceRegion(); if (sourceRegion != null) { // Clip to actual image bounds sourceRegion = sourceRegion.intersection(sourceBounds); sourceBounds.setBounds(sourceRegion); } // Adjust for subsampling offsets int gridX = p.getSubsamplingXOffset(); int gridY = p.getSubsamplingYOffset(); sourceBounds.x += gridX; sourceBounds.y += gridY; sourceBounds.width -= gridX; sourceBounds.height -= gridY; // Get subsampling factors periodX = p.getSourceXSubsampling(); periodY = p.getSourceYSubsampling(); } // Compute output dimensions destSize.setSize((sourceBounds.width + periodX - 1)/periodX, (sourceBounds.height + periodY - 1)/periodY); if (destSize.width <= 0 || destSize.height <= 0) { throw new IllegalArgumentException("Empty source region!"); } } /** * Create a color table from the image ColorModel and SampleModel. */ private static byte[] createColorTable(ColorModel colorModel, SampleModel sampleModel) { byte[] colorTable; if (colorModel instanceof IndexColorModel) { IndexColorModel icm = (IndexColorModel)colorModel; int mapSize = icm.getMapSize(); /** * The GIF image format assumes that size of image palette * is power of two. We will use closest larger power of two * as size of color table. */ int ctSize = getGifPaletteSize(mapSize); byte[] reds = new byte[ctSize]; byte[] greens = new byte[ctSize]; byte[] blues = new byte[ctSize]; icm.getReds(reds); icm.getGreens(greens); icm.getBlues(blues); /** * fill tail of color component arrays by replica of first color * in order to avoid appearance of extra colors in the color table */ for (int i = mapSize; i < ctSize; i++) { reds[i] = reds[0]; greens[i] = greens[0]; blues[i] = blues[0]; } colorTable = new byte[3*ctSize]; int idx = 0; for (int i = 0; i < ctSize; i++) { colorTable[idx++] = reds[i]; colorTable[idx++] = greens[i]; colorTable[idx++] = blues[i]; } } else if (sampleModel.getNumBands() == 1) { // create gray-scaled color table for single-banded images int numBits = sampleModel.getSampleSize()[0]; if (numBits > 8) { numBits = 8; } int colorTableLength = 3*(1 << numBits); colorTable = new byte[colorTableLength]; for (int i = 0; i < colorTableLength; i++) { colorTable[i] = (byte)(i/3); } } else { // We do not have enough information here // to create well-fit color table for RGB image. colorTable = null; } return colorTable; } /** * According do GIF specification size of clor table (palette here) * must be in range from 2 to 256 and must be power of 2. */ private static int getGifPaletteSize(int x) { if (x <= 2) { return 2; } x = x - 1; x = x | (x >> 1); x = x | (x >> 2); x = x | (x >> 4); x = x | (x >> 8); x = x | (x >> 16); return x + 1; } public GIFImageWriter(GIFImageWriterSpi originatingProvider) { super(originatingProvider); if (DEBUG) { System.err.println("GIF Writer is created"); } } public boolean canWriteSequence() { return true; } /** * Merges inData into outData. The supplied * metadata format name is attempted first and failing that the standard * metadata format name is attempted. */ private void convertMetadata(String metadataFormatName, IIOMetadata inData, IIOMetadata outData) { String formatName = null; String nativeFormatName = inData.getNativeMetadataFormatName(); if (nativeFormatName != null && nativeFormatName.equals(metadataFormatName)) { formatName = metadataFormatName; } else { String[] extraFormatNames = inData.getExtraMetadataFormatNames(); if (extraFormatNames != null) { for (int i = 0; i < extraFormatNames.length; i++) { if (extraFormatNames[i].equals(metadataFormatName)) { formatName = metadataFormatName; break; } } } } if (formatName == null && inData.isStandardMetadataFormatSupported()) { formatName = STANDARD_METADATA_NAME; } if (formatName != null) { try { Node root = inData.getAsTree(formatName); outData.mergeTree(formatName, root); } catch(IIOInvalidTreeException e) { // ignore } } } /** * Creates a default stream metadata object and merges in the * supplied metadata. */ public IIOMetadata convertStreamMetadata(IIOMetadata inData, ImageWriteParam param) { if (inData == null) { throw new IllegalArgumentException("inData == null!"); } IIOMetadata sm = getDefaultStreamMetadata(param); convertMetadata(STREAM_METADATA_NAME, inData, sm); return sm; } /** * Creates a default image metadata object and merges in the * supplied metadata. */ public IIOMetadata convertImageMetadata(IIOMetadata inData, ImageTypeSpecifier imageType, ImageWriteParam param) { if (inData == null) { throw new IllegalArgumentException("inData == null!"); } if (imageType == null) { throw new IllegalArgumentException("imageType == null!"); } GIFWritableImageMetadata im = (GIFWritableImageMetadata)getDefaultImageMetadata(imageType, param); // Save interlace flag state. boolean isProgressive = im.interlaceFlag; convertMetadata(IMAGE_METADATA_NAME, inData, im); // Undo change to interlace flag if not MODE_COPY_FROM_METADATA. if (param != null && param.canWriteProgressive() && param.getProgressiveMode() != param.MODE_COPY_FROM_METADATA) { im.interlaceFlag = isProgressive; } return im; } public void endWriteSequence() throws IOException { if (stream == null) { throw new IllegalStateException("output == null!"); } if (!isWritingSequence) { throw new IllegalStateException("prepareWriteSequence() was not invoked!"); } writeTrailer(); resetLocal(); } public IIOMetadata getDefaultImageMetadata(ImageTypeSpecifier imageType, ImageWriteParam param) { GIFWritableImageMetadata imageMetadata = new GIFWritableImageMetadata(); // Image dimensions SampleModel sampleModel = imageType.getSampleModel(); Rectangle sourceBounds = new Rectangle(sampleModel.getWidth(), sampleModel.getHeight()); Dimension destSize = new Dimension(); computeRegions(sourceBounds, destSize, param); imageMetadata.imageWidth = destSize.width; imageMetadata.imageHeight = destSize.height; // Interlacing if (param != null && param.canWriteProgressive() && param.getProgressiveMode() == ImageWriteParam.MODE_DISABLED) { imageMetadata.interlaceFlag = false; } else { imageMetadata.interlaceFlag = true; } // Local color table ColorModel colorModel = imageType.getColorModel(); imageMetadata.localColorTable = createColorTable(colorModel, sampleModel); // Transparency if (colorModel instanceof IndexColorModel) { int transparentIndex = ((IndexColorModel)colorModel).getTransparentPixel(); if (transparentIndex != -1) { imageMetadata.transparentColorFlag = true; imageMetadata.transparentColorIndex = transparentIndex; } } return imageMetadata; } public IIOMetadata getDefaultStreamMetadata(ImageWriteParam param) { GIFWritableStreamMetadata streamMetadata = new GIFWritableStreamMetadata(); streamMetadata.version = "89a"; return streamMetadata; } public ImageWriteParam getDefaultWriteParam() { return new GIFImageWriteParam(getLocale()); } public void prepareWriteSequence(IIOMetadata streamMetadata) throws IOException { if (stream == null) { throw new IllegalStateException("Output is not set."); } resetLocal(); // Save the possibly converted stream metadata as an instance variable. if (streamMetadata == null) { this.theStreamMetadata = (GIFWritableStreamMetadata)getDefaultStreamMetadata(null); } else { this.theStreamMetadata = new GIFWritableStreamMetadata(); convertMetadata(STREAM_METADATA_NAME, streamMetadata, theStreamMetadata); } this.isWritingSequence = true; } public void reset() { super.reset(); resetLocal(); } /** * Resets locally defined instance variables. */ private void resetLocal() { this.isWritingSequence = false; this.wroteSequenceHeader = false; this.theStreamMetadata = null; this.imageIndex = 0; } public void setOutput(Object output) { super.setOutput(output); if (output != null) { if (!(output instanceof ImageOutputStream)) { throw new IllegalArgumentException("output is not an ImageOutputStream"); } this.stream = (ImageOutputStream)output; this.stream.setByteOrder(ByteOrder.LITTLE_ENDIAN); } else { this.stream = null; } } public void write(IIOMetadata sm, IIOImage iioimage, ImageWriteParam p) throws IOException { if (stream == null) { throw new IllegalStateException("output == null!"); } if (iioimage == null) { throw new IllegalArgumentException("iioimage == null!"); } if (iioimage.hasRaster()) { throw new UnsupportedOperationException("canWriteRasters() == false!"); } resetLocal(); GIFWritableStreamMetadata streamMetadata; if (sm == null) { streamMetadata = (GIFWritableStreamMetadata)getDefaultStreamMetadata(p); } else { streamMetadata = (GIFWritableStreamMetadata)convertStreamMetadata(sm, p); } write(true, true, streamMetadata, iioimage, p); } public void writeToSequence(IIOImage image, ImageWriteParam param) throws IOException { if (stream == null) { throw new IllegalStateException("output == null!"); } if (image == null) { throw new IllegalArgumentException("image == null!"); } if (image.hasRaster()) { throw new UnsupportedOperationException("canWriteRasters() == false!"); } if (!isWritingSequence) { throw new IllegalStateException("prepareWriteSequence() was not invoked!"); } write(!wroteSequenceHeader, false, theStreamMetadata, image, param); if (!wroteSequenceHeader) { wroteSequenceHeader = true; } this.imageIndex++; } private boolean needToCreateIndex(RenderedImage image) { SampleModel sampleModel = image.getSampleModel(); ColorModel colorModel = image.getColorModel(); return sampleModel.getNumBands() != 1 || sampleModel.getSampleSize()[0] > 8 || colorModel.getComponentSize()[0] > 8; } /** * Writes any extension blocks, the Image Descriptor, the image data, * and optionally the header (Signature and Logical Screen Descriptor) * and trailer (Block Terminator). * * @param writeHeader Whether to write the header. * @param writeTrailer Whether to write the trailer. * @param sm The stream metadata or null if * writeHeader is false. * @param iioimage The image and image metadata. * @param p The write parameters. * * @throws IllegalArgumentException if the number of bands is not 1. * @throws IllegalArgumentException if the number of bits per sample is * greater than 8. * @throws IllegalArgumentException if the color component size is * greater than 8. * @throws IllegalArgumentException if writeHeader is * true and sm is null. * @throws IllegalArgumentException if writeHeader is * false and a sequence is not being written. */ private void write(boolean writeHeader, boolean writeTrailer, IIOMetadata sm, IIOImage iioimage, ImageWriteParam p) throws IOException { clearAbortRequest(); RenderedImage image = iioimage.getRenderedImage(); // Check for ability to encode image. if (needToCreateIndex(image)) { image = PaletteBuilder.createIndexedImage(image); iioimage.setRenderedImage(image); } ColorModel colorModel = image.getColorModel(); SampleModel sampleModel = image.getSampleModel(); // Determine source region and destination dimensions. Rectangle sourceBounds = new Rectangle(image.getMinX(), image.getMinY(), image.getWidth(), image.getHeight()); Dimension destSize = new Dimension(); computeRegions(sourceBounds, destSize, p); // Convert any provided image metadata. GIFWritableImageMetadata imageMetadata = null; if (iioimage.getMetadata() != null) { imageMetadata = new GIFWritableImageMetadata(); convertMetadata(IMAGE_METADATA_NAME, iioimage.getMetadata(), imageMetadata); // Converted rgb image can use palette different from global. // In order to avoid color artefacts we want to be sure we use // appropriate palette. For this we initialize local color table // from current color and sample models. // At this point we can guarantee that local color table can be // build because image was already converted to indexed or // gray-scale representations if (imageMetadata.localColorTable == null) { imageMetadata.localColorTable = createColorTable(colorModel, sampleModel); // in case of indexed image we should take care of // transparent pixels if (colorModel instanceof IndexColorModel) { IndexColorModel icm = (IndexColorModel)colorModel; int index = icm.getTransparentPixel(); imageMetadata.transparentColorFlag = (index != -1); if (imageMetadata.transparentColorFlag) { imageMetadata.transparentColorIndex = index; } /* NB: transparentColorFlag might have not beed reset for greyscale images but explicitly reseting it here is potentially not right thing to do until we have way to find whether current value was explicitly set by the user. */ } } } // Global color table values. byte[] globalColorTable = null; // Write the header (Signature+Logical Screen Descriptor+ // Global Color Table). if (writeHeader) { if (sm == null) { throw new IllegalArgumentException("Cannot write null header!"); } GIFWritableStreamMetadata streamMetadata = (GIFWritableStreamMetadata)sm; // Set the version if not set. if (streamMetadata.version == null) { streamMetadata.version = "89a"; } // Set the Logical Screen Desriptor if not set. if (streamMetadata.logicalScreenWidth == GIFMetadata.UNDEFINED_INTEGER_VALUE) { streamMetadata.logicalScreenWidth = destSize.width; } if (streamMetadata.logicalScreenHeight == GIFMetadata.UNDEFINED_INTEGER_VALUE) { streamMetadata.logicalScreenHeight = destSize.height; } if (streamMetadata.colorResolution == GIFMetadata.UNDEFINED_INTEGER_VALUE) { streamMetadata.colorResolution = colorModel != null ? colorModel.getComponentSize()[0] : sampleModel.getSampleSize()[0]; } // Set the Global Color Table if not set, i.e., if not // provided in the stream metadata. if (streamMetadata.globalColorTable == null) { if (isWritingSequence && imageMetadata != null && imageMetadata.localColorTable != null) { // Writing a sequence and a local color table was // provided in the metadata of the first image: use it. streamMetadata.globalColorTable = imageMetadata.localColorTable; } else if (imageMetadata == null || imageMetadata.localColorTable == null) { // Create a color table. streamMetadata.globalColorTable = createColorTable(colorModel, sampleModel); } } // Set the Global Color Table. At this point it should be // A) the global color table provided in stream metadata, if any; // B) the local color table of the image metadata, if any, if // writing a sequence; // C) a table created on the basis of the first image ColorModel // and SampleModel if no local color table is available; or // D) null if none of the foregoing conditions obtain (which // should only be if a sequence is not being written and // a local color table is provided in image metadata). globalColorTable = streamMetadata.globalColorTable; // Write the header. int bitsPerPixel; if (globalColorTable != null) { bitsPerPixel = getNumBits(globalColorTable.length/3); } else if (imageMetadata != null && imageMetadata.localColorTable != null) { bitsPerPixel = getNumBits(imageMetadata.localColorTable.length/3); } else { bitsPerPixel = sampleModel.getSampleSize(0); } writeHeader(streamMetadata, bitsPerPixel); } else if (isWritingSequence) { globalColorTable = theStreamMetadata.globalColorTable; } else { throw new IllegalArgumentException("Must write header for single image!"); } // Write extension blocks, Image Descriptor, and image data. writeImage(iioimage.getRenderedImage(), imageMetadata, p, globalColorTable, sourceBounds, destSize); // Write the trailer. if (writeTrailer) { writeTrailer(); } } /** * Writes any extension blocks, the Image Descriptor, and the image data * * @param iioimage The image and image metadata. * @param param The write parameters. * @param globalColorTable The Global Color Table. * @param sourceBounds The source region. * @param destSize The destination dimensions. */ private void writeImage(RenderedImage image, GIFWritableImageMetadata imageMetadata, ImageWriteParam param, byte[] globalColorTable, Rectangle sourceBounds, Dimension destSize) throws IOException { ColorModel colorModel = image.getColorModel(); SampleModel sampleModel = image.getSampleModel(); boolean writeGraphicsControlExtension; if (imageMetadata == null) { // Create default metadata. imageMetadata = (GIFWritableImageMetadata)getDefaultImageMetadata( new ImageTypeSpecifier(image), param); // Set GraphicControlExtension flag only if there is // transparency. writeGraphicsControlExtension = imageMetadata.transparentColorFlag; } else { // Check for GraphicControlExtension element. NodeList list = null; try { IIOMetadataNode root = (IIOMetadataNode) imageMetadata.getAsTree(IMAGE_METADATA_NAME); list = root.getElementsByTagName("GraphicControlExtension"); } catch(IllegalArgumentException iae) { // Should never happen. } // Set GraphicControlExtension flag if element present. writeGraphicsControlExtension = list != null && list.getLength() > 0; // If progressive mode is not MODE_COPY_FROM_METADATA, ensure // the interlacing is set per the ImageWriteParam mode setting. if (param != null && param.canWriteProgressive()) { if (param.getProgressiveMode() == ImageWriteParam.MODE_DISABLED) { imageMetadata.interlaceFlag = false; } else if (param.getProgressiveMode() == ImageWriteParam.MODE_DEFAULT) { imageMetadata.interlaceFlag = true; } } } // Unset local color table if equal to global color table. if (Arrays.equals(globalColorTable, imageMetadata.localColorTable)) { imageMetadata.localColorTable = null; } // Override dimensions imageMetadata.imageWidth = destSize.width; imageMetadata.imageHeight = destSize.height; // Write Graphics Control Extension. if (writeGraphicsControlExtension) { writeGraphicControlExtension(imageMetadata); } // Write extension blocks. writePlainTextExtension(imageMetadata); writeApplicationExtension(imageMetadata); writeCommentExtension(imageMetadata); // Write Image Descriptor int bitsPerPixel = getNumBits(imageMetadata.localColorTable == null ? (globalColorTable == null ? sampleModel.getSampleSize(0) : globalColorTable.length/3) : imageMetadata.localColorTable.length/3); writeImageDescriptor(imageMetadata, bitsPerPixel); // Write image data writeRasterData(image, sourceBounds, destSize, param, imageMetadata.interlaceFlag); } private void writeRows(RenderedImage image, LZWCompressor compressor, int sx, int sdx, int sy, int sdy, int sw, int dy, int ddy, int dw, int dh, int numRowsWritten, int progressReportRowPeriod) throws IOException { if (DEBUG) System.out.println("Writing unoptimized"); int[] sbuf = new int[sw]; byte[] dbuf = new byte[dw]; Raster raster = image.getNumXTiles() == 1 && image.getNumYTiles() == 1 ? image.getTile(0, 0) : image.getData(); for (int y = dy; y < dh; y += ddy) { if (numRowsWritten % progressReportRowPeriod == 0) { if (abortRequested()) { processWriteAborted(); return; } processImageProgress((numRowsWritten*100.0F)/dh); } raster.getSamples(sx, sy, sw, 1, 0, sbuf); for (int i = 0, j = 0; i < dw; i++, j += sdx) { dbuf[i] = (byte)sbuf[j]; } compressor.compress(dbuf, 0, dw); numRowsWritten++; sy += sdy; } } private void writeRowsOpt(byte[] data, int offset, int lineStride, LZWCompressor compressor, int dy, int ddy, int dw, int dh, int numRowsWritten, int progressReportRowPeriod) throws IOException { if (DEBUG) System.out.println("Writing optimized"); offset += dy*lineStride; lineStride *= ddy; for (int y = dy; y < dh; y += ddy) { if (numRowsWritten % progressReportRowPeriod == 0) { if (abortRequested()) { processWriteAborted(); return; } processImageProgress((numRowsWritten*100.0F)/dh); } compressor.compress(data, offset, dw); numRowsWritten++; offset += lineStride; } } private void writeRasterData(RenderedImage image, Rectangle sourceBounds, Dimension destSize, ImageWriteParam param, boolean interlaceFlag) throws IOException { int sourceXOffset = sourceBounds.x; int sourceYOffset = sourceBounds.y; int sourceWidth = sourceBounds.width; int sourceHeight = sourceBounds.height; int destWidth = destSize.width; int destHeight = destSize.height; int periodX; int periodY; if (param == null) { periodX = 1; periodY = 1; } else { periodX = param.getSourceXSubsampling(); periodY = param.getSourceYSubsampling(); } SampleModel sampleModel = image.getSampleModel(); int bitsPerPixel = sampleModel.getSampleSize()[0]; int initCodeSize = bitsPerPixel; if (initCodeSize == 1) { initCodeSize++; } stream.write(initCodeSize); LZWCompressor compressor = new LZWCompressor(stream, initCodeSize, false); boolean isOptimizedCase = periodX == 1 && periodY == 1 && sampleModel instanceof ComponentSampleModel && image.getNumXTiles() == 1 && image.getNumYTiles() == 1 && image.getTile(0, 0).getDataBuffer() instanceof DataBufferByte; int numRowsWritten = 0; int progressReportRowPeriod = Math.max(destHeight/20, 1); processImageStarted(imageIndex); if (interlaceFlag) { if (DEBUG) System.out.println("Writing interlaced"); if (isOptimizedCase) { Raster tile = image.getTile(0, 0); byte[] data = ((DataBufferByte)tile.getDataBuffer()).getData(); ComponentSampleModel csm = (ComponentSampleModel)tile.getSampleModel(); int offset = csm.getOffset(sourceXOffset - tile.getSampleModelTranslateX(), sourceYOffset - tile.getSampleModelTranslateY(), 0); int lineStride = csm.getScanlineStride(); writeRowsOpt(data, offset, lineStride, compressor, 0, 8, destWidth, destHeight, numRowsWritten, progressReportRowPeriod); if (abortRequested()) { return; } numRowsWritten += destHeight/8; writeRowsOpt(data, offset, lineStride, compressor, 4, 8, destWidth, destHeight, numRowsWritten, progressReportRowPeriod); if (abortRequested()) { return; } numRowsWritten += (destHeight - 4)/8; writeRowsOpt(data, offset, lineStride, compressor, 2, 4, destWidth, destHeight, numRowsWritten, progressReportRowPeriod); if (abortRequested()) { return; } numRowsWritten += (destHeight - 2)/4; writeRowsOpt(data, offset, lineStride, compressor, 1, 2, destWidth, destHeight, numRowsWritten, progressReportRowPeriod); } else { writeRows(image, compressor, sourceXOffset, periodX, sourceYOffset, 8*periodY, sourceWidth, 0, 8, destWidth, destHeight, numRowsWritten, progressReportRowPeriod); if (abortRequested()) { return; } numRowsWritten += destHeight/8; writeRows(image, compressor, sourceXOffset, periodX, sourceYOffset + 4*periodY, 8*periodY, sourceWidth, 4, 8, destWidth, destHeight, numRowsWritten, progressReportRowPeriod); if (abortRequested()) { return; } numRowsWritten += (destHeight - 4)/8; writeRows(image, compressor, sourceXOffset, periodX, sourceYOffset + 2*periodY, 4*periodY, sourceWidth, 2, 4, destWidth, destHeight, numRowsWritten, progressReportRowPeriod); if (abortRequested()) { return; } numRowsWritten += (destHeight - 2)/4; writeRows(image, compressor, sourceXOffset, periodX, sourceYOffset + periodY, 2*periodY, sourceWidth, 1, 2, destWidth, destHeight, numRowsWritten, progressReportRowPeriod); } } else { if (DEBUG) System.out.println("Writing non-interlaced"); if (isOptimizedCase) { Raster tile = image.getTile(0, 0); byte[] data = ((DataBufferByte)tile.getDataBuffer()).getData(); ComponentSampleModel csm = (ComponentSampleModel)tile.getSampleModel(); int offset = csm.getOffset(sourceXOffset - tile.getSampleModelTranslateX(), sourceYOffset - tile.getSampleModelTranslateY(), 0); int lineStride = csm.getScanlineStride(); writeRowsOpt(data, offset, lineStride, compressor, 0, 1, destWidth, destHeight, numRowsWritten, progressReportRowPeriod); } else { writeRows(image, compressor, sourceXOffset, periodX, sourceYOffset, periodY, sourceWidth, 0, 1, destWidth, destHeight, numRowsWritten, progressReportRowPeriod); } } if (abortRequested()) { return; } processImageProgress(100.0F); compressor.flush(); stream.write(0x00); processImageComplete(); } private void writeHeader(String version, int logicalScreenWidth, int logicalScreenHeight, int colorResolution, int pixelAspectRatio, int backgroundColorIndex, boolean sortFlag, int bitsPerPixel, byte[] globalColorTable) throws IOException { try { // Signature stream.writeBytes("GIF"+version); // Screen Descriptor // Width stream.writeShort((short)logicalScreenWidth); // Height stream.writeShort((short)logicalScreenHeight); // Global Color Table // Packed fields int packedFields = globalColorTable != null ? 0x80 : 0x00; packedFields |= ((colorResolution - 1) & 0x7) << 4; if (sortFlag) { packedFields |= 0x8; } packedFields |= (bitsPerPixel - 1); stream.write(packedFields); // Background color index stream.write(backgroundColorIndex); // Pixel aspect ratio stream.write(pixelAspectRatio); // Global Color Table if (globalColorTable != null) { stream.write(globalColorTable); } } catch (IOException e) { throw new IIOException("I/O error writing header!", e); } } private void writeHeader(IIOMetadata streamMetadata, int bitsPerPixel) throws IOException { GIFWritableStreamMetadata sm; if (streamMetadata instanceof GIFWritableStreamMetadata) { sm = (GIFWritableStreamMetadata)streamMetadata; } else { sm = new GIFWritableStreamMetadata(); Node root = streamMetadata.getAsTree(STREAM_METADATA_NAME); sm.setFromTree(STREAM_METADATA_NAME, root); } writeHeader(sm.version, sm.logicalScreenWidth, sm.logicalScreenHeight, sm.colorResolution, sm.pixelAspectRatio, sm.backgroundColorIndex, sm.sortFlag, bitsPerPixel, sm.globalColorTable); } private void writeGraphicControlExtension(int disposalMethod, boolean userInputFlag, boolean transparentColorFlag, int delayTime, int transparentColorIndex) throws IOException { try { stream.write(0x21); stream.write(0xf9); stream.write(4); int packedFields = (disposalMethod & 0x3) << 2; if (userInputFlag) { packedFields |= 0x2; } if (transparentColorFlag) { packedFields |= 0x1; } stream.write(packedFields); stream.writeShort((short)delayTime); stream.write(transparentColorIndex); stream.write(0x00); } catch (IOException e) { throw new IIOException("I/O error writing Graphic Control Extension!", e); } } private void writeGraphicControlExtension(GIFWritableImageMetadata im) throws IOException { writeGraphicControlExtension(im.disposalMethod, im.userInputFlag, im.transparentColorFlag, im.delayTime, im.transparentColorIndex); } private void writeBlocks(byte[] data) throws IOException { if (data != null && data.length > 0) { int offset = 0; while (offset < data.length) { int len = Math.min(data.length - offset, 255); stream.write(len); stream.write(data, offset, len); offset += len; } } } private void writePlainTextExtension(GIFWritableImageMetadata im) throws IOException { if (im.hasPlainTextExtension) { try { stream.write(0x21); stream.write(0x1); stream.write(12); stream.writeShort(im.textGridLeft); stream.writeShort(im.textGridTop); stream.writeShort(im.textGridWidth); stream.writeShort(im.textGridHeight); stream.write(im.characterCellWidth); stream.write(im.characterCellHeight); stream.write(im.textForegroundColor); stream.write(im.textBackgroundColor); writeBlocks(im.text); stream.write(0x00); } catch (IOException e) { throw new IIOException("I/O error writing Plain Text Extension!", e); } } } private void writeApplicationExtension(GIFWritableImageMetadata im) throws IOException { if (im.applicationIDs != null) { Iterator iterIDs = im.applicationIDs.iterator(); Iterator iterCodes = im.authenticationCodes.iterator(); Iterator iterData = im.applicationData.iterator(); while (iterIDs.hasNext()) { try { stream.write(0x21); stream.write(0xff); stream.write(11); stream.write((byte[])iterIDs.next(), 0, 8); stream.write((byte[])iterCodes.next(), 0, 3); writeBlocks((byte[])iterData.next()); stream.write(0x00); } catch (IOException e) { throw new IIOException("I/O error writing Application Extension!", e); } } } } private void writeCommentExtension(GIFWritableImageMetadata im) throws IOException { if (im.comments != null) { try { Iterator iter = im.comments.iterator(); while (iter.hasNext()) { stream.write(0x21); stream.write(0xfe); writeBlocks((byte[])iter.next()); stream.write(0x00); } } catch (IOException e) { throw new IIOException("I/O error writing Comment Extension!", e); } } } private void writeImageDescriptor(int imageLeftPosition, int imageTopPosition, int imageWidth, int imageHeight, boolean interlaceFlag, boolean sortFlag, int bitsPerPixel, byte[] localColorTable) throws IOException { try { stream.write(0x2c); stream.writeShort((short)imageLeftPosition); stream.writeShort((short)imageTopPosition); stream.writeShort((short)imageWidth); stream.writeShort((short)imageHeight); int packedFields = localColorTable != null ? 0x80 : 0x00; if (interlaceFlag) { packedFields |= 0x40; } if (sortFlag) { packedFields |= 0x8; } packedFields |= (bitsPerPixel - 1); stream.write(packedFields); if (localColorTable != null) { stream.write(localColorTable); } } catch (IOException e) { throw new IIOException("I/O error writing Image Descriptor!", e); } } private void writeImageDescriptor(GIFWritableImageMetadata imageMetadata, int bitsPerPixel) throws IOException { writeImageDescriptor(imageMetadata.imageLeftPosition, imageMetadata.imageTopPosition, imageMetadata.imageWidth, imageMetadata.imageHeight, imageMetadata.interlaceFlag, imageMetadata.sortFlag, bitsPerPixel, imageMetadata.localColorTable); } private void writeTrailer() throws IOException { stream.write(0x3b); } } class GIFImageWriteParam extends ImageWriteParam { GIFImageWriteParam(Locale locale) { super(locale); this.canWriteCompressed = true; this.canWriteProgressive = true; this.compressionTypes = new String[] {"LZW", "lzw"}; this.compressionType = compressionTypes[0]; } public void setCompressionMode(int mode) { if (mode == MODE_DISABLED) { throw new UnsupportedOperationException("MODE_DISABLED is not supported."); } super.setCompressionMode(mode); } } ././@LongLink0000000000000000000000000000015300000000000011564 Lustar rootrootjai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/gif/GIFWritableImageMetadata.javajai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/gif/GIFWritableImageMetadat0000664000175100017510000004335610411071363032473 0ustar tilletille/* * $RCSfile: GIFWritableImageMetadata.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.2 $ * $Date: 2006-03-24 22:30:11 $ * $State: Exp $ */ package com.sun.media.imageioimpl.plugins.gif; import java.io.UnsupportedEncodingException; import java.nio.charset.Charset; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import javax.imageio.ImageTypeSpecifier; import javax.imageio.metadata.IIOInvalidTreeException; import javax.imageio.metadata.IIOMetadata; import javax.imageio.metadata.IIOMetadataNode; import javax.imageio.metadata.IIOMetadataFormat; import javax.imageio.metadata.IIOMetadataFormatImpl; import org.w3c.dom.Node; class GIFWritableImageMetadata extends GIFImageMetadata { // package scope static final String NATIVE_FORMAT_NAME = "javax_imageio_gif_image_1.0"; GIFWritableImageMetadata() { super(true, NATIVE_FORMAT_NAME, "com.sun.media.imageioimpl.plugins.gif.GIFImageMetadataFormat", null, null); } public boolean isReadOnly() { return false; } public void reset() { // Fields from Image Descriptor imageLeftPosition = 0; imageTopPosition = 0; imageWidth = 0; imageHeight = 0; interlaceFlag = false; sortFlag = false; localColorTable = null; // Fields from Graphic Control Extension disposalMethod = 0; userInputFlag = false; transparentColorFlag = false; delayTime = 0; transparentColorIndex = 0; // Fields from Plain Text Extension hasPlainTextExtension = false; textGridLeft = 0; textGridTop = 0; textGridWidth = 0; textGridHeight = 0; characterCellWidth = 0; characterCellHeight = 0; textForegroundColor = 0; textBackgroundColor = 0; text = null; // Fields from ApplicationExtension applicationIDs = null; authenticationCodes = null; applicationData = null; // Fields from CommentExtension // List of byte[] comments = null; } private byte[] fromISO8859(String data) { try { return data.getBytes("ISO-8859-1"); } catch (UnsupportedEncodingException e) { return (new String("")).getBytes(); } } protected void mergeNativeTree(Node root) throws IIOInvalidTreeException { Node node = root; if (!node.getNodeName().equals(nativeMetadataFormatName)) { fatal(node, "Root must be " + nativeMetadataFormatName); } node = node.getFirstChild(); while (node != null) { String name = node.getNodeName(); if (name.equals("ImageDescriptor")) { imageLeftPosition = getIntAttribute(node, "imageLeftPosition", -1, true, true, 0, 65535); imageTopPosition = getIntAttribute(node, "imageTopPosition", -1, true, true, 0, 65535); imageWidth = getIntAttribute(node, "imageWidth", -1, true, true, 1, 65535); imageHeight = getIntAttribute(node, "imageHeight", -1, true, true, 1, 65535); interlaceFlag = getBooleanAttribute(node, "interlaceFlag", false, true); } else if (name.equals("LocalColorTable")) { int sizeOfLocalColorTable = getIntAttribute(node, "sizeOfLocalColorTable", true, 2, 256); if (sizeOfLocalColorTable != 2 && sizeOfLocalColorTable != 4 && sizeOfLocalColorTable != 8 && sizeOfLocalColorTable != 16 && sizeOfLocalColorTable != 32 && sizeOfLocalColorTable != 64 && sizeOfLocalColorTable != 128 && sizeOfLocalColorTable != 256) { fatal(node, "Bad value for LocalColorTable attribute sizeOfLocalColorTable!"); } sortFlag = getBooleanAttribute(node, "sortFlag", false, true); localColorTable = getColorTable(node, "ColorTableEntry", true, sizeOfLocalColorTable); } else if (name.equals("GraphicControlExtension")) { String disposalMethodName = getStringAttribute(node, "disposalMethod", null, true, disposalMethodNames); disposalMethod = 0; while(!disposalMethodName.equals(disposalMethodNames[disposalMethod])) { disposalMethod++; } userInputFlag = getBooleanAttribute(node, "userInputFlag", false, true); transparentColorFlag = getBooleanAttribute(node, "transparentColorFlag", false, true); delayTime = getIntAttribute(node, "delayTime", -1, true, true, 0, 65535); transparentColorIndex = getIntAttribute(node, "transparentColorIndex", -1, true, true, 0, 65535); } else if (name.equals("PlainTextExtension")) { hasPlainTextExtension = true; textGridLeft = getIntAttribute(node, "textGridLeft", -1, true, true, 0, 65535); textGridTop = getIntAttribute(node, "textGridTop", -1, true, true, 0, 65535); textGridWidth = getIntAttribute(node, "textGridWidth", -1, true, true, 1, 65535); textGridHeight = getIntAttribute(node, "textGridHeight", -1, true, true, 1, 65535); characterCellWidth = getIntAttribute(node, "characterCellWidth", -1, true, true, 1, 65535); characterCellHeight = getIntAttribute(node, "characterCellHeight", -1, true, true, 1, 65535); textForegroundColor = getIntAttribute(node, "textForegroundColor", -1, true, true, 0, 255); textBackgroundColor = getIntAttribute(node, "textBackgroundColor", -1, true, true, 0, 255); // XXX The "text" attribute of the PlainTextExtension element // is not defined in the GIF image metadata format but it is // present in the GIFImageMetadata class. Consequently it is // used here but not required and with a default of "". See // bug 5082763. String textString = getStringAttribute(node, "text", "", false, null); text = fromISO8859(textString); } else if (name.equals("ApplicationExtensions")) { IIOMetadataNode applicationExtension = (IIOMetadataNode)node.getFirstChild(); if (!applicationExtension.getNodeName().equals("ApplicationExtension")) { fatal(node, "Only a ApplicationExtension may be a child of a ApplicationExtensions!"); } String applicationIDString = getStringAttribute(applicationExtension, "applicationID", null, true, null); String authenticationCodeString = getStringAttribute(applicationExtension, "authenticationCode", null, true, null); Object applicationExtensionData = applicationExtension.getUserObject(); if (applicationExtensionData == null || !(applicationExtensionData instanceof byte[])) { fatal(applicationExtension, "Bad user object in ApplicationExtension!"); } if (applicationIDs == null) { applicationIDs = new ArrayList(); authenticationCodes = new ArrayList(); applicationData = new ArrayList(); } applicationIDs.add(fromISO8859(applicationIDString)); authenticationCodes.add(fromISO8859(authenticationCodeString)); applicationData.add(applicationExtensionData); } else if (name.equals("CommentExtensions")) { Node commentExtension = node.getFirstChild(); if (commentExtension != null) { while(commentExtension != null) { if (!commentExtension.getNodeName().equals("CommentExtension")) { fatal(node, "Only a CommentExtension may be a child of a CommentExtensions!"); } if (comments == null) { comments = new ArrayList(); } String comment = getStringAttribute(commentExtension, "value", null, true, null); comments.add(fromISO8859(comment)); commentExtension = commentExtension.getNextSibling(); } } } else { fatal(node, "Unknown child of root node!"); } node = node.getNextSibling(); } } protected void mergeStandardTree(Node root) throws IIOInvalidTreeException { Node node = root; if (!node.getNodeName() .equals(IIOMetadataFormatImpl.standardMetadataFormatName)) { fatal(node, "Root must be " + IIOMetadataFormatImpl.standardMetadataFormatName); } node = node.getFirstChild(); while (node != null) { String name = node.getNodeName(); if (name.equals("Chroma")) { Node childNode = node.getFirstChild(); while(childNode != null) { String childName = childNode.getNodeName(); if (childName.equals("Palette")) { localColorTable = getColorTable(childNode, "PaletteEntry", false, -1); break; } childNode = childNode.getNextSibling(); } } else if (name.equals("Compression")) { Node childNode = node.getFirstChild(); while(childNode != null) { String childName = childNode.getNodeName(); if (childName.equals("NumProgressiveScans")) { int numProgressiveScans = getIntAttribute(childNode, "value", 4, false, true, 1, Integer.MAX_VALUE); if (numProgressiveScans > 1) { interlaceFlag = true; } break; } childNode = childNode.getNextSibling(); } } else if (name.equals("Dimension")) { Node childNode = node.getFirstChild(); while(childNode != null) { String childName = childNode.getNodeName(); if (childName.equals("HorizontalPixelOffset")) { imageLeftPosition = getIntAttribute(childNode, "value", -1, true, true, 0, 65535); } else if (childName.equals("VerticalPixelOffset")) { imageTopPosition = getIntAttribute(childNode, "value", -1, true, true, 0, 65535); } childNode = childNode.getNextSibling(); } } else if (name.equals("Text")) { Node childNode = node.getFirstChild(); while(childNode != null) { String childName = childNode.getNodeName(); if (childName.equals("TextEntry") && getAttribute(childNode, "compression", "none", false).equals("none") && Charset.isSupported(getAttribute(childNode, "encoding", "ISO-8859-1", false))) { String value = getAttribute(childNode, "value"); byte[] comment = fromISO8859(value); if (comments == null) { comments = new ArrayList(); } comments.add(comment); } childNode = childNode.getNextSibling(); } } else if (name.equals("Transparency")) { Node childNode = node.getFirstChild(); while(childNode != null) { String childName = childNode.getNodeName(); if (childName.equals("TransparentIndex")) { transparentColorIndex = getIntAttribute(childNode, "value", -1, true, true, 0, 255); transparentColorFlag = true; break; } childNode = childNode.getNextSibling(); } } node = node.getNextSibling(); } } public void setFromTree(String formatName, Node root) throws IIOInvalidTreeException { reset(); mergeTree(formatName, root); } } ././@LongLink0000000000000000000000000000016200000000000011564 Lustar rootrootjai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/gif/GIFImageMetadataFormatResources.javajai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/gif/GIFImageMetadataFormatR0000775000175100017510000001266310411071363032435 0ustar tilletille/* * $RCSfile: GIFImageMetadataFormatResources.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.1 $ * $Date: 2006-03-24 22:30:10 $ * $State: Exp $ */ package com.sun.media.imageioimpl.plugins.gif; import java.util.ListResourceBundle; public class GIFImageMetadataFormatResources extends ListResourceBundle { public GIFImageMetadataFormatResources() {} protected Object[][] getContents() { return new Object[][] { // Node name, followed by description { "ImageDescriptor", "The image descriptor" }, { "LocalColorTable", "The local color table" }, { "ColorTableEntry", "A local color table entry" }, { "GraphicControlExtension", "A graphic control extension" }, { "PlainTextExtension", "A plain text (text grid) extension" }, { "ApplicationExtensions", "A set of application extensions" }, { "ApplicationExtension", "An application extension" }, { "CommentExtensions", "A set of comments" }, { "CommentExtension", "A comment" }, // Node name + "/" + AttributeName, followed by description { "ImageDescriptor/imageLeftPosition", "The X offset of the image relative to the screen origin" }, { "ImageDescriptor/imageTopPosition", "The Y offset of the image relative to the screen origin" }, { "ImageDescriptor/imageWidth", "The width of the image" }, { "ImageDescriptor/imageHeight", "The height of the image" }, { "ImageDescriptor/interlaceFlag", "True if the image is stored using interlacing" }, { "LocalColorTable/sizeOfLocalColorTable", "The number of entries in the local color table" }, { "LocalColorTable/sortFlag", "True if the local color table is sorted by frequency" }, { "ColorTableEntry/index", "The index of the color table entry" }, { "ColorTableEntry/red", "The red value for the color table entry" }, { "ColorTableEntry/green", "The green value for the color table entry" }, { "ColorTableEntry/blue", "The blue value for the color table entry" }, { "GraphicControlExtension/disposalMethod", "The disposal method for this frame" }, { "GraphicControlExtension/userInputFlag", "True if the frame should be advanced based on user input" }, { "GraphicControlExtension/transparentColorFlag", "True if a transparent color exists" }, { "GraphicControlExtension/delayTime", "The time to delay between frames, in hundredths of a second" }, { "GraphicControlExtension/transparentColorIndex", "The transparent color, if transparentColorFlag is true" }, { "PlainTextExtension/textGridLeft", "The X offset of the text grid" }, { "PlainTextExtension/textGridTop", "The Y offset of the text grid" }, { "PlainTextExtension/textGridWidth", "The number of columns in the text grid" }, { "PlainTextExtension/textGridHeight", "The number of rows in the text grid" }, { "PlainTextExtension/characterCellWidth", "The width of a character cell" }, { "PlainTextExtension/characterCellHeight", "The height of a character cell" }, { "PlainTextExtension/textForegroundColor", "The text foreground color index" }, { "PlainTextExtension/textBackgroundColor", "The text background color index" }, { "ApplicationExtension/applicationID", "The application ID" }, { "ApplicationExtension/authenticationCode", "The authentication code" }, { "CommentExtension/value", "The comment" }, }; } } ././@LongLink0000000000000000000000000000016300000000000011565 Lustar rootrootjai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/gif/GIFStreamMetadataFormatResources.javajai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/gif/GIFStreamMetadataFormat0000775000175100017510000000747610411071363032532 0ustar tilletille /* * $RCSfile: GIFStreamMetadataFormatResources.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.1 $ * $Date: 2006-03-24 22:30:11 $ * $State: Exp $ */ package com.sun.media.imageioimpl.plugins.gif; import java.util.ListResourceBundle; public class GIFStreamMetadataFormatResources extends ListResourceBundle { public GIFStreamMetadataFormatResources() {} protected Object[][] getContents() { return new Object[][] { // Node name, followed by description { "Version", "The file version, either 87a or 89a" }, { "LogicalScreenDescriptor", "The logical screen descriptor, except for the global color table" }, { "GlobalColorTable", "The global color table" }, { "ColorTableEntry", "A global color table entry" }, // Node name + "/" + AttributeName, followed by description { "Version/value", "The version string" }, { "LogicalScreenDescriptor/logicalScreenWidth", "The width in pixels of the whole picture" }, { "LogicalScreenDescriptor/logicalScreenHeight", "The height in pixels of the whole picture" }, { "LogicalScreenDescriptor/colorResolution", "The number of bits of color resolution, beteen 1 and 8" }, { "LogicalScreenDescriptor/pixelAspectRatio", "If 0, indicates square pixels, else W/H = (value + 15)/64" }, { "GlobalColorTable/sizeOfGlobalColorTable", "The number of entries in the global color table" }, { "GlobalColorTable/backgroundColorIndex", "The index of the color table entry to be used as a background" }, { "GlobalColorTable/sortFlag", "True if the global color table is sorted by frequency" }, { "ColorTableEntry/index", "The index of the color table entry" }, { "ColorTableEntry/red", "The red value for the color table entry" }, { "ColorTableEntry/green", "The green value for the color table entry" }, { "ColorTableEntry/blue", "The blue value for the color table entry" }, }; } } jai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/png/0000775000175100017510000000000011650556207026225 5ustar tilletille././@LongLink0000000000000000000000000000014500000000000011565 Lustar rootrootjai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/png/CLibPNGImageWriter.javajai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/png/CLibPNGImageWriter.java0000664000175100017510000003745410522220614032406 0ustar tilletille/* * $RCSfile: CLibPNGImageWriter.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.7 $ * $Date: 2006-11-01 22:37:00 $ * $State: Exp $ */ package com.sun.media.imageioimpl.plugins.png; import java.awt.Color; import java.awt.color.ColorSpace; import java.awt.color.ICC_ColorSpace; import java.awt.color.ICC_Profile; import java.awt.image.ColorModel; import java.awt.image.IndexColorModel; import java.awt.image.RenderedImage; import java.awt.image.SampleModel; import java.io.IOException; import java.io.OutputStream; import java.util.Arrays; import java.util.Locale; import javax.imageio.IIOException; import javax.imageio.IIOImage; import javax.imageio.ImageWriter; import javax.imageio.ImageWriteParam; import javax.imageio.ImageTypeSpecifier; import javax.imageio.metadata.IIOInvalidTreeException; import javax.imageio.metadata.IIOMetadata; import javax.imageio.metadata.IIOMetadataFormatImpl; import javax.imageio.spi.ImageWriterSpi; import javax.imageio.stream.ImageOutputStream; import com.sun.media.imageioimpl.common.ImageUtil; import com.sun.media.imageioimpl.plugins.clib.CLibImageWriter; import com.sun.media.imageioimpl.plugins.clib.OutputStreamAdapter; import com.sun.medialib.codec.png.Constants; import com.sun.medialib.codec.png.Encoder; import com.sun.medialib.codec.jiio.mediaLibImage; final class CLibPNGImageWriter extends CLibImageWriter { CLibPNGImageWriter(ImageWriterSpi originatingProvider) { super(originatingProvider); } public ImageWriteParam getDefaultWriteParam() { return new CLibPNGImageWriteParam(getLocale()); } public IIOMetadata getDefaultImageMetadata(ImageTypeSpecifier imageType, ImageWriteParam param) { CLibPNGMetadata m = new CLibPNGMetadata(); if(param != null && param.getDestinationType() != null) { imageType = param.getDestinationType(); } if(imageType != null) { m.initialize(imageType, imageType.getSampleModel().getNumBands(), param, 0); } return m; } public IIOMetadata convertImageMetadata(IIOMetadata inData, ImageTypeSpecifier imageType, ImageWriteParam param) { // Check arguments. if(inData == null) { throw new IllegalArgumentException("inData == null!"); } if(imageType == null) { throw new IllegalArgumentException("imageType == null!"); } CLibPNGMetadata outData = null; // Obtain a CLibPNGMetadata object. if(inData instanceof CLibPNGMetadata) { // Clone the input metadata. outData = (CLibPNGMetadata)((CLibPNGMetadata)inData).clone(); } else { try { outData = new CLibPNGMetadata(inData); } catch(IIOInvalidTreeException e) { // XXX Warning outData = new CLibPNGMetadata(); } } // Update the metadata per the image type and param. outData.initialize(imageType, imageType.getSampleModel().getNumBands(), param, outData.IHDR_interlaceMethod); return outData; } public void write(IIOMetadata streamMetadata, IIOImage image, ImageWriteParam param) throws IOException { if(output == null) { throw new IllegalStateException("output == null"); } OutputStream stream = null; if(output instanceof ImageOutputStream) { stream = new OutputStreamAdapter((ImageOutputStream)output); } else { throw new IllegalArgumentException ("!(output instanceof ImageOutputStream)"); } RenderedImage renderedImage = image.getRenderedImage(); ImageUtil.canEncodeImage(this, renderedImage.getColorModel(), renderedImage.getSampleModel()); int[] supportedFormats = new int[] { Constants.MLIB_FORMAT_GRAYSCALE, Constants.MLIB_FORMAT_GRAYSCALE_ALPHA, Constants.MLIB_FORMAT_INDEXED, Constants.MLIB_FORMAT_BGR, Constants.MLIB_FORMAT_RGB, Constants.MLIB_FORMAT_BGRA, Constants.MLIB_FORMAT_RGBA }; mediaLibImage mlImage = getMediaLibImage(renderedImage, param, true, supportedFormats); Encoder encoder = null; try { encoder = new Encoder(mlImage); } catch(Throwable t) { throw new IIOException("codecLib error", t); } // Set the maximum length of the iDAT chunk. encoder.setIDATSize(8192); // Determine the image type. ImageTypeSpecifier imageType; if(param != null && param.getDestinationType() != null) { imageType = param.getDestinationType(); } else if(mlImage.getType() == mediaLibImage.MLIB_BIT) { if(renderedImage.getColorModel() instanceof IndexColorModel) { imageType = new ImageTypeSpecifier(renderedImage.getColorModel(), renderedImage.getSampleModel()); } else { int dataType = renderedImage.getSampleModel().getDataType(); imageType = ImageTypeSpecifier.createGrayscale(1, dataType, false); } } else if(mlImage.getChannels() == renderedImage.getSampleModel().getNumBands()) { // Note: ImageTypeSpecifier.createFromRenderedImage() gave an // incorrect result here for an indexed BufferedImage as the // ImageTypeSpecifier generated by createFromBufferedImage() // does not match the actual image. imageType = new ImageTypeSpecifier(renderedImage); } else { SampleModel sm = renderedImage.getSampleModel(); int dataType = sm.getDataType(); int bitDepth = sm.getSampleSize(0); int numBands = mlImage.getChannels(); switch(numBands) { case 1: imageType = ImageTypeSpecifier.createGrayscale(bitDepth, dataType, false); break; case 2: imageType = ImageTypeSpecifier.createGrayscale(bitDepth, dataType, false, false); break; case 3: ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_sRGB); imageType = ImageTypeSpecifier.createInterleaved(cs, new int[] {0, 1, 2}, dataType, false, false); break; default: throw new IIOException("Cannot encode image with "+ numBands+" bands!"); } } // Get metadata. IIOMetadata imageMetadata = image.getMetadata(); if(imageMetadata != null) { // Convert metadata. imageMetadata = convertImageMetadata(imageMetadata, imageType, param); } else { // Use default. imageMetadata = getDefaultImageMetadata(imageType, param); } // Set metadata on encoder. ((CLibPNGMetadata)imageMetadata).writeMetadata(encoder); ColorModel colorModel = null; if(param != null) { ImageTypeSpecifier destinationType = param.getDestinationType(); if(destinationType != null) { colorModel = destinationType.getColorModel(); } // Set compression level to (int)(9*(1.0F - compressionQuality)). if(param.getCompressionMode() == ImageWriteParam.MODE_EXPLICIT) { try { int compressionLevel = (int)(9*(1.0F - param.getCompressionQuality())); encoder.setCompressionLevel(compressionLevel); } catch(Throwable t) { throw new IIOException("codecLib error", t); } // Set the strategy if appropriate. if(param instanceof CLibPNGImageWriteParam) { try { encoder.setStrategy( ((CLibPNGImageWriteParam)param).getStrategy()); } catch(Throwable t) { throw new IIOException("codecLib error", t); } } } } else { // null ImageWriteParam try { // Do not set the compression level: let it default. // Z_DEFAULT_STRATEGY encoder.setStrategy(0); } catch(Throwable t) { throw new IIOException("codecLib error", t); } } if(colorModel == null) { colorModel = renderedImage.getColorModel(); } // If no iCCP chunk is already in the metadata and the color space // is a non-standard ICC color space, the write it to iCCP chunk. if(!((CLibPNGMetadata)imageMetadata).iCCP_present && colorModel != null && ImageUtil.isNonStandardICCColorSpace(colorModel.getColorSpace())) { // Get the profile data. ICC_ColorSpace iccColorSpace = (ICC_ColorSpace)colorModel.getColorSpace(); ICC_Profile iccProfile = iccColorSpace.getProfile(); byte[] iccProfileData = iccColorSpace.getProfile().getData(); // Get the profile name. byte[] desc = iccProfile.getData(ICC_Profile.icSigProfileDescriptionTag); String profileName; if(desc != null) { long len = ((desc[8]&0xff) << 24) | ((desc[9]&0xff) << 16) | ((desc[10]&0xff) << 8) | (desc[11]&0xff); profileName = new String(desc, 12, (int)len); } else { profileName = "ICCProfile"; } // Set the profile on the Encoder. profileName = CLibPNGMetadata.toPrintableLatin1(profileName); encoder.setEmbeddedICCProfile(profileName, iccProfileData); } try { encoder.encode(stream); } catch(Throwable t) { throw new IIOException("codecLib error", t); } } } /** * This differs from the core PNG ImageWriteParam in that: * * . 'canWriteCompressed' is set to 'true' so that canWriteCompressed() * will return 'true'. * . compression types are: "DEFAULT", "FILTERED", and "HUFFMAN_ONLY" * and are used to set the encoder strategy to Z_DEFAULT, Z_FILTERED, * and Z_HUFFMAN_ONLY as described in the PNG specification. * . compression modes are: MODE_DEFAULT, MODE_EXPLICIT and * MODE_COPY_FROM_METADATA); MODE_DISABLED is not allowed. * . compression quality is used to set the compression level of the * encoder according to: * * compressionLevel = (int)(9*(1.0F - compressionQuality)) * * As in the core PNG writer, a progressiveMode of MODE_DEFAULT sets * Adam7 interlacing whereas MODE_DISABLED sets default interlacing, * i.e., none. */ final class CLibPNGImageWriteParam extends ImageWriteParam { private static final float DEFAULT_COMPRESSION_QUALITY = 1.0F/3.0F; // Encoder strategies mapped to compression types. private static final String DEFAULT_COMPRESSION_TYPE = "DEFAULT"; private static final String FILTERED_COMPRESSION_TYPE = "FILTERED"; private static final String HUFFMAN_COMPRESSION_TYPE = "HUFFMAN_ONLY"; // Compression descriptions private static final String[] compressionQualityDescriptions = new String[] { I18N.getString("CLibPNGImageWriteParam0"), I18N.getString("CLibPNGImageWriteParam1"), I18N.getString("CLibPNGImageWriteParam2") }; CLibPNGImageWriteParam(Locale locale) { super(locale); canWriteCompressed = true; canWriteProgressive = true; compressionTypes = new String[] {DEFAULT_COMPRESSION_TYPE, FILTERED_COMPRESSION_TYPE, HUFFMAN_COMPRESSION_TYPE}; compressionQuality = DEFAULT_COMPRESSION_QUALITY; compressionType = DEFAULT_COMPRESSION_TYPE; } int getStrategy() { if(compressionType.equals(FILTERED_COMPRESSION_TYPE)) { return 1; // Z_FILTERED } else if(compressionType.equals(HUFFMAN_COMPRESSION_TYPE)) { return 2; // Z_HUFFMAN_ONLY } else { return 0; // Z_DEFAULT_STRATEGY } } public String[] getCompressionQualityDescriptions() { super.getCompressionQualityDescriptions(); // Performs checks. return compressionQualityDescriptions; } public float[] getCompressionQualityValues() { super.getCompressionQualityValues(); // Performs checks. // According to the java.util.zip.Deflater class, the Deflater // level 1 gives the best speed (short of no compression). Since // quality is derived from level as // // quality = 1 - level/9 // // this gives a value of 8.0/9.0 for the corresponding quality. return new float[] { 0.0F, // "Best Compression" (float)(8.0F/9.0F), // "Best Speed" 1.0F }; // "No Compression" } public void setCompressionMode(int mode) { if(mode == MODE_DISABLED) { throw new UnsupportedOperationException("mode == MODE_DISABLED"); } super.setCompressionMode(mode); // This sets the instance variable. } public void unsetCompression() { super.unsetCompression(); // Performs checks. compressionQuality = DEFAULT_COMPRESSION_QUALITY; compressionType = DEFAULT_COMPRESSION_TYPE; } } jai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/png/CLibPNGMetadata.java0000664000175100017510000034575210400632760031716 0ustar tilletille/* * $RCSfile: CLibPNGMetadata.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.3 $ * $Date: 2006-02-27 17:25:04 $ * $State: Exp $ */ package com.sun.media.imageioimpl.plugins.png; import java.awt.image.ColorModel; import java.awt.image.IndexColorModel; import java.awt.image.SampleModel; import java.io.ByteArrayInputStream; import java.io.InputStream; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.util.ArrayList; import java.util.Arrays; import java.util.Calendar; import java.util.GregorianCalendar; import java.util.Iterator; import java.util.List; import java.util.StringTokenizer; import java.util.zip.DataFormatException; import java.util.zip.Deflater; import java.util.zip.Inflater; import javax.imageio.IIOException; import javax.imageio.ImageTypeSpecifier; import javax.imageio.ImageWriteParam; import javax.imageio.metadata.IIOInvalidTreeException; import javax.imageio.metadata.IIOMetadata; import javax.imageio.metadata.IIOMetadataFormat; import javax.imageio.metadata.IIOMetadataFormatImpl; import javax.imageio.metadata.IIOMetadataNode; import javax.imageio.stream.ImageInputStream; import javax.imageio.stream.MemoryCacheImageInputStream; import org.w3c.dom.Node; import com.sun.medialib.codec.png.Decoder; import com.sun.medialib.codec.png.Encoder; import com.sun.medialib.codec.png.PNGChunk; import com.sun.medialib.codec.png.PNGTextualData; import com.sun.medialib.codec.jiio.mediaLibImage; // // Core J2SE problems fixed in this package: // 5109146: // PNG: Background color initialization from standard metadata is incomplete // 5109114: // PNG: Cannot set IHDR_bitDepth from standard metadata /Data/BitsPerSample // 5106305: // PNG standard to native image metadata conversion incorrect for pixel size // 5106550: // PNG writer merge standard metadata fails for TextEntry sans #IMPLIED // attributes // 5082756: // Image I/O plug-ins set metadata boolean attributes to "true" or "false" // 5105068: // PNGImageWriter.convertImageMetadata() broken for non-PNGMetadata // /** */ public class CLibPNGMetadata extends IIOMetadata implements Cloneable { // package scope public static final String nativeMetadataFormatName = "javax_imageio_png_1.0"; protected static final String nativeMetadataFormatClassName = "com.sun.media.imageioimpl.plugins.png.CLibPNGMetadataFormat"; // Color types for IHDR chunk public static final String[] IHDR_colorTypeNames = { "Grayscale", null, "RGB", "Palette", "GrayAlpha", null, "RGBAlpha" }; public static final int[] IHDR_numChannels = { 1, 0, 3, 3, 2, 0, 4 }; // Bit depths for IHDR chunk public static final String[] IHDR_bitDepths = { "1", "2", "4", "8", "16" }; // Compression methods for IHDR chunk public static final String[] IHDR_compressionMethodNames = { "deflate" }; // Filter methods for IHDR chunk public static final String[] IHDR_filterMethodNames = { "adaptive" }; // Interlace methods for IHDR chunk public static final String[] IHDR_interlaceMethodNames = { "none", "adam7" }; // Compression methods for iCCP chunk public static final String[] iCCP_compressionMethodNames = { "deflate" }; // Compression methods for zTXt chunk public static final String[] zTXt_compressionMethodNames = { "deflate" }; // "Unknown" unit for pHYs chunk public static final int PHYS_UNIT_UNKNOWN = 0; // "Meter" unit for pHYs chunk public static final int PHYS_UNIT_METER = 1; // Unit specifiers for pHYs chunk public static final String[] unitSpecifierNames = { "unknown", "meter" }; // Rendering intents for sRGB chunk public static final String[] renderingIntentNames = { "Perceptual", // 0 "Relative colorimetric", // 1 "Saturation", // 2 "Absolute colorimetric" // 3 }; // Color space types for Chroma->ColorSpaceType node public static final String[] colorSpaceTypeNames = { "GRAY", null, "RGB", "RGB", "GRAY", null, "RGB" }; // BEGIN Definitions required for reading. // Critical chunks static final int IHDR_TYPE = chunkType("IHDR"); static final int PLTE_TYPE = chunkType("PLTE"); static final int IDAT_TYPE = chunkType("IDAT"); static final int IEND_TYPE = chunkType("IEND"); // Ancillary chunks static final int bKGD_TYPE = chunkType("bKGD"); static final int cHRM_TYPE = chunkType("cHRM"); static final int gAMA_TYPE = chunkType("gAMA"); static final int hIST_TYPE = chunkType("hIST"); static final int iCCP_TYPE = chunkType("iCCP"); static final int iTXt_TYPE = chunkType("iTXt"); static final int pHYs_TYPE = chunkType("pHYs"); static final int sBIT_TYPE = chunkType("sBIT"); static final int sPLT_TYPE = chunkType("sPLT"); static final int sRGB_TYPE = chunkType("sRGB"); static final int tEXt_TYPE = chunkType("tEXt"); static final int tIME_TYPE = chunkType("tIME"); static final int tRNS_TYPE = chunkType("tRNS"); static final int zTXt_TYPE = chunkType("zTXt"); static final int PNG_COLOR_GRAY = 0; static final int PNG_COLOR_RGB = 2; static final int PNG_COLOR_PALETTE = 3; static final int PNG_COLOR_GRAY_ALPHA = 4; static final int PNG_COLOR_RGB_ALPHA = 6; // END Definitions required for reading. // IHDR chunk public boolean IHDR_present; public int IHDR_width; public int IHDR_height; public int IHDR_bitDepth; public int IHDR_colorType; public int IHDR_compressionMethod; public int IHDR_filterMethod; public int IHDR_interlaceMethod; // 0 == none, 1 == adam7 // PLTE chunk public boolean PLTE_present; public byte[] PLTE_red; public byte[] PLTE_green; public byte[] PLTE_blue; // bKGD chunk // If external (non-PNG sourced) data has red = green = blue, // always store it as gray and promote when writing public boolean bKGD_present; public int bKGD_colorType; // PNG_COLOR_GRAY, _RGB, or _PALETTE public int bKGD_index; public int bKGD_gray; public int bKGD_red; public int bKGD_green; public int bKGD_blue; // cHRM chunk public boolean cHRM_present; public int cHRM_whitePointX; public int cHRM_whitePointY; public int cHRM_redX; public int cHRM_redY; public int cHRM_greenX; public int cHRM_greenY; public int cHRM_blueX; public int cHRM_blueY; // gAMA chunk public boolean gAMA_present; public int gAMA_gamma; // hIST chunk public boolean hIST_present; public char[] hIST_histogram; // iCCP chunk public boolean iCCP_present; public String iCCP_profileName; public int iCCP_compressionMethod; public byte[] iCCP_compressedProfile; // iTXt chunk public ArrayList iTXt_keyword = new ArrayList(); // Strings public ArrayList iTXt_compressionFlag = new ArrayList(); // Integers public ArrayList iTXt_compressionMethod = new ArrayList(); // Integers public ArrayList iTXt_languageTag = new ArrayList(); // Strings public ArrayList iTXt_translatedKeyword = new ArrayList(); // Strings public ArrayList iTXt_text = new ArrayList(); // Strings // pHYs chunk public boolean pHYs_present; public int pHYs_pixelsPerUnitXAxis; public int pHYs_pixelsPerUnitYAxis; public int pHYs_unitSpecifier; // 0 == unknown, 1 == meter // sBIT chunk public boolean sBIT_present; public int sBIT_colorType; // PNG_COLOR_GRAY, _GRAY_ALPHA, _RGB, _RGB_ALPHA public int sBIT_grayBits; public int sBIT_redBits; public int sBIT_greenBits; public int sBIT_blueBits; public int sBIT_alphaBits; // sPLT chunk public boolean sPLT_present; public String sPLT_paletteName; // 1-79 characters public int sPLT_sampleDepth; // 8 or 16 public int[] sPLT_red; public int[] sPLT_green; public int[] sPLT_blue; public int[] sPLT_alpha; public int[] sPLT_frequency; // sRGB chunk public boolean sRGB_present; public int sRGB_renderingIntent; // tEXt chunk public ArrayList tEXt_keyword = new ArrayList(); // 1-79 char Strings public ArrayList tEXt_text = new ArrayList(); // Strings // tIME chunk public boolean tIME_present; public int tIME_year; public int tIME_month; public int tIME_day; public int tIME_hour; public int tIME_minute; public int tIME_second; // tRNS chunk // If external (non-PNG sourced) data has red = green = blue, // always store it as gray and promote when writing public boolean tRNS_present; public int tRNS_colorType; // PNG_COLOR_GRAY, _RGB, or _PALETTE public byte[] tRNS_alpha; // May have fewer entries than PLTE_red, etc. public int tRNS_gray; public int tRNS_red; public int tRNS_green; public int tRNS_blue; // zTXt chunk public ArrayList zTXt_keyword = new ArrayList(); // Strings public ArrayList zTXt_compressionMethod = new ArrayList(); // Integers public ArrayList zTXt_text = new ArrayList(); // Strings // Unknown chunks public ArrayList unknownChunkType = new ArrayList(); // Strings public ArrayList unknownChunkData = new ArrayList(); // byte arrays /** * Converts its parameter to another String which contains * only printable Latin-1 characters but not leading, trailing, or * consecutive spaces. * * @param s the String to convert. * @return a printable Latin-1 String sans superfluous spaces. */ static String toPrintableLatin1(String s) { // Pass a null right back. if(s == null) return null; // Get Latin-1 characters. byte[] data = null; try { data = s.getBytes("ISO-8859-1"); } catch(UnsupportedEncodingException e) { // In theory this should not happen (assert). data = s.getBytes(); } // Copy printable characters omitting leading spaces and // all but first trailing space. int len = 0; int prev = 0; for (int i = 0; i < data.length; i++) { int d = data[i] & 0xFF; if (prev == 32 && d == 32) continue; if ((d > 32 && d <=126) || (d >= 161 && d <=255) || (d == 32 && len != 0)) data[len++] = (byte)d; prev = d; } // Return an empty string if no acceptable characters. if(len == 0) return ""; // Omit trailing space, if any. if(data[len - 1] == 32) len--; return new String(data, 0, len); } public CLibPNGMetadata() { super(true, nativeMetadataFormatName, nativeMetadataFormatClassName, null, null); } public CLibPNGMetadata(IIOMetadata metadata) throws IIOInvalidTreeException { this(); if(metadata != null) { List formats = Arrays.asList(metadata.getMetadataFormatNames()); if(formats.contains(nativeMetadataFormatName)) { // Initialize from native image metadata format. String format = nativeMetadataFormatName; setFromTree(format, metadata.getAsTree(format)); } else if(metadata.isStandardMetadataFormatSupported()) { // Initialize from standard metadata form of the input tree. String format = IIOMetadataFormatImpl.standardMetadataFormatName; setFromTree(format, metadata.getAsTree(format)); } } } /** * Sets the instance variables of the IHDR and if necessary PLTE and * tRNS chunks. The numBands parameter is necessary since * we may only be writing a subset of the image bands. */ public void initialize(ImageTypeSpecifier imageType, int numBands, ImageWriteParam param, int interlaceMethod) { ColorModel colorModel = imageType.getColorModel(); SampleModel sampleModel = imageType.getSampleModel(); // Intialize IHDR_width and IHDR_height IHDR_width = sampleModel.getWidth(); IHDR_height = sampleModel.getHeight(); // Initialize IHDR_bitDepth int[] sampleSize = sampleModel.getSampleSize(); int bitDepth = sampleSize[0]; // Choose max bit depth over all channels // Fixes bug 4413109 for (int i = 1; i < sampleSize.length; i++) { if (sampleSize[i] > bitDepth) { bitDepth = sampleSize[i]; } } // Multi-channel images must have a bit depth of 8 or 16 if (sampleSize.length > 1 && bitDepth < 8) { bitDepth = 8; } // Round bit depth up to a power of 2 if (bitDepth > 2 && bitDepth < 4) { bitDepth = 4; } else if (bitDepth > 4 && bitDepth < 8) { bitDepth = 8; } else if (bitDepth > 8 && bitDepth < 16) { bitDepth = 16; } else if (bitDepth > 16) { throw new RuntimeException("bitDepth > 16!"); } IHDR_bitDepth = bitDepth; // Initialize IHDR_colorType if (colorModel instanceof IndexColorModel) { IndexColorModel icm = (IndexColorModel)colorModel; int size = icm.getMapSize(); byte[] reds = new byte[size]; icm.getReds(reds); byte[] greens = new byte[size]; icm.getGreens(greens); byte[] blues = new byte[size]; icm.getBlues(blues); // Determine whether the color tables are actually a gray ramp // if the color type has not been set previously boolean isGray = false; if (!IHDR_present || (IHDR_colorType != PNG_COLOR_PALETTE)) { isGray = true; int scale = 255/((1 << IHDR_bitDepth) - 1); for (int i = 0; i < size; i++) { byte red = reds[i]; if ((red != (byte)(i*scale)) || (red != greens[i]) || (red != blues[i])) { isGray = false; break; } } } // Determine whether transparency exists boolean hasAlpha = colorModel.hasAlpha(); byte[] alpha = null; if (hasAlpha) { alpha = new byte[size]; icm.getAlphas(alpha); } if (isGray && hasAlpha) { IHDR_colorType = PNG_COLOR_GRAY_ALPHA; } else if (isGray) { IHDR_colorType = PNG_COLOR_GRAY; } else { IHDR_colorType = PNG_COLOR_PALETTE; // Initialize PLTE chunk PLTE_present = true; PLTE_red = (byte[])reds.clone(); PLTE_green = (byte[])greens.clone(); PLTE_blue = (byte[])blues.clone(); if (hasAlpha) { // Initialize tRNS chunk tRNS_present = true; tRNS_colorType = PNG_COLOR_PALETTE; tRNS_alpha = (byte[])alpha.clone(); } } } else { if (numBands == 1) { IHDR_colorType = PNG_COLOR_GRAY; } else if (numBands == 2) { IHDR_colorType = PNG_COLOR_GRAY_ALPHA; } else if (numBands == 3) { IHDR_colorType = PNG_COLOR_RGB; } else if (numBands == 4) { IHDR_colorType = PNG_COLOR_RGB_ALPHA; } else { throw new RuntimeException("Number of bands not 1-4!"); } } // Initialize IHDR_compressionMethod and IHDR_filterMethod IHDR_compressionMethod = IHDR_filterMethod = 0; // Only supported value // Initialize IHDR_interlaceMethod if(param != null && param.getProgressiveMode() == ImageWriteParam.MODE_DISABLED) { IHDR_interlaceMethod = 0; // No interlacing. } else if(param != null && param.getProgressiveMode() == ImageWriteParam.MODE_DEFAULT) { IHDR_interlaceMethod = 1; // Adam7 } else { // param == null || // param.getProgressiveMode() == // ImageWriteParam.MODE_COPY_FROM_METADATA IHDR_interlaceMethod = interlaceMethod; } IHDR_present = true; } public boolean isReadOnly() { return false; } private ArrayList cloneBytesArrayList(ArrayList in) { if (in == null) { return null; } else { ArrayList list = new ArrayList(in.size()); Iterator iter = in.iterator(); while (iter.hasNext()) { Object o = iter.next(); if (o == null) { list.add(null); } else { list.add(((byte[])o).clone()); } } return list; } } // Deep clone public Object clone() { CLibPNGMetadata metadata; try { metadata = (CLibPNGMetadata)super.clone(); } catch (CloneNotSupportedException e) { return null; } // unknownChunkData needs deep clone metadata.unknownChunkData = cloneBytesArrayList(this.unknownChunkData); return metadata; } public Node getAsTree(String formatName) { if (formatName.equals(nativeMetadataFormatName)) { return getNativeTree(); } else if (formatName.equals (IIOMetadataFormatImpl.standardMetadataFormatName)) { return getStandardTree(); } else { throw new IllegalArgumentException("Not a recognized format!"); } } private Node getNativeTree() { IIOMetadataNode node = null; // scratch node IIOMetadataNode root = new IIOMetadataNode(nativeMetadataFormatName); // IHDR if (IHDR_present) { IIOMetadataNode IHDR_node = new IIOMetadataNode("IHDR"); IHDR_node.setAttribute("width", Integer.toString(IHDR_width)); IHDR_node.setAttribute("height", Integer.toString(IHDR_height)); IHDR_node.setAttribute("bitDepth", Integer.toString(IHDR_bitDepth)); IHDR_node.setAttribute("colorType", IHDR_colorTypeNames[IHDR_colorType]); // IHDR_compressionMethod must be 0 in PNG 1.1 IHDR_node.setAttribute("compressionMethod", IHDR_compressionMethodNames[IHDR_compressionMethod]); // IHDR_filterMethod must be 0 in PNG 1.1 IHDR_node.setAttribute("filterMethod", IHDR_filterMethodNames[IHDR_filterMethod]); IHDR_node.setAttribute("interlaceMethod", IHDR_interlaceMethodNames[IHDR_interlaceMethod]); root.appendChild(IHDR_node); } // PLTE if (PLTE_present) { IIOMetadataNode PLTE_node = new IIOMetadataNode("PLTE"); int numEntries = PLTE_red.length; for (int i = 0; i < numEntries; i++) { IIOMetadataNode entry = new IIOMetadataNode("PLTEEntry"); entry.setAttribute("index", Integer.toString(i)); entry.setAttribute("red", Integer.toString(PLTE_red[i] & 0xff)); entry.setAttribute("green", Integer.toString(PLTE_green[i] & 0xff)); entry.setAttribute("blue", Integer.toString(PLTE_blue[i] & 0xff)); PLTE_node.appendChild(entry); } root.appendChild(PLTE_node); } // bKGD if (bKGD_present) { IIOMetadataNode bKGD_node = new IIOMetadataNode("bKGD"); if (bKGD_colorType == PNG_COLOR_PALETTE) { node = new IIOMetadataNode("bKGD_Palette"); node.setAttribute("index", Integer.toString(bKGD_index)); } else if (bKGD_colorType == PNG_COLOR_GRAY) { node = new IIOMetadataNode("bKGD_Grayscale"); node.setAttribute("gray", Integer.toString(bKGD_gray)); } else if (bKGD_colorType == PNG_COLOR_RGB) { node = new IIOMetadataNode("bKGD_RGB"); node.setAttribute("red", Integer.toString(bKGD_red)); node.setAttribute("green", Integer.toString(bKGD_green)); node.setAttribute("blue", Integer.toString(bKGD_blue)); } bKGD_node.appendChild(node); root.appendChild(bKGD_node); } // cHRM if (cHRM_present) { IIOMetadataNode cHRM_node = new IIOMetadataNode("cHRM"); cHRM_node.setAttribute("whitePointX", Integer.toString(cHRM_whitePointX)); cHRM_node.setAttribute("whitePointY", Integer.toString(cHRM_whitePointY)); cHRM_node.setAttribute("redX", Integer.toString(cHRM_redX)); cHRM_node.setAttribute("redY", Integer.toString(cHRM_redY)); cHRM_node.setAttribute("greenX", Integer.toString(cHRM_greenX)); cHRM_node.setAttribute("greenY", Integer.toString(cHRM_greenY)); cHRM_node.setAttribute("blueX", Integer.toString(cHRM_blueX)); cHRM_node.setAttribute("blueY", Integer.toString(cHRM_blueY)); root.appendChild(cHRM_node); } // gAMA if (gAMA_present) { IIOMetadataNode gAMA_node = new IIOMetadataNode("gAMA"); gAMA_node.setAttribute("value", Integer.toString(gAMA_gamma)); root.appendChild(gAMA_node); } // hIST if (hIST_present) { IIOMetadataNode hIST_node = new IIOMetadataNode("hIST"); for (int i = 0; i < hIST_histogram.length; i++) { IIOMetadataNode hist = new IIOMetadataNode("hISTEntry"); hist.setAttribute("index", Integer.toString(i)); hist.setAttribute("value", Integer.toString(hIST_histogram[i])); hIST_node.appendChild(hist); } root.appendChild(hIST_node); } // iCCP if (iCCP_present) { IIOMetadataNode iCCP_node = new IIOMetadataNode("iCCP"); iCCP_node.setAttribute("profileName", iCCP_profileName); iCCP_node.setAttribute("compressionMethod", iCCP_compressionMethodNames[iCCP_compressionMethod]); Object profile = iCCP_compressedProfile; if (profile != null) { profile = ((byte[])profile).clone(); } iCCP_node.setUserObject(profile); root.appendChild(iCCP_node); } // iTXt if (iTXt_keyword.size() > 0) { IIOMetadataNode iTXt_parent = new IIOMetadataNode("iTXt"); for (int i = 0; i < iTXt_keyword.size(); i++) { Integer val; IIOMetadataNode iTXt_node = new IIOMetadataNode("iTXtEntry"); iTXt_node.setAttribute("keyword", (String)iTXt_keyword.get(i)); val = (Integer)iTXt_compressionFlag.get(i); iTXt_node.setAttribute("compressionFlag", val.toString()); val = (Integer)iTXt_compressionMethod.get(i); iTXt_node.setAttribute("compressionMethod", val.toString()); iTXt_node.setAttribute("languageTag", (String)iTXt_languageTag.get(i)); iTXt_node.setAttribute("translatedKeyword", (String)iTXt_translatedKeyword.get(i)); iTXt_node.setAttribute("text", (String)iTXt_text.get(i)); iTXt_parent.appendChild(iTXt_node); } root.appendChild(iTXt_parent); } // pHYs if (pHYs_present) { IIOMetadataNode pHYs_node = new IIOMetadataNode("pHYs"); pHYs_node.setAttribute("pixelsPerUnitXAxis", Integer.toString(pHYs_pixelsPerUnitXAxis)); pHYs_node.setAttribute("pixelsPerUnitYAxis", Integer.toString(pHYs_pixelsPerUnitYAxis)); pHYs_node.setAttribute("unitSpecifier", unitSpecifierNames[pHYs_unitSpecifier]); root.appendChild(pHYs_node); } // sBIT if (sBIT_present) { IIOMetadataNode sBIT_node = new IIOMetadataNode("sBIT"); if (sBIT_colorType == PNG_COLOR_GRAY) { node = new IIOMetadataNode("sBIT_Grayscale"); node.setAttribute("gray", Integer.toString(sBIT_grayBits)); } else if (sBIT_colorType == PNG_COLOR_GRAY_ALPHA) { node = new IIOMetadataNode("sBIT_GrayAlpha"); node.setAttribute("gray", Integer.toString(sBIT_grayBits)); node.setAttribute("alpha", Integer.toString(sBIT_alphaBits)); } else if (sBIT_colorType == PNG_COLOR_RGB) { node = new IIOMetadataNode("sBIT_RGB"); node.setAttribute("red", Integer.toString(sBIT_redBits)); node.setAttribute("green", Integer.toString(sBIT_greenBits)); node.setAttribute("blue", Integer.toString(sBIT_blueBits)); } else if (sBIT_colorType == PNG_COLOR_RGB_ALPHA) { node = new IIOMetadataNode("sBIT_RGBAlpha"); node.setAttribute("red", Integer.toString(sBIT_redBits)); node.setAttribute("green", Integer.toString(sBIT_greenBits)); node.setAttribute("blue", Integer.toString(sBIT_blueBits)); node.setAttribute("alpha", Integer.toString(sBIT_alphaBits)); } else if (sBIT_colorType == PNG_COLOR_PALETTE) { node = new IIOMetadataNode("sBIT_Palette"); node.setAttribute("red", Integer.toString(sBIT_redBits)); node.setAttribute("green", Integer.toString(sBIT_greenBits)); node.setAttribute("blue", Integer.toString(sBIT_blueBits)); } sBIT_node.appendChild(node); root.appendChild(sBIT_node); } // sPLT if (sPLT_present) { IIOMetadataNode sPLT_node = new IIOMetadataNode("sPLT"); sPLT_node.setAttribute("name", sPLT_paletteName); sPLT_node.setAttribute("sampleDepth", Integer.toString(sPLT_sampleDepth)); int numEntries = sPLT_red.length; for (int i = 0; i < numEntries; i++) { IIOMetadataNode entry = new IIOMetadataNode("sPLTEntry"); entry.setAttribute("index", Integer.toString(i)); entry.setAttribute("red", Integer.toString(sPLT_red[i])); entry.setAttribute("green", Integer.toString(sPLT_green[i])); entry.setAttribute("blue", Integer.toString(sPLT_blue[i])); entry.setAttribute("alpha", Integer.toString(sPLT_alpha[i])); entry.setAttribute("frequency", Integer.toString(sPLT_frequency[i])); sPLT_node.appendChild(entry); } root.appendChild(sPLT_node); } // sRGB if (sRGB_present) { IIOMetadataNode sRGB_node = new IIOMetadataNode("sRGB"); sRGB_node.setAttribute("renderingIntent", renderingIntentNames[sRGB_renderingIntent]); root.appendChild(sRGB_node); } // tEXt if (tEXt_keyword.size() > 0) { IIOMetadataNode tEXt_parent = new IIOMetadataNode("tEXt"); for (int i = 0; i < tEXt_keyword.size(); i++) { IIOMetadataNode tEXt_node = new IIOMetadataNode("tEXtEntry"); tEXt_node.setAttribute("keyword" , (String)tEXt_keyword.get(i)); tEXt_node.setAttribute("value" , (String)tEXt_text.get(i)); tEXt_parent.appendChild(tEXt_node); } root.appendChild(tEXt_parent); } // tIME if (tIME_present) { IIOMetadataNode tIME_node = new IIOMetadataNode("tIME"); tIME_node.setAttribute("year", Integer.toString(tIME_year)); tIME_node.setAttribute("month", Integer.toString(tIME_month)); tIME_node.setAttribute("day", Integer.toString(tIME_day)); tIME_node.setAttribute("hour", Integer.toString(tIME_hour)); tIME_node.setAttribute("minute", Integer.toString(tIME_minute)); tIME_node.setAttribute("second", Integer.toString(tIME_second)); root.appendChild(tIME_node); } // tRNS if (tRNS_present) { IIOMetadataNode tRNS_node = new IIOMetadataNode("tRNS"); if (tRNS_colorType == PNG_COLOR_PALETTE) { node = new IIOMetadataNode("tRNS_Palette"); for (int i = 0; i < tRNS_alpha.length; i++) { IIOMetadataNode entry = new IIOMetadataNode("tRNS_PaletteEntry"); entry.setAttribute("index", Integer.toString(i)); entry.setAttribute("alpha", Integer.toString(tRNS_alpha[i] & 0xff)); node.appendChild(entry); } } else if (tRNS_colorType == PNG_COLOR_GRAY) { node = new IIOMetadataNode("tRNS_Grayscale"); node.setAttribute("gray", Integer.toString(tRNS_gray)); } else if (tRNS_colorType == PNG_COLOR_RGB) { node = new IIOMetadataNode("tRNS_RGB"); node.setAttribute("red", Integer.toString(tRNS_red)); node.setAttribute("green", Integer.toString(tRNS_green)); node.setAttribute("blue", Integer.toString(tRNS_blue)); } tRNS_node.appendChild(node); root.appendChild(tRNS_node); } // zTXt if (zTXt_keyword.size() > 0) { IIOMetadataNode zTXt_parent = new IIOMetadataNode("zTXt"); for (int i = 0; i < zTXt_keyword.size(); i++) { IIOMetadataNode zTXt_node = new IIOMetadataNode("zTXtEntry"); zTXt_node.setAttribute("keyword", (String)zTXt_keyword.get(i)); int cm = ((Integer)zTXt_compressionMethod.get(i)).intValue(); zTXt_node.setAttribute("compressionMethod", zTXt_compressionMethodNames[cm]); zTXt_node.setAttribute("text", (String)zTXt_text.get(i)); zTXt_parent.appendChild(zTXt_node); } root.appendChild(zTXt_parent); } // Unknown chunks if (unknownChunkType.size() > 0) { IIOMetadataNode unknown_parent = new IIOMetadataNode("UnknownChunks"); for (int i = 0; i < unknownChunkType.size(); i++) { IIOMetadataNode unknown_node = new IIOMetadataNode("UnknownChunk"); unknown_node.setAttribute("type", (String)unknownChunkType.get(i)); unknown_node.setUserObject((byte[])unknownChunkData.get(i)); unknown_parent.appendChild(unknown_node); } root.appendChild(unknown_parent); } return root; } private int getNumChannels() { // Determine number of channels // Be careful about palette color with transparency int numChannels = IHDR_numChannels[IHDR_colorType]; if (IHDR_colorType == PNG_COLOR_PALETTE && tRNS_present && tRNS_colorType == IHDR_colorType) { numChannels = 4; } return numChannels; } public IIOMetadataNode getStandardChromaNode() { IIOMetadataNode chroma_node = new IIOMetadataNode("Chroma"); IIOMetadataNode node = null; // scratch node node = new IIOMetadataNode("ColorSpaceType"); node.setAttribute("name", colorSpaceTypeNames[IHDR_colorType]); chroma_node.appendChild(node); node = new IIOMetadataNode("NumChannels"); node.setAttribute("value", Integer.toString(getNumChannels())); chroma_node.appendChild(node); if (gAMA_present) { node = new IIOMetadataNode("Gamma"); node.setAttribute("value", Float.toString(gAMA_gamma*1.0e-5F)); chroma_node.appendChild(node); } node = new IIOMetadataNode("BlackIsZero"); node.setAttribute("value", "TRUE"); chroma_node.appendChild(node); if (PLTE_present) { boolean hasAlpha = tRNS_present && (tRNS_colorType == PNG_COLOR_PALETTE); node = new IIOMetadataNode("Palette"); for (int i = 0; i < PLTE_red.length; i++) { IIOMetadataNode entry = new IIOMetadataNode("PaletteEntry"); entry.setAttribute("index", Integer.toString(i)); entry.setAttribute("red", Integer.toString(PLTE_red[i] & 0xff)); entry.setAttribute("green", Integer.toString(PLTE_green[i] & 0xff)); entry.setAttribute("blue", Integer.toString(PLTE_blue[i] & 0xff)); if (hasAlpha) { int alpha = (i < tRNS_alpha.length) ? (tRNS_alpha[i] & 0xff) : 255; entry.setAttribute("alpha", Integer.toString(alpha)); } node.appendChild(entry); } chroma_node.appendChild(node); } if (bKGD_present) { if (bKGD_colorType == PNG_COLOR_PALETTE) { node = new IIOMetadataNode("BackgroundIndex"); node.setAttribute("value", Integer.toString(bKGD_index)); } else { node = new IIOMetadataNode("BackgroundColor"); int r, g, b; if (bKGD_colorType == PNG_COLOR_GRAY) { r = g = b = bKGD_gray; } else { r = bKGD_red; g = bKGD_green; b = bKGD_blue; } node.setAttribute("red", Integer.toString(r)); node.setAttribute("green", Integer.toString(g)); node.setAttribute("blue", Integer.toString(b)); } chroma_node.appendChild(node); } return chroma_node; } public IIOMetadataNode getStandardCompressionNode() { IIOMetadataNode compression_node = new IIOMetadataNode("Compression"); IIOMetadataNode node = null; // scratch node node = new IIOMetadataNode("CompressionTypeName"); node.setAttribute("value", "deflate"); compression_node.appendChild(node); node = new IIOMetadataNode("Lossless"); node.setAttribute("value", "TRUE"); compression_node.appendChild(node); node = new IIOMetadataNode("NumProgressiveScans"); node.setAttribute("value", (IHDR_interlaceMethod == 0) ? "1" : "7"); compression_node.appendChild(node); return compression_node; } private String repeat(String s, int times) { if (times == 1) { return s; } StringBuffer sb = new StringBuffer((s.length() + 1)*times - 1); sb.append(s); for (int i = 1; i < times; i++) { sb.append(" "); sb.append(s); } return sb.toString(); } public IIOMetadataNode getStandardDataNode() { IIOMetadataNode data_node = new IIOMetadataNode("Data"); IIOMetadataNode node = null; // scratch node node = new IIOMetadataNode("PlanarConfiguration"); node.setAttribute("value", "PixelInterleaved"); data_node.appendChild(node); node = new IIOMetadataNode("SampleFormat"); node.setAttribute("value", IHDR_colorType == PNG_COLOR_PALETTE ? "Index" : "UnsignedIntegral"); data_node.appendChild(node); String bitDepth = Integer.toString(IHDR_bitDepth); node = new IIOMetadataNode("BitsPerSample"); node.setAttribute("value", repeat(bitDepth, getNumChannels())); data_node.appendChild(node); if (sBIT_present) { node = new IIOMetadataNode("SignificantBitsPerSample"); String sbits; if (sBIT_colorType == PNG_COLOR_GRAY || sBIT_colorType == PNG_COLOR_GRAY_ALPHA) { sbits = Integer.toString(sBIT_grayBits); } else { // sBIT_colorType == PNG_COLOR_RGB || // sBIT_colorType == PNG_COLOR_RGB_ALPHA sbits = Integer.toString(sBIT_redBits) + " " + Integer.toString(sBIT_greenBits) + " " + Integer.toString(sBIT_blueBits); } if (sBIT_colorType == PNG_COLOR_GRAY_ALPHA || sBIT_colorType == PNG_COLOR_RGB_ALPHA) { sbits += " " + Integer.toString(sBIT_alphaBits); } node.setAttribute("value", sbits); data_node.appendChild(node); } // SampleMSB return data_node; } public IIOMetadataNode getStandardDimensionNode() { IIOMetadataNode dimension_node = new IIOMetadataNode("Dimension"); IIOMetadataNode node = null; // scratch node node = new IIOMetadataNode("PixelAspectRatio"); // aspect ratio is pixel width/height which is the ratio of the // inverses of pixels per unit length. float ratio = pHYs_present ? (float)pHYs_pixelsPerUnitYAxis/pHYs_pixelsPerUnitXAxis : 1.0F; node.setAttribute("value", Float.toString(ratio)); dimension_node.appendChild(node); node = new IIOMetadataNode("ImageOrientation"); node.setAttribute("value", "Normal"); dimension_node.appendChild(node); if (pHYs_present && pHYs_unitSpecifier == PHYS_UNIT_METER) { node = new IIOMetadataNode("HorizontalPixelSize"); node.setAttribute("value", Float.toString(1000.0F/pHYs_pixelsPerUnitXAxis)); dimension_node.appendChild(node); node = new IIOMetadataNode("VerticalPixelSize"); node.setAttribute("value", Float.toString(1000.0F/pHYs_pixelsPerUnitYAxis)); dimension_node.appendChild(node); } return dimension_node; } public IIOMetadataNode getStandardDocumentNode() { if (!tIME_present) { return null; } IIOMetadataNode document_node = new IIOMetadataNode("Document"); IIOMetadataNode node = null; // scratch node node = new IIOMetadataNode("ImageModificationTime"); node.setAttribute("year", Integer.toString(tIME_year)); node.setAttribute("month", Integer.toString(tIME_month)); node.setAttribute("day", Integer.toString(tIME_day)); node.setAttribute("hour", Integer.toString(tIME_hour)); node.setAttribute("minute", Integer.toString(tIME_minute)); node.setAttribute("second", Integer.toString(tIME_second)); document_node.appendChild(node); return document_node; } public IIOMetadataNode getStandardTextNode() { int numEntries = tEXt_keyword.size() + iTXt_keyword.size() + zTXt_keyword.size(); if (numEntries == 0) { return null; } IIOMetadataNode text_node = new IIOMetadataNode("Text"); IIOMetadataNode node = null; // scratch node for (int i = 0; i < tEXt_keyword.size(); i++) { node = new IIOMetadataNode("TextEntry"); node.setAttribute("keyword", (String)tEXt_keyword.get(i)); node.setAttribute("value", (String)tEXt_text.get(i)); node.setAttribute("encoding", "ISO-8859-1"); node.setAttribute("compression", "none"); text_node.appendChild(node); } for (int i = 0; i < iTXt_keyword.size(); i++) { node = new IIOMetadataNode("TextEntry"); node.setAttribute("keyword", (String)iTXt_keyword.get(i)); node.setAttribute("value", (String)iTXt_text.get(i)); node.setAttribute("language", (String)iTXt_languageTag.get(i)); if (((Integer)iTXt_compressionFlag.get(i)).intValue() == 1) { node.setAttribute("compression", "deflate"); } else { node.setAttribute("compression", "none"); } text_node.appendChild(node); } for (int i = 0; i < zTXt_keyword.size(); i++) { node = new IIOMetadataNode("TextEntry"); node.setAttribute("keyword", (String)zTXt_keyword.get(i)); node.setAttribute("value", (String)zTXt_text.get(i)); node.setAttribute("compression", "deflate"); text_node.appendChild(node); } return text_node; } public IIOMetadataNode getStandardTransparencyNode() { IIOMetadataNode transparency_node = new IIOMetadataNode("Transparency"); IIOMetadataNode node = null; // scratch node node = new IIOMetadataNode("Alpha"); boolean hasAlpha = (IHDR_colorType == PNG_COLOR_RGB_ALPHA) || (IHDR_colorType == PNG_COLOR_GRAY_ALPHA) || (IHDR_colorType == PNG_COLOR_PALETTE && tRNS_present && (tRNS_colorType == IHDR_colorType) && (tRNS_alpha != null)); node.setAttribute("value", hasAlpha ? "nonpremultiplied" : "none"); transparency_node.appendChild(node); if (tRNS_present) { if(tRNS_colorType == PNG_COLOR_RGB || tRNS_colorType == PNG_COLOR_GRAY) { node = new IIOMetadataNode("TransparentColor"); if (tRNS_colorType == PNG_COLOR_RGB) { node.setAttribute("value", Integer.toString(tRNS_red) + " " + Integer.toString(tRNS_green) + " " + Integer.toString(tRNS_blue)); } else if (tRNS_colorType == PNG_COLOR_GRAY) { node.setAttribute("value", Integer.toString(tRNS_gray)); } transparency_node.appendChild(node); } } return transparency_node; } // Shorthand for throwing an IIOInvalidTreeException private void fatal(Node node, String reason) throws IIOInvalidTreeException { throw new IIOInvalidTreeException(reason, node); } // Get an integer-valued attribute private int getIntAttribute(Node node, String name, int defaultValue, boolean required) throws IIOInvalidTreeException { String value = getAttribute(node, name, null, required); if (value == null) { return defaultValue; } return Integer.parseInt(value); } // Get a float-valued attribute private float getFloatAttribute(Node node, String name, float defaultValue, boolean required) throws IIOInvalidTreeException { String value = getAttribute(node, name, null, required); if (value == null) { return defaultValue; } return Float.parseFloat(value); } // Get a required integer-valued attribute private int getIntAttribute(Node node, String name) throws IIOInvalidTreeException { return getIntAttribute(node, name, -1, true); } // Get a required float-valued attribute private float getFloatAttribute(Node node, String name) throws IIOInvalidTreeException { return getFloatAttribute(node, name, -1.0F, true); } // Get a boolean-valued attribute private boolean getBooleanAttribute(Node node, String name, boolean defaultValue, boolean required) throws IIOInvalidTreeException { Node attr = node.getAttributes().getNamedItem(name); if (attr == null) { if (!required) { return defaultValue; } else { fatal(node, "Required attribute " + name + " not present!"); } } String value = attr.getNodeValue(); if (value.equalsIgnoreCase("true")) { return true; } else if (value.equalsIgnoreCase("false")) { return false; } else { fatal(node, "Attribute " + name + " must be 'true' or 'false'!"); return false; } } // Get a required boolean-valued attribute private boolean getBooleanAttribute(Node node, String name) throws IIOInvalidTreeException { return getBooleanAttribute(node, name, false, true); } // Get an enumerated attribute as an index into a String array private int getEnumeratedAttribute(Node node, String name, String[] legalNames, int defaultValue, boolean required) throws IIOInvalidTreeException { Node attr = node.getAttributes().getNamedItem(name); if (attr == null) { if (!required) { return defaultValue; } else { fatal(node, "Required attribute " + name + " not present!"); } } String value = attr.getNodeValue(); for (int i = 0; i < legalNames.length; i++) { if (value.equals(legalNames[i])) { return i; } } fatal(node, "Illegal value for attribute " + name + "!"); return -1; } // Get a required enumerated attribute as an index into a String array private int getEnumeratedAttribute(Node node, String name, String[] legalNames) throws IIOInvalidTreeException { return getEnumeratedAttribute(node, name, legalNames, -1, true); } // Get a String-valued attribute private String getAttribute(Node node, String name, String defaultValue, boolean required) throws IIOInvalidTreeException { Node attr = node.getAttributes().getNamedItem(name); if (attr == null) { if (!required) { return defaultValue; } else { fatal(node, "Required attribute " + name + " not present!"); } } return attr.getNodeValue(); } // Get a required String-valued attribute private String getAttribute(Node node, String name) throws IIOInvalidTreeException { return getAttribute(node, name, null, true); } public void mergeTree(String formatName, Node root) throws IIOInvalidTreeException { if (formatName.equals(nativeMetadataFormatName)) { if (root == null) { throw new IllegalArgumentException("root == null!"); } mergeNativeTree(root); } else if (formatName.equals (IIOMetadataFormatImpl.standardMetadataFormatName)) { if (root == null) { throw new IllegalArgumentException("root == null!"); } mergeStandardTree(root); } else { throw new IllegalArgumentException("Not a recognized format!"); } } private void mergeNativeTree(Node root) throws IIOInvalidTreeException { Node node = root; if (!node.getNodeName().equals(nativeMetadataFormatName)) { fatal(node, "Root must be " + nativeMetadataFormatName); } node = node.getFirstChild(); while (node != null) { String name = node.getNodeName(); if (name.equals("IHDR")) { IHDR_width = getIntAttribute(node, "width"); IHDR_height = getIntAttribute(node, "height"); IHDR_bitDepth = getEnumeratedAttribute(node, "bitDepth", IHDR_bitDepths); IHDR_colorType = getEnumeratedAttribute(node, "colorType", IHDR_colorTypeNames); IHDR_compressionMethod = getEnumeratedAttribute(node, "compressionMethod", IHDR_compressionMethodNames); IHDR_filterMethod = getEnumeratedAttribute(node, "filterMethod", IHDR_filterMethodNames); IHDR_interlaceMethod = getEnumeratedAttribute(node, "interlaceMethod", IHDR_interlaceMethodNames); IHDR_present = true; } else if (name.equals("PLTE")) { byte[] red = new byte[256]; byte[] green = new byte[256]; byte[] blue = new byte[256]; int maxindex = -1; Node PLTE_entry = node.getFirstChild(); if (PLTE_entry == null) { fatal(node, "Palette has no entries!"); } while (PLTE_entry != null) { if (!PLTE_entry.getNodeName().equals("PLTEEntry")) { fatal(node, "Only a PLTEEntry may be a child of a PLTE!"); } int index = getIntAttribute(PLTE_entry, "index"); if (index < 0 || index > 255) { fatal(node, "Bad value for PLTEEntry attribute index!"); } if (index > maxindex) { maxindex = index; } red[index] = (byte)getIntAttribute(PLTE_entry, "red"); green[index] = (byte)getIntAttribute(PLTE_entry, "green"); blue[index] = (byte)getIntAttribute(PLTE_entry, "blue"); PLTE_entry = PLTE_entry.getNextSibling(); } int numEntries = maxindex + 1; PLTE_red = new byte[numEntries]; PLTE_green = new byte[numEntries]; PLTE_blue = new byte[numEntries]; System.arraycopy(red, 0, PLTE_red, 0, numEntries); System.arraycopy(green, 0, PLTE_green, 0, numEntries); System.arraycopy(blue, 0, PLTE_blue, 0, numEntries); PLTE_present = true; } else if (name.equals("bKGD")) { bKGD_present = false; // Guard against partial overwrite Node bKGD_node = node.getFirstChild(); if (bKGD_node == null) { fatal(node, "bKGD node has no children!"); } String bKGD_name = bKGD_node.getNodeName(); if (bKGD_name.equals("bKGD_Palette")) { bKGD_index = getIntAttribute(bKGD_node, "index"); bKGD_colorType = PNG_COLOR_PALETTE; } else if (bKGD_name.equals("bKGD_Grayscale")) { bKGD_gray = getIntAttribute(bKGD_node, "gray"); bKGD_colorType = PNG_COLOR_GRAY; } else if (bKGD_name.equals("bKGD_RGB")) { bKGD_red = getIntAttribute(bKGD_node, "red"); bKGD_green = getIntAttribute(bKGD_node, "green"); bKGD_blue = getIntAttribute(bKGD_node, "blue"); bKGD_colorType = PNG_COLOR_RGB; } else { fatal(node, "Bad child of a bKGD node!"); } if (bKGD_node.getNextSibling() != null) { fatal(node, "bKGD node has more than one child!"); } bKGD_present = true; } else if (name.equals("cHRM")) { cHRM_whitePointX = getIntAttribute(node, "whitePointX"); cHRM_whitePointY = getIntAttribute(node, "whitePointY"); cHRM_redX = getIntAttribute(node, "redX"); cHRM_redY = getIntAttribute(node, "redY"); cHRM_greenX = getIntAttribute(node, "greenX"); cHRM_greenY = getIntAttribute(node, "greenY"); cHRM_blueX = getIntAttribute(node, "blueX"); cHRM_blueY = getIntAttribute(node, "blueY"); cHRM_present = true; } else if (name.equals("gAMA")) { gAMA_gamma = getIntAttribute(node, "value"); gAMA_present = true; } else if (name.equals("hIST")) { char[] hist = new char[256]; int maxindex = -1; Node hIST_entry = node.getFirstChild(); if (hIST_entry == null) { fatal(node, "hIST node has no children!"); } while (hIST_entry != null) { if (!hIST_entry.getNodeName().equals("hISTEntry")) { fatal(node, "Only a hISTEntry may be a child of a hIST!"); } int index = getIntAttribute(hIST_entry, "index"); if (index < 0 || index > 255) { fatal(node, "Bad value for histEntry attribute index!"); } if (index > maxindex) { maxindex = index; } hist[index] = (char)getIntAttribute(hIST_entry, "value"); hIST_entry = hIST_entry.getNextSibling(); } int numEntries = maxindex + 1; hIST_histogram = new char[numEntries]; System.arraycopy(hist, 0, hIST_histogram, 0, numEntries); hIST_present = true; } else if (name.equals("iCCP")) { iCCP_profileName = toPrintableLatin1(getAttribute(node, "profileName")); iCCP_compressionMethod = getEnumeratedAttribute(node, "compressionMethod", iCCP_compressionMethodNames); Object compressedProfile = ((IIOMetadataNode)node).getUserObject(); if (compressedProfile == null) { fatal(node, "No ICCP profile present in user object!"); } if (!(compressedProfile instanceof byte[])) { fatal(node, "User object not a byte array!"); } iCCP_compressedProfile = (byte[])((byte[])compressedProfile).clone(); iCCP_present = true; } else if (name.equals("iTXt")) { Node iTXt_node = node.getFirstChild(); while (iTXt_node != null) { if (!iTXt_node.getNodeName().equals("iTXtEntry")) { fatal(node, "Only an iTXtEntry may be a child of an iTXt!"); } String keyword = toPrintableLatin1(getAttribute(iTXt_node, "keyword")); iTXt_keyword.add(keyword); boolean compressionFlag = getBooleanAttribute(iTXt_node, "compressionFlag"); iTXt_compressionFlag.add(new Boolean(compressionFlag)); String compressionMethod = getAttribute(iTXt_node, "compressionMethod"); iTXt_compressionMethod.add(compressionMethod); String languageTag = getAttribute(iTXt_node, "languageTag"); iTXt_languageTag.add(languageTag); String translatedKeyword = getAttribute(iTXt_node, "translatedKeyword"); iTXt_translatedKeyword.add(translatedKeyword); String text = getAttribute(iTXt_node, "text"); iTXt_text.add(text); iTXt_node = iTXt_node.getNextSibling(); } } else if (name.equals("pHYs")) { pHYs_pixelsPerUnitXAxis = getIntAttribute(node, "pixelsPerUnitXAxis"); pHYs_pixelsPerUnitYAxis = getIntAttribute(node, "pixelsPerUnitYAxis"); pHYs_unitSpecifier = getEnumeratedAttribute(node, "unitSpecifier", unitSpecifierNames); pHYs_present = true; } else if (name.equals("sBIT")) { sBIT_present = false; // Guard against partial overwrite Node sBIT_node = node.getFirstChild(); if (sBIT_node == null) { fatal(node, "sBIT node has no children!"); } String sBIT_name = sBIT_node.getNodeName(); if (sBIT_name.equals("sBIT_Grayscale")) { sBIT_grayBits = getIntAttribute(sBIT_node, "gray"); sBIT_colorType = PNG_COLOR_GRAY; } else if (sBIT_name.equals("sBIT_GrayAlpha")) { sBIT_grayBits = getIntAttribute(sBIT_node, "gray"); sBIT_alphaBits = getIntAttribute(sBIT_node, "alpha"); sBIT_colorType = PNG_COLOR_GRAY_ALPHA; } else if (sBIT_name.equals("sBIT_RGB")) { sBIT_redBits = getIntAttribute(sBIT_node, "red"); sBIT_greenBits = getIntAttribute(sBIT_node, "green"); sBIT_blueBits = getIntAttribute(sBIT_node, "blue"); sBIT_colorType = PNG_COLOR_RGB; } else if (sBIT_name.equals("sBIT_RGBAlpha")) { sBIT_redBits = getIntAttribute(sBIT_node, "red"); sBIT_greenBits = getIntAttribute(sBIT_node, "green"); sBIT_blueBits = getIntAttribute(sBIT_node, "blue"); sBIT_alphaBits = getIntAttribute(sBIT_node, "alpha"); sBIT_colorType = PNG_COLOR_RGB_ALPHA; } else if (sBIT_name.equals("sBIT_Palette")) { sBIT_redBits = getIntAttribute(sBIT_node, "red"); sBIT_greenBits = getIntAttribute(sBIT_node, "green"); sBIT_blueBits = getIntAttribute(sBIT_node, "blue"); sBIT_colorType = PNG_COLOR_PALETTE; } else { fatal(node, "Bad child of an sBIT node!"); } if (sBIT_node.getNextSibling() != null) { fatal(node, "sBIT node has more than one child!"); } sBIT_present = true; } else if (name.equals("sPLT")) { sPLT_paletteName = toPrintableLatin1(getAttribute(node, "name")); sPLT_sampleDepth = getIntAttribute(node, "sampleDepth"); int[] red = new int[256]; int[] green = new int[256]; int[] blue = new int[256]; int[] alpha = new int[256]; int[] frequency = new int[256]; int maxindex = -1; Node sPLT_entry = node.getFirstChild(); if (sPLT_entry == null) { fatal(node, "sPLT node has no children!"); } while (sPLT_entry != null) { if (!sPLT_entry.getNodeName().equals("sPLTEntry")) { fatal(node, "Only an sPLTEntry may be a child of an sPLT!"); } int index = getIntAttribute(sPLT_entry, "index"); if (index < 0 || index > 255) { fatal(node, "Bad value for PLTEEntry attribute index!"); } if (index > maxindex) { maxindex = index; } red[index] = getIntAttribute(sPLT_entry, "red"); green[index] = getIntAttribute(sPLT_entry, "green"); blue[index] = getIntAttribute(sPLT_entry, "blue"); alpha[index] = getIntAttribute(sPLT_entry, "alpha"); frequency[index] = getIntAttribute(sPLT_entry, "frequency"); sPLT_entry = sPLT_entry.getNextSibling(); } int numEntries = maxindex + 1; sPLT_red = new int[numEntries]; sPLT_green = new int[numEntries]; sPLT_blue = new int[numEntries]; sPLT_alpha = new int[numEntries]; sPLT_frequency = new int[numEntries]; System.arraycopy(red, 0, sPLT_red, 0, numEntries); System.arraycopy(green, 0, sPLT_green, 0, numEntries); System.arraycopy(blue, 0, sPLT_blue, 0, numEntries); System.arraycopy(alpha, 0, sPLT_alpha, 0, numEntries); System.arraycopy(frequency, 0, sPLT_frequency, 0, numEntries); sPLT_present = true; } else if (name.equals("sRGB")) { sRGB_renderingIntent = getEnumeratedAttribute(node, "renderingIntent", renderingIntentNames); sRGB_present = true; } else if (name.equals("tEXt")) { Node tEXt_node = node.getFirstChild(); while (tEXt_node != null) { if (!tEXt_node.getNodeName().equals("tEXtEntry")) { fatal(node, "Only an tEXtEntry may be a child of an tEXt!"); } String keyword = toPrintableLatin1(getAttribute(tEXt_node, "keyword")); tEXt_keyword.add(keyword); String text = getAttribute(tEXt_node, "value"); tEXt_text.add(text); tEXt_node = tEXt_node.getNextSibling(); } } else if (name.equals("tIME")) { tIME_year = getIntAttribute(node, "year"); tIME_month = getIntAttribute(node, "month"); tIME_day = getIntAttribute(node, "day"); tIME_hour = getIntAttribute(node, "hour"); tIME_minute = getIntAttribute(node, "minute"); tIME_second = getIntAttribute(node, "second"); tIME_present = true; } else if (name.equals("tRNS")) { tRNS_present = false; // Guard against partial overwrite Node tRNS_node = node.getFirstChild(); if (tRNS_node == null) { fatal(node, "tRNS node has no children!"); } String tRNS_name = tRNS_node.getNodeName(); if (tRNS_name.equals("tRNS_Palette")) { byte[] alpha = new byte[256]; int maxindex = -1; Node tRNS_paletteEntry = tRNS_node.getFirstChild(); if (tRNS_paletteEntry == null) { fatal(node, "tRNS_Palette node has no children!"); } while (tRNS_paletteEntry != null) { if (!tRNS_paletteEntry.getNodeName().equals( "tRNS_PaletteEntry")) { fatal(node, "Only a tRNS_PaletteEntry may be a child of a tRNS_Palette!"); } int index = getIntAttribute(tRNS_paletteEntry, "index"); if (index < 0 || index > 255) { fatal(node, "Bad value for tRNS_PaletteEntry attribute index!"); } if (index > maxindex) { maxindex = index; } alpha[index] = (byte)getIntAttribute(tRNS_paletteEntry, "alpha"); tRNS_paletteEntry = tRNS_paletteEntry.getNextSibling(); } int numEntries = maxindex + 1; tRNS_alpha = new byte[numEntries]; tRNS_colorType = PNG_COLOR_PALETTE; System.arraycopy(alpha, 0, tRNS_alpha, 0, numEntries); } else if (tRNS_name.equals("tRNS_Grayscale")) { tRNS_gray = getIntAttribute(tRNS_node, "gray"); tRNS_colorType = PNG_COLOR_GRAY; } else if (tRNS_name.equals("tRNS_RGB")) { tRNS_red = getIntAttribute(tRNS_node, "red"); tRNS_green = getIntAttribute(tRNS_node, "green"); tRNS_blue = getIntAttribute(tRNS_node, "blue"); tRNS_colorType = PNG_COLOR_RGB; } else { fatal(node, "Bad child of a tRNS node!"); } if (tRNS_node.getNextSibling() != null) { fatal(node, "tRNS node has more than one child!"); } tRNS_present = true; } else if (name.equals("zTXt")) { Node zTXt_node = node.getFirstChild(); while (zTXt_node != null) { if (!zTXt_node.getNodeName().equals("zTXtEntry")) { fatal(node, "Only an zTXtEntry may be a child of an zTXt!"); } String keyword = toPrintableLatin1(getAttribute(zTXt_node, "keyword")); zTXt_keyword.add(keyword); int compressionMethod = getEnumeratedAttribute(zTXt_node, "compressionMethod", zTXt_compressionMethodNames); zTXt_compressionMethod.add(new Integer(compressionMethod)); String text = getAttribute(zTXt_node, "text"); zTXt_text.add(text); zTXt_node = zTXt_node.getNextSibling(); } } else if (name.equals("UnknownChunks")) { Node unknown_node = node.getFirstChild(); while (unknown_node != null) { if (!unknown_node.getNodeName().equals("UnknownChunk")) { fatal(node, "Only an UnknownChunk may be a child of an UnknownChunks!"); } String chunkType = getAttribute(unknown_node, "type"); Object chunkData = ((IIOMetadataNode)unknown_node).getUserObject(); if (chunkType.length() != 4) { fatal(unknown_node, "Chunk type must be 4 characters!"); } if (chunkData == null) { fatal(unknown_node, "No chunk data present in user object!"); } if (!(chunkData instanceof byte[])) { fatal(unknown_node, "User object not a byte array!"); } unknownChunkType.add(chunkType); unknownChunkData.add(((byte[])chunkData).clone()); unknown_node = unknown_node.getNextSibling(); } } else { fatal(node, "Unknown child of root node!"); } node = node.getNextSibling(); } } private boolean isISOLatin(String s) { int len = s.length(); for (int i = 0; i < len; i++) { if (s.charAt(i) > 255) { return false; } } return true; } private void mergeStandardTree(Node root) throws IIOInvalidTreeException { Node node = root; if (!node.getNodeName() .equals(IIOMetadataFormatImpl.standardMetadataFormatName)) { fatal(node, "Root must be " + IIOMetadataFormatImpl.standardMetadataFormatName); } node = node.getFirstChild(); while(node != null) { String name = node.getNodeName(); if (name.equals("Chroma")) { Node child = node.getFirstChild(); while (child != null) { String childName = child.getNodeName(); if (childName.equals("Gamma")) { float gamma = getFloatAttribute(child, "value"); gAMA_present = true; gAMA_gamma = (int)(gamma*100000 + 0.5); } else if (childName.equals("Palette")) { byte[] red = new byte[256]; byte[] green = new byte[256]; byte[] blue = new byte[256]; int maxindex = -1; Node entry = child.getFirstChild(); while (entry != null) { String entryName = entry.getNodeName(); if(entryName.equals("PaletteEntry")) { int index = getIntAttribute(entry, "index"); if (index >= 0 && index <= 255) { red[index] = (byte)getIntAttribute(entry, "red"); green[index] = (byte)getIntAttribute(entry, "green"); blue[index] = (byte)getIntAttribute(entry, "blue"); if (index > maxindex) { maxindex = index; } } } entry = entry.getNextSibling(); } int numEntries = maxindex + 1; PLTE_red = new byte[numEntries]; PLTE_green = new byte[numEntries]; PLTE_blue = new byte[numEntries]; System.arraycopy(red, 0, PLTE_red, 0, numEntries); System.arraycopy(green, 0, PLTE_green, 0, numEntries); System.arraycopy(blue, 0, PLTE_blue, 0, numEntries); PLTE_present = true; } else if (childName.equals("BackgroundIndex")) { bKGD_present = true; bKGD_colorType = PNG_COLOR_PALETTE; bKGD_index = getIntAttribute(child, "value"); } else if (childName.equals("BackgroundColor")) { int red = getIntAttribute(child, "red"); int green = getIntAttribute(child, "green"); int blue = getIntAttribute(child, "blue"); if (red == green && red == blue) { bKGD_colorType = PNG_COLOR_GRAY; bKGD_gray = red; } else { bKGD_colorType = PNG_COLOR_RGB; bKGD_red = red; bKGD_green = green; bKGD_blue = blue; } bKGD_present = true; } // } else if (childName.equals("ColorSpaceType")) { // } else if (childName.equals("NumChannels")) { child = child.getNextSibling(); } } else if (name.equals("Compression")) { Node child = node.getFirstChild(); while (child != null) { String childName = child.getNodeName(); if (childName.equals("NumProgressiveScans")) { // Use Adam7 if NumProgressiveScans > 1 int scans = getIntAttribute(child, "value"); IHDR_interlaceMethod = (scans > 1) ? 1 : 0; // } else if (childName.equals("CompressionTypeName")) { // } else if (childName.equals("Lossless")) { // } else if (childName.equals("BitRate")) { } child = child.getNextSibling(); } } else if (name.equals("Data")) { Node child = node.getFirstChild(); while (child != null) { String childName = child.getNodeName(); if (childName.equals("BitsPerSample")) { String s = getAttribute(child, "value"); StringTokenizer t = new StringTokenizer(s); int maxBits = -1; while (t.hasMoreTokens()) { int bits = Integer.parseInt(t.nextToken()); if (bits > maxBits) { maxBits = bits; } } if (maxBits < 1) { maxBits = 1; } else if (maxBits == 3) { maxBits = 4; } else if (maxBits > 4 && maxBits < 8) { maxBits = 8; } else if (maxBits > 8) { maxBits = 16; } IHDR_bitDepth = maxBits; } else if (childName.equals("SignificantBitsPerSample")) { String s = getAttribute(child, "value"); StringTokenizer t = new StringTokenizer(s); int numTokens = t.countTokens(); if (numTokens == 1) { sBIT_colorType = PNG_COLOR_GRAY; sBIT_grayBits = Integer.parseInt(t.nextToken()); } else if (numTokens == 2) { sBIT_colorType = PNG_COLOR_GRAY_ALPHA; sBIT_grayBits = Integer.parseInt(t.nextToken()); sBIT_alphaBits = Integer.parseInt(t.nextToken()); } else if (numTokens == 3) { sBIT_colorType = PNG_COLOR_RGB; sBIT_redBits = Integer.parseInt(t.nextToken()); sBIT_greenBits = Integer.parseInt(t.nextToken()); sBIT_blueBits = Integer.parseInt(t.nextToken()); } else if (numTokens == 4) { sBIT_colorType = PNG_COLOR_RGB_ALPHA; sBIT_redBits = Integer.parseInt(t.nextToken()); sBIT_greenBits = Integer.parseInt(t.nextToken()); sBIT_blueBits = Integer.parseInt(t.nextToken()); sBIT_alphaBits = Integer.parseInt(t.nextToken()); } if (numTokens >= 1 && numTokens <= 4) { sBIT_present = true; } // } else if (childName.equals("PlanarConfiguration")) { // } else if (childName.equals("SampleFormat")) { // } else if (childName.equals("SampleMSB")) { } child = child.getNextSibling(); } } else if (name.equals("Dimension")) { boolean gotWidth = false; boolean gotHeight = false; boolean gotAspectRatio = false; float width = -1.0F; float height = -1.0F; float aspectRatio = -1.0F; Node child = node.getFirstChild(); while (child != null) { String childName = child.getNodeName(); if (childName.equals("PixelAspectRatio")) { aspectRatio = getFloatAttribute(child, "value"); gotAspectRatio = true; } else if (childName.equals("HorizontalPixelSize")) { width = getFloatAttribute(child, "value"); gotWidth = true; } else if (childName.equals("VerticalPixelSize")) { height = getFloatAttribute(child, "value"); gotHeight = true; // } else if (childName.equals("ImageOrientation")) { // } else if // (childName.equals("HorizontalPhysicalPixelSpacing")) { // } else if // (childName.equals("VerticalPhysicalPixelSpacing")) { // } else if (childName.equals("HorizontalPosition")) { // } else if (childName.equals("VerticalPosition")) { // } else if (childName.equals("HorizontalPixelOffset")) { // } else if (childName.equals("VerticalPixelOffset")) { } child = child.getNextSibling(); } if (gotWidth && gotHeight) { pHYs_present = true; pHYs_unitSpecifier = 1; pHYs_pixelsPerUnitXAxis = (int)(1000.0F/width + 0.5F); pHYs_pixelsPerUnitYAxis = (int)(1000.0F/height + 0.5F); } else if (gotAspectRatio) { pHYs_present = true; pHYs_unitSpecifier = 0; // Find a reasonable rational approximation int denom = 1; for (; denom < 100; denom++) { int num = (int)(aspectRatio*denom); if (Math.abs(num/denom - aspectRatio) < 0.001) { break; } } pHYs_pixelsPerUnitXAxis = (int)(aspectRatio*denom); pHYs_pixelsPerUnitYAxis = denom; } } else if (name.equals("Document")) { Node child = node.getFirstChild(); while (child != null) { String childName = child.getNodeName(); if (childName.equals("ImageModificationTime")) { tIME_present = true; tIME_year = getIntAttribute(child, "year"); tIME_month = getIntAttribute(child, "month"); tIME_day = getIntAttribute(child, "day"); tIME_hour = getIntAttribute(child, "hour", 0, false); tIME_minute = getIntAttribute(child, "minute", 0, false); tIME_second = getIntAttribute(child, "second", 0, false); // } else if (childName.equals("SubimageInterpretation")) { // } else if (childName.equals("ImageCreationTime")) { } child = child.getNextSibling(); } } else if (name.equals("Text")) { Node child = node.getFirstChild(); while (child != null) { String childName = child.getNodeName(); if (childName.equals("TextEntry")) { String keyword = getAttribute(child, "keyword", "text", false); String value = getAttribute(child, "value"); String encoding = getAttribute(child, "encoding", "unknown", false); String language = getAttribute(child, "language", "unknown", false); String compression = getAttribute(child, "compression", "other", false); if (isISOLatin(value)) { if (compression.equals("zip")) { // Use a zTXt node zTXt_keyword.add(toPrintableLatin1(keyword)); zTXt_text.add(value); zTXt_compressionMethod.add(new Integer(0)); } else { // Use a tEXt node tEXt_keyword.add(toPrintableLatin1(keyword)); tEXt_text.add(value); } } else { int flag = compression.equals("zip") ? 1 : 0; // Use an iTXt node iTXt_keyword.add(toPrintableLatin1(keyword)); iTXt_compressionFlag.add(new Integer(flag)); iTXt_compressionMethod.add(new Integer(0)); iTXt_languageTag.add(language); iTXt_translatedKeyword.add(keyword); // fake it iTXt_text.add(value); } } child = child.getNextSibling(); } // } else if (name.equals("Transparency")) { // Node child = node.getFirstChild(); // while (child != null) { // String childName = child.getNodeName(); // if (childName.equals("Alpha")) { // } else if (childName.equals("TransparentIndex")) { // } else if (childName.equals("TransparentColor")) { // } else if (childName.equals("TileTransparencies")) { // } else if (childName.equals("TileOpacities")) { // } // child = child.getNextSibling(); // } // } else { // // fatal(node, "Unknown child of root node!"); } node = node.getNextSibling(); } } // Reset all instance variables to their initial state public void reset() { IHDR_present = false; PLTE_present = false; bKGD_present = false; cHRM_present = false; gAMA_present = false; hIST_present = false; iCCP_present = false; iTXt_keyword = new ArrayList(); iTXt_compressionFlag = new ArrayList(); iTXt_compressionMethod = new ArrayList(); iTXt_languageTag = new ArrayList(); iTXt_translatedKeyword = new ArrayList(); iTXt_text = new ArrayList(); pHYs_present = false; sBIT_present = false; sPLT_present = false; sRGB_present = false; tEXt_keyword = new ArrayList(); tEXt_text = new ArrayList(); tIME_present = false; tRNS_present = false; zTXt_keyword = new ArrayList(); zTXt_compressionMethod = new ArrayList(); zTXt_text = new ArrayList(); unknownChunkType = new ArrayList(); unknownChunkData = new ArrayList(); } // BEGIN metadata reading section. private boolean gotHeader = false; private boolean gotMetadata = false; private Decoder decoder = null; private CLibPNGImageReader reader = null; private static int chunkType(String typeString) { char c0 = typeString.charAt(0); char c1 = typeString.charAt(1); char c2 = typeString.charAt(2); char c3 = typeString.charAt(3); int type = (c0 << 24) | (c1 << 16) | (c2 << 8) | c3; return type; } private String readNullTerminatedString(ImageInputStream stream) throws IOException { StringBuffer b = new StringBuffer(); int c; while ((c = stream.read()) != 0) { b.append((char)c); } return b.toString(); } private void readHeader() throws IIOException { if (gotHeader) { return; } try { mediaLibImage mlibImage = decoder.getImage(); int width = mlibImage.getWidth(); int height = mlibImage.getHeight(); int bitDepth = decoder.getBitDepth(); int colorType; switch(mlibImage.getChannels()) { case 1: colorType = decoder.getPalette() == null? PNG_COLOR_GRAY : PNG_COLOR_PALETTE; break; case 2: colorType = PNG_COLOR_GRAY_ALPHA; break; case 3: colorType = PNG_COLOR_RGB; break; case 4: colorType = PNG_COLOR_RGB_ALPHA; break; default: throw new IIOException("Unsupported image type."); } // Compression method 0 (deflate/inflate) is only supported type. int compressionMethod = 0; // Filter method 0 (adaptive filtering) is only supported type. int filterMethod = 0; int interlaceMethod = decoder.getInterlaceMethod(); if (width == 0) { throw new IIOException("Image width == 0!"); } if (height == 0) { throw new IIOException("Image height == 0!"); } if (bitDepth != 1 && bitDepth != 2 && bitDepth != 4 && bitDepth != 8 && bitDepth != 16) { throw new IIOException("Bit depth must be 1, 2, 4, 8, or 16!"); } if (colorType != 0 && colorType != 2 && colorType != 3 && colorType != 4 && colorType != 6) { throw new IIOException("Color type must be 0, 2, 3, 4, or 6!"); } if (colorType == PNG_COLOR_PALETTE && bitDepth == 16) { throw new IIOException("Bad color type/bit depth combination!"); } if ((colorType == PNG_COLOR_RGB || colorType == PNG_COLOR_RGB_ALPHA || colorType == PNG_COLOR_GRAY_ALPHA) && (bitDepth != 8 && bitDepth != 16)) { throw new IIOException("Bad color type/bit depth combination!"); } if (compressionMethod != 0) { throw new IIOException("Unknown compression method (not 0)!"); } if (filterMethod != 0) { throw new IIOException("Unknown filter method (not 0)!"); } if (interlaceMethod != 0 && interlaceMethod != 1) { throw new IIOException("Unknown interlace method (not 0 or 1)!"); } IHDR_present = true; IHDR_width = width; IHDR_height = height; IHDR_bitDepth = bitDepth; IHDR_colorType = colorType; IHDR_compressionMethod = compressionMethod; IHDR_filterMethod = filterMethod; IHDR_interlaceMethod = interlaceMethod; gotHeader = true; } catch (IOException e) { throw new IIOException("I/O error reading PNG header!", e); } } private void parse_PLTE_chunk() throws IOException { if (PLTE_present) { processWarningOccurred( "A PNG image may not contain more than one PLTE chunk.\n" + "The chunk will be ignored."); return; } else if (IHDR_colorType == PNG_COLOR_GRAY || IHDR_colorType == PNG_COLOR_GRAY_ALPHA) { processWarningOccurred( "A PNG gray or gray alpha image cannot have a PLTE chunk.\n" + "The chunk will be ignored."); return; } byte[] palette = decoder.getPalette(); if(palette != null) { int numEntries = palette.length/3; if (IHDR_colorType == PNG_COLOR_PALETTE) { int maxEntries = 1 << IHDR_bitDepth; if (numEntries > maxEntries) { processWarningOccurred( "PLTE chunk contains too many entries for bit depth, ignoring extras."); numEntries = maxEntries; } } // Round array sizes up to 2^2^n int paletteEntries; if (numEntries > 16) { paletteEntries = 256; } else if (numEntries > 4) { paletteEntries = 16; } else if (numEntries > 2) { paletteEntries = 4; } else { paletteEntries = 2; } PLTE_present = true; PLTE_red = new byte[paletteEntries]; PLTE_green = new byte[paletteEntries]; PLTE_blue = new byte[paletteEntries]; int index = 0; for (int i = 0; i < numEntries; i++) { PLTE_red[i] = palette[index++]; PLTE_green[i] = palette[index++]; PLTE_blue[i] = palette[index++]; } } } private void parse_bKGD_chunk() throws IOException { int[] background = decoder.getBackground(); if(background != null) { if (IHDR_colorType == PNG_COLOR_PALETTE) { bKGD_colorType = PNG_COLOR_PALETTE; bKGD_index = background[0]; } else if (IHDR_colorType == PNG_COLOR_GRAY || IHDR_colorType == PNG_COLOR_GRAY_ALPHA) { bKGD_colorType = PNG_COLOR_GRAY; bKGD_gray = background[0]; } else { // RGB or RGB_ALPHA bKGD_colorType = PNG_COLOR_RGB; bKGD_red = background[0]; bKGD_green = background[1]; bKGD_blue = background[2]; } bKGD_present = true; } } private void parse_cHRM_chunk() throws IOException { int[] chrm = decoder.getAllPrimaryChromaticities(); if(chrm != null) { int i = 0; cHRM_whitePointX = chrm[i++]; cHRM_whitePointY = chrm[i++]; cHRM_redX = chrm[i++]; cHRM_redY = chrm[i++]; cHRM_greenX = chrm[i++]; cHRM_greenY = chrm[i++]; cHRM_blueX = chrm[i++]; cHRM_blueY = chrm[i++]; cHRM_present = true; } } private void parse_gAMA_chunk() throws IOException { int gamma = decoder.getImageGamma(); if(gamma != decoder.PNG_gAMA_DEFAULT) { gAMA_gamma = gamma; gAMA_present = true; } } private void parse_hIST_chunk() throws IOException, IIOException { short[] histogram = decoder.getHistogram(); if(histogram != null) { if (!PLTE_present) { throw new IIOException("hIST chunk without prior PLTE chunk!"); } int length = Math.min(PLTE_red.length, histogram.length); hIST_histogram = new char[length]; for(int i = 0; i < length; i++) { hIST_histogram[i] = (char)histogram[i]; } hIST_present = true; } } private void parse_iCCP_chunk() throws IOException { String profileName = decoder.getEmbeddedICCProfileName(); if(profileName != null) { iCCP_profileName = profileName; byte[] uncompressedProfile = decoder.getEmbeddedICCProfile(); // Need to compress this profile to match metadata specification. Deflater compressor = new Deflater(Deflater.BEST_COMPRESSION); compressor.setInput(uncompressedProfile); compressor.finish(); int off = 0; int len = uncompressedProfile.length; byte[] compressedProfile = new byte[uncompressedProfile.length]; do { int count = compressor.deflate(compressedProfile, off, len); off += count; len -= count; } while(!compressor.finished()); int compressedDataLength = off; iCCP_compressedProfile = new byte[compressedDataLength]; System.arraycopy(compressedProfile, 0, iCCP_compressedProfile, 0, compressedDataLength); iCCP_present = true; } } private void parse_pHYs_chunk() throws IOException { int unitSpecifier = decoder.getPhysicalPixelDimensions(decoder.PNG_PIXELS_UNIT_SPECIFIER); if(unitSpecifier != decoder.PNG_pHYs_NOT_DEFINED) { pHYs_pixelsPerUnitXAxis = decoder.getPhysicalPixelDimensions(decoder.PNG_PIXELS_UNIT_X); pHYs_pixelsPerUnitYAxis = decoder.getPhysicalPixelDimensions(decoder.PNG_PIXELS_UNIT_Y); pHYs_unitSpecifier = unitSpecifier; pHYs_present = true; } } private void parse_sBIT_chunk() throws IOException { byte[] sBits = decoder.getSignificantBits(); if(sBits != null) { int i = 0; int colorType = IHDR_colorType; if (colorType == PNG_COLOR_GRAY || colorType == PNG_COLOR_GRAY_ALPHA) { sBIT_grayBits = sBits[i++]; } else if (colorType == PNG_COLOR_RGB || colorType == PNG_COLOR_PALETTE || colorType == PNG_COLOR_RGB_ALPHA) { sBIT_redBits = sBits[i++]; sBIT_greenBits = sBits[i++]; sBIT_blueBits = sBits[i++]; } if (colorType == PNG_COLOR_GRAY_ALPHA || colorType == PNG_COLOR_RGB_ALPHA) { sBIT_alphaBits = sBits[i++]; } sBIT_colorType = colorType; sBIT_present = true; } } private void parse_sPLT_chunk() throws IOException, IIOException { PNGChunk[] sPLTChunks = decoder.getSuggestedPalette(); if(sPLTChunks != null && sPLTChunks.length > 0 && sPLTChunks[0] != null) { PNGChunk sPLTChunk = sPLTChunks[0]; byte[] chunkData = sPLTChunk.getData(); int chunkLength = chunkData.length; InputStream is = new ByteArrayInputStream(sPLTChunk.getData()); ImageInputStream stream = new MemoryCacheImageInputStream(is); sPLT_paletteName = readNullTerminatedString(stream); chunkLength -= sPLT_paletteName.length() + 1; int sampleDepth = stream.readUnsignedByte(); sPLT_sampleDepth = sampleDepth; int numEntries = chunkLength/(4*(sampleDepth/8) + 2); sPLT_red = new int[numEntries]; sPLT_green = new int[numEntries]; sPLT_blue = new int[numEntries]; sPLT_alpha = new int[numEntries]; sPLT_frequency = new int[numEntries]; if (sampleDepth == 8) { for (int i = 0; i < numEntries; i++) { sPLT_red[i] = stream.readUnsignedByte(); sPLT_green[i] = stream.readUnsignedByte(); sPLT_blue[i] = stream.readUnsignedByte(); sPLT_alpha[i] = stream.readUnsignedByte(); sPLT_frequency[i] = stream.readUnsignedShort(); } } else if (sampleDepth == 16) { for (int i = 0; i < numEntries; i++) { sPLT_red[i] = stream.readUnsignedShort(); sPLT_green[i] = stream.readUnsignedShort(); sPLT_blue[i] = stream.readUnsignedShort(); sPLT_alpha[i] = stream.readUnsignedShort(); sPLT_frequency[i] = stream.readUnsignedShort(); } } else { throw new IIOException("sPLT sample depth not 8 or 16!"); } sPLT_present = true; } } private void parse_sRGB_chunk() throws IOException { int renderingIntent = decoder.getStandardRGB(); if(renderingIntent != decoder.PNG_sRGB_NOT_DEFINED) { sRGB_renderingIntent = renderingIntent; sRGB_present = true; } } private void parse_tIME_chunk() throws IOException { Calendar cal = decoder.getLastModificationTime(); if(cal != null) { tIME_year = cal.get(Calendar.YEAR); tIME_month = cal.get(Calendar.MONTH) + 1; tIME_day = cal.get(Calendar.DAY_OF_MONTH); tIME_hour = cal.get(Calendar.HOUR_OF_DAY); tIME_minute = cal.get(Calendar.MINUTE); tIME_second = cal.get(Calendar.SECOND); tIME_present = true; } } private void parse_tRNS_chunk() throws IOException { int[] transparency = decoder.getTransparency(); if(transparency == null) { return; } int colorType = IHDR_colorType; if (colorType == PNG_COLOR_PALETTE) { if (!PLTE_present) { processWarningOccurred( "tRNS chunk without prior PLTE chunk, ignoring it."); return; } // Alpha table may have fewer entries than RGB palette int maxEntries = PLTE_red.length; int numEntries = transparency.length; if (numEntries > maxEntries) { processWarningOccurred( "tRNS chunk has more entries than prior PLTE chunk, ignoring extras."); numEntries = maxEntries; } tRNS_alpha = new byte[numEntries]; tRNS_colorType = PNG_COLOR_PALETTE; for(int i = 0; i < numEntries; i++) { tRNS_alpha[i] = (byte)transparency[i]; } } else if (colorType == PNG_COLOR_GRAY) { if (transparency.length != 1) { processWarningOccurred( "tRNS chunk for gray image must have length 2, ignoring chunk."); return; } tRNS_gray = transparency[0]; tRNS_colorType = PNG_COLOR_GRAY; } else if (colorType == PNG_COLOR_RGB) { if (transparency.length != 3) { processWarningOccurred( "tRNS chunk for RGB image must have length 6, ignoring chunk."); return; } tRNS_red = transparency[0]; tRNS_green = transparency[1]; tRNS_blue = transparency[2]; tRNS_colorType = PNG_COLOR_RGB; } else { processWarningOccurred( "Gray+Alpha and RGBA images may not have a tRNS chunk, ignoring it."); return; } tRNS_present = true; } // Parse all iTXt, tEXt, and zTXt chunks. private void parseTextChunk() throws IOException { PNGTextualData[] textualData = decoder.getTextualData(); if(textualData != null) { for(int i = 0; i < textualData.length; i++) { PNGTextualData textData = textualData[i]; String keyword = textData.getKeyword(); String text = textData.getText(); String translatedKeyword = textData.getTranslatedKeyword(); // No way to detect a zTXt chunk to use tEXt for zTXt. // Also, all text is already decompressed. if(keyword.equals(translatedKeyword)) { // tEXt and zTXt tEXt_keyword.add(keyword); tEXt_text.add(text); } else { // iTXt iTXt_keyword.add(keyword); iTXt_text.add(text); iTXt_translatedKeyword.add(translatedKeyword); // XXX No access to compression flag so set to 'false' // as text is decompressed by codecLib. int compressionFlag = 0; iTXt_compressionFlag.add(new Integer(compressionFlag)); // No access to compression method but only specified // one is '0' (deflate compression with ZLib data stream). int compressionMethod = 0; iTXt_compressionMethod.add(new Integer(compressionMethod)); String languageTag = textData.getEncoding(); iTXt_languageTag.add(languageTag); } } } } synchronized void readMetadata(CLibPNGImageReader reader, Decoder decoder) throws IIOException { if (gotMetadata) { return; } this.reader = reader; this.decoder = decoder; readHeader(); try { parse_PLTE_chunk(); parse_bKGD_chunk(); parse_cHRM_chunk(); parse_gAMA_chunk(); parse_hIST_chunk(); parse_iCCP_chunk(); parse_pHYs_chunk(); parse_sBIT_chunk(); parse_sPLT_chunk(); parse_sRGB_chunk(); parse_tIME_chunk(); parse_tRNS_chunk(); parseTextChunk(); PNGChunk[] userChunks = decoder.getUserData(); if(userChunks != null) { for(int i = 0; i < userChunks.length; i++) { // Read an unknown chunk PNGChunk userChunk = userChunks[i]; int chunkType = userChunk.getID(); byte[] b = userChunk.getData(); StringBuffer chunkName = new StringBuffer(4); chunkName.append((char)(chunkType >>> 24)); chunkName.append((char)((chunkType >> 16) & 0xff)); chunkName.append((char)((chunkType >> 8) & 0xff)); chunkName.append((char)(chunkType & 0xff)); int ancillaryBit = chunkType >>> 28; if (ancillaryBit == 0) { processWarningOccurred( "Encountered unknown chunk with critical bit set!"); } unknownChunkType.add(chunkName.toString()); unknownChunkData.add(b); } } } catch (IOException e) { throw new IIOException("Error reading PNG metadata", e); } finally { this.reader = null; this.decoder = null; } gotMetadata = true; } void processWarningOccurred(String warning) { if(reader != null) { reader.forwardWarningMessage(warning); } } // END metadata reading methods. // BEGIN metadata writing methods. synchronized void writeMetadata(Encoder encoder) throws IIOException { if(IHDR_present) { encoder.setBitDepth(IHDR_bitDepth); encoder.setInterlaceMethod(IHDR_interlaceMethod == 0 ? Encoder.PNG_INTERLACE_METHOD_DEFAULT : Encoder.PNG_INTERLACE_METHOD_ADAM7); } if(PLTE_present) { int paletteLength = PLTE_red.length; byte[] palette = new byte[3*paletteLength]; for(int i = 0, j= 0; i < paletteLength; i++) { palette[j++] = PLTE_red[i]; palette[j++] = PLTE_green[i]; palette[j++] = PLTE_blue[i]; } encoder.setPalette(palette); } if(bKGD_present) { int[] color; switch(bKGD_colorType) { case PNG_COLOR_GRAY: color = new int[] {bKGD_gray}; break; case PNG_COLOR_PALETTE: color = new int[] {bKGD_index}; break; default: color = new int[] {bKGD_red, bKGD_green, bKGD_blue}; } encoder.setBackground(color); } if(cHRM_present) { encoder.setPrimaryChromaticities(cHRM_whitePointX, cHRM_whitePointY, cHRM_redX, cHRM_redY, cHRM_greenX, cHRM_greenY, cHRM_blueX, cHRM_blueY); } if(gAMA_present) { encoder.setImageGamma(gAMA_gamma); } if(hIST_present) { int histogramLength = hIST_histogram.length; short[] histogram = new short[histogramLength]; for(int i = 0; i < histogramLength; i++) { histogram[i] = (short)hIST_histogram[i]; } encoder.setHistogram(histogram); } if(iCCP_present) { // Encoder expects an uncompressed profile so decompress. Inflater decompresser = new Inflater(); decompresser.setInput(iCCP_compressedProfile); byte[] result = new byte[2*decompresser.getRemaining()]; int off = 0; try { do { off += decompresser.inflate(result, off, result.length - off); if(off == result.length && !decompresser.finished()) { byte[] tmpbuf = new byte[2*result.length]; System.arraycopy(result, 0, tmpbuf, 0, result.length); result = tmpbuf; } } while(!decompresser.finished()); decompresser.end(); byte[] uncompressedProfile; if(off == result.length) { uncompressedProfile = result; } else { uncompressedProfile = new byte[off]; System.arraycopy(result, 0, uncompressedProfile, 0, off); } String iCCPName = toPrintableLatin1(iCCP_profileName); encoder.setEmbeddedICCProfile(iCCPName, uncompressedProfile); } catch(DataFormatException e) { // XXX warning message? } } if(iTXt_keyword.size() > 0) { int numChunks = iTXt_keyword.size(); for(int i = 0; i < numChunks; i++) { Integer compressionFlag = Integer.valueOf((String)iTXt_compressionFlag.get(i)); encoder.setUnicodeTextualData ((String)iTXt_keyword.get(i), (String)iTXt_translatedKeyword.get(i), (String)iTXt_languageTag.get(i), (String)iTXt_text.get(i), compressionFlag.intValue() == 1); } } if(pHYs_present) { encoder.setPhysicalPixelDimensions(pHYs_pixelsPerUnitXAxis, pHYs_pixelsPerUnitYAxis, pHYs_unitSpecifier); } if(sBIT_present) { byte[] bits; switch(sBIT_colorType) { case PNG_COLOR_GRAY: bits = new byte[] {(byte)(sBIT_grayBits&0xff)}; break; case PNG_COLOR_GRAY_ALPHA: bits = new byte[] {(byte)(sBIT_grayBits&0xff), (byte)(sBIT_alphaBits&0xff)}; break; case PNG_COLOR_RGB_ALPHA: bits = new byte[] {(byte)(sBIT_redBits&0xff), (byte)(sBIT_greenBits&0xff), (byte)(sBIT_blueBits&0xff), (byte)(sBIT_alphaBits&0xff)}; break; default: // RGB and PALETTE bits = new byte[] {(byte)(sBIT_redBits&0xff), (byte)(sBIT_greenBits&0xff), (byte)(sBIT_blueBits&0xff)}; break; } encoder.setSignificantBits(bits); } if(sPLT_present) { if(sPLT_sampleDepth == 8) { byte[] red = new byte[sPLT_red.length]; byte[] green = new byte[sPLT_green.length]; byte[] blue = new byte[sPLT_blue.length]; byte[] alpha = new byte[sPLT_alpha.length]; short[] frequency = new short[sPLT_frequency.length]; int length = red.length; for(int i = 0; i < length; i++) { red[i] = (byte)(sPLT_red[i]&0xff); green[i] = (byte)(sPLT_green[i]&0xff); blue[i] = (byte)(sPLT_blue[i]&0xff); alpha[i] = (byte)(sPLT_alpha[i]&0xff); frequency[i] = (short)(sPLT_frequency[i]&0xffff); } String sPLTName = toPrintableLatin1(sPLT_paletteName); encoder.setSuggestedPalette(sPLTName, red, green, blue, alpha, frequency); } else { short[] red = new short[sPLT_red.length]; short[] green = new short[sPLT_green.length]; short[] blue = new short[sPLT_blue.length]; short[] alpha = new short[sPLT_alpha.length]; short[] frequency = new short[sPLT_frequency.length]; int length = red.length; for(int i = 0; i < length; i++) { red[i] = (short)(sPLT_red[i]&0xffff); green[i] = (short)(sPLT_green[i]&0xffff); blue[i] = (short)(sPLT_blue[i]&0xffff); alpha[i] = (short)(sPLT_alpha[i]&0xffff); frequency[i] = (short)(sPLT_frequency[i]&0xffff); } String sPLTName = toPrintableLatin1(sPLT_paletteName); encoder.setSuggestedPalette(sPLTName, red, green, blue, alpha, frequency); } } if(sRGB_present) { encoder.setStandardRGB(sRGB_renderingIntent); } if(tEXt_keyword.size() > 0) { int numChunks = tEXt_keyword.size(); for(int i = 0; i < numChunks; i++) { encoder.setTextualData((String)tEXt_keyword.get(i), (String)tEXt_text.get(i), false); } } if(tIME_present) { encoder.setLastModificationTime (new GregorianCalendar(tIME_year, tIME_month - 1, tIME_day, tIME_hour, tIME_minute, tIME_second)); } if(tRNS_present) { if(tRNS_colorType == PNG_COLOR_GRAY) { encoder.setTransparency(tRNS_gray, tRNS_gray, tRNS_gray); } else if(tRNS_colorType == PNG_COLOR_PALETTE) { int length = tRNS_alpha.length; int[] color = new int[length]; for(int i = 0; i < length; i++) { color[i] = tRNS_alpha[i]&0xff; } encoder.setTransparency(color); } else { encoder.setTransparency(tRNS_red, tRNS_green, tRNS_blue); } } if(zTXt_keyword.size() > 0) { int numChunks = zTXt_keyword.size(); for(int i = 0; i < numChunks; i++) { encoder.setTextualData((String)zTXt_keyword.get(i), (String)zTXt_text.get(i), true); } } if(unknownChunkType.size() > 0) { int numChunks = unknownChunkType.size(); for(int i = 0; i < numChunks; i++) { encoder.setUserData((String)unknownChunkType.get(i), (byte[])unknownChunkData.get(i), Encoder.PNG_SAVE_BEFORE_IMAGE_DATA); } } } // END metadata writing methods. } ././@LongLink0000000000000000000000000000016100000000000011563 Lustar rootrootjai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/png/CLibPNGMetadataFormatResources.javajai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/png/CLibPNGMetadataFormatRe0000664000175100017510000002623410203036165032423 0ustar tilletille/* * $RCSfile: CLibPNGMetadataFormatResources.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.1 $ * $Date: 2005-02-11 05:01:39 $ * $State: Exp $ */ package com.sun.media.imageioimpl.plugins.png; import java.util.ListResourceBundle; import javax.imageio.metadata.IIOMetadataFormat; import javax.imageio.metadata.IIOMetadataFormatImpl; public class CLibPNGMetadataFormatResources extends ListResourceBundle { static final Object[][] contents = { // Node name, followed by description { "IHDR", "The IHDR chunk, containing the header" }, { "PLTE", "The PLTE chunk, containing the palette" }, { "PLTEEntry", "A palette entry" }, { "bKGD", "The bKGD chunk, containing the background color" }, { "bKGD_RGB", "An RGB background color, for RGB and RGBAlpha images" }, { "bKGD_Grayscale", "A grayscale background color, for Gray and GrayAlpha images" }, { "bKGD_Palette", "A background palette index" }, { "cHRM", "The cHRM chunk, containing color calibration" }, { "gAMA", "The gAMA chunk, containing the image gamma" }, { "hIST", "The hIST chunk, containing histogram information " }, { "hISTEntry", "A histogram entry" }, { "iCCP", "The iCCP chunk, containing an ICC color profile" }, { "iTXt", "The iTXt chunk, containing internationalized text" }, { "iTXtEntry", "A localized text entry" }, { "pHYS", "The pHYS chunk, containing the pixel size and aspect ratio" }, { "sBIT", "The sBIT chunk, containing significant bit information" }, { "sBIT_Grayscale", "Significant bit information for gray samples" }, { "sBIT_GrayAlpha", "Significant bit information for gray and alpha samples" }, { "sBIT_RGB", "Significant bit information for RGB samples" }, { "sBIT_RGBAlpha", "Significant bit information for RGBA samples" }, { "sBIT_Palette", "Significant bit information for RGB palette entries" }, { "sPLT", "The sPLT chunk, containing a suggested palette" }, { "sPLTEntry", "A suggested palette entry" }, { "sRGB", "The sRGB chunk, containing rendering intent information" }, { "tEXt", "The tEXt chunk, containing text" }, { "tEXtEntry", "A text entry" }, { "tIME", "The tIME chunk, containing the image modification time" }, { "tRNS", "The tRNS chunk, containing transparency information" }, { "tRNS_Grayscale", "A grayscale value that should be considered transparent" }, { "tRNS_RGB", "An RGB value that should be considered transparent" }, { "tRNS_Palette", "A palette index that should be considered transparent" }, { "zTXt", "The zTXt chunk, containing compressed text" }, { "zTXtEntry", "A compressed text entry" }, { "UnknownChunks", "A set of unknown chunks" }, { "UnknownChunk", "Unknown chunk data stored as a byte array" }, // Node name + "/" + AttributeName, followed by description { "IHDR/width", "The width of the image in pixels" }, { "IHDR/height", "The height of the image in pixels" }, { "IHDR/bitDepth", "The bit depth of the image samples" }, { "IHDR/colorType", "The color type of the image" }, { "IHDR/compressionMethod", "The compression used for image data, always \"deflate\"" }, { "IHDR/filterMethod", "The filtering method used for compression, always \"adaptive\"" }, { "IHDR/interlaceMethod", "The interlacing method, \"none\" or \"adam7\"" }, { "PLTEEntry/index", "The index of a palette entry" }, { "PLTEEntry/red", "The red value of a palette entry" }, { "PLTEEntry/green", "The green value of a palette entry" }, { "PLTEEntry/blue", "The blue value of a palette entry" }, { "bKGD_Grayscale/gray", "A gray value to be used as a background" }, { "bKGD_RGB/red", "A red value to be used as a background" }, { "bKGD_RGB/green", "A green value to be used as a background" }, { "bKGD_RGB/blue", "A blue value to be used as a background" }, { "bKGD_Palette/index", "A palette index to be used as a background" }, { "cHRM/whitePointX", "The CIE x coordinate of the white point, multiplied by 1e5" }, { "cHRM/whitePointY", "The CIE y coordinate of the white point, multiplied by 1e5" }, { "cHRM/redX", "The CIE x coordinate of the red primary, multiplied by 1e5" }, { "cHRM/redY", "The CIE y coordinate of the red primary, multiplied by 1e5" }, { "cHRM/greenX", "The CIE x coordinate of the green primary, multiplied by 1e5" }, { "cHRM/greenY", "The CIE y coordinate of the green primary, multiplied by 1e5" }, { "cHRM/blueX", "The CIE x coordinate of the blue primary, multiplied by 1e5" }, { "cHRM/blueY", "The CIE y coordinate of the blue primary, multiplied by 1e5" }, { "gAMA/value", "The image gamma, multiplied by 1e5" }, { "hISTEntry/index", "The palette index of this histogram entry" }, { "hISTEntry/value", "The frequency of this histogram entry" }, { "iCCP/profileName", "The name of this ICC profile" }, { "iCCP/compressionMethod", "The compression method used to store this ICC profile" }, { "iTXtEntry/keyword", "The keyword" }, { "iTXtEntry/compressionMethod", "The compression method used to store this iTXt entry" }, { "iTXtEntry/languageTag", "The ISO tag describing the language of this iTXt entry" }, { "iTXtEntry/translatedKeyword", "The translated keyword for iTXt entry" }, { "iTXtEntry/text", "The localized text" }, { "pHYS/pixelsPerUnitXAxis", "The number of horizontal pixels per unit, multiplied by 1e5" }, { "pHYS/pixelsPerUnitYAxis", "The number of vertical pixels per unit, multiplied by 1e5" }, { "pHYS/unitSpecifier", "The unit specifier for this chunk (i.e., meters)" }, { "sBIT_Grayscale/gray", "The number of significant bits of the gray samples" }, { "sBIT_GrayAlpha/gray", "The number of significant bits of the gray of gray/alpha samples" }, { "sBIT_GrayAlpha/alpha", "The number of significant bits of the alpha of gray/alpha samples" }, { "sBIT_RGB/red", "The number of significant bits of the red of RGB samples" }, { "sBIT_RGB/green", "The number of significant bits of the green of RGB samples" }, { "sBIT_RGB/blue", "The number of significant bits of the blue of RGB samples" }, { "sBIT_RGBAlpha/red", "The number of significant bits of the red of RGBA samples" }, { "sBIT_RGBAlpha/green", "The number of significant bits of the green of RGBA samples" }, { "sBIT_RGBAlpha/blue", "The number of significant bits of the blue of RGBA samples" }, { "sBIT_RGBAlpha/alpha", "The number of significant bits of the alpha of RGBA samples" }, { "sBIT_Palette/red", "The number of significant bits of the red palette entries" }, { "sBIT_Palette/green", "The number of significant bits of the green palette entries" }, { "sBIT_Palette/blue", "The number of significant bits of the blue palette entries" }, { "sPLTEntry/index", "The index of a suggested palette entry" }, { "sPLTEntry/red", "The red value of a suggested palette entry" }, { "sPLTEntry/green", "The green value of a suggested palette entry" }, { "sPLTEntry/blue", "The blue value of a suggested palette entry" }, { "sPLTEntry/alpha", "The blue value of a suggested palette entry" }, { "sRGB/renderingIntent", "The rendering intent" }, { "tEXtEntry/keyword", "The keyword" }, { "tEXtEntry/value", "The text" }, { "tIME/year", "The year when the image was last modified" }, { "tIME/month", "The month when the image was last modified, 1 = January" }, { "tIME/day", "The day of the month when the image was last modified" }, { "tIME/hour", "The hour when the image was last modified" }, { "tIME/minute", "The minute when the image was last modified" }, { "tIME/second", "The second when the image was last modified, 60 = leap second" }, { "tRNS_Grayscale/gray", "The gray value to be considered transparent" }, { "tRNS_RGB/red", "The red value to be considered transparent" }, { "tRNS_RGB/green", "The green value to be considered transparent" }, { "tRNS_RGB/blue", "The blue value to be considered transparent" }, { "tRNS_Palette/index", "A palette index to be considered transparent" }, { "tRNS_Palette/alpha", "The transparency associated with the palette entry" }, { "zTXtEntry/keyword", "The keyword" }, { "zTXtEntry/compressionMethod", "The compression method" }, { "zTXtEntry/text", "The compressed text" }, { "UnknownChunk/type", "The 4-character type of the unknown chunk" } }; public CLibPNGMetadataFormatResources() {} public Object[][] getContents() { return contents; } } ././@LongLink0000000000000000000000000000015000000000000011561 Lustar rootrootjai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/png/CLibPNGMetadataFormat.javajai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/png/CLibPNGMetadataFormat.j0000664000175100017510000004473310203036165032370 0ustar tilletille/* * $RCSfile: CLibPNGMetadataFormat.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.1 $ * $Date: 2005-02-11 05:01:39 $ * $State: Exp $ */ package com.sun.media.imageioimpl.plugins.png; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.ListResourceBundle; import javax.imageio.ImageTypeSpecifier; import javax.imageio.metadata.IIOMetadataFormat; import javax.imageio.metadata.IIOMetadataFormatImpl; public class CLibPNGMetadataFormat extends IIOMetadataFormatImpl { private static IIOMetadataFormat instance = null; private static String VALUE_0 = "0"; private static String VALUE_1 = "1"; private static String VALUE_12 = "12"; private static String VALUE_23 = "23"; private static String VALUE_31 = "31"; private static String VALUE_59 = "59"; private static String VALUE_60 = "60"; private static String VALUE_255 = "255"; private static String VALUE_MAX_16 = "65535"; // 2^16 - 1 private static String VALUE_MAX_32 = "2147483647"; // 2^32 - 1 private CLibPNGMetadataFormat() { super(CLibPNGMetadata.nativeMetadataFormatName, CHILD_POLICY_SOME); // root -> IHDR addElement("IHDR", CLibPNGMetadata.nativeMetadataFormatName, CHILD_POLICY_EMPTY); addAttribute("IHDR", "width", DATATYPE_INTEGER, true, null, VALUE_1, VALUE_MAX_32, true, true); addAttribute("IHDR", "height", DATATYPE_INTEGER, true, null, VALUE_1, VALUE_MAX_32, true, true); addAttribute("IHDR", "bitDepth", DATATYPE_INTEGER, true, null, Arrays.asList(CLibPNGMetadata.IHDR_bitDepths)); String[] colorTypes = { "Grayscale", "RGB", "Palette", "GrayAlpha", "RGBAlpha" }; addAttribute("IHDR", "colorType", DATATYPE_STRING, true, null, Arrays.asList(colorTypes)); addAttribute("IHDR", "compressionMethod", DATATYPE_STRING, true, null, Arrays.asList(CLibPNGMetadata.IHDR_compressionMethodNames)); addAttribute("IHDR", "filterMethod", DATATYPE_STRING, true, null, Arrays.asList(CLibPNGMetadata.IHDR_filterMethodNames)); addAttribute("IHDR", "interlaceMethod", DATATYPE_STRING, true, null, Arrays.asList(CLibPNGMetadata.IHDR_interlaceMethodNames)); // root -> PLTE addElement("PLTE", CLibPNGMetadata.nativeMetadataFormatName, 1, 256); // root -> PLTE -> PLTEEntry addElement("PLTEEntry", "PLTE", CHILD_POLICY_EMPTY); addAttribute("PLTEEntry", "index", DATATYPE_INTEGER, true, null, VALUE_0, VALUE_255, true, true); addAttribute("PLTEEntry", "red", DATATYPE_INTEGER, true, null, VALUE_0, VALUE_255, true, true); addAttribute("PLTEEntry", "green", DATATYPE_INTEGER, true, null, VALUE_0, VALUE_255, true, true); addAttribute("PLTEEntry", "blue", DATATYPE_INTEGER, true, null, VALUE_0, VALUE_255, true, true); // root -> bKGD addElement("bKGD", CLibPNGMetadata.nativeMetadataFormatName, CHILD_POLICY_CHOICE); // root -> bKGD -> bKGD_Grayscale addElement("bKGD_Grayscale", "bKGD", CHILD_POLICY_EMPTY); addAttribute("bKGD_Grayscale", "gray", DATATYPE_INTEGER, true, null, VALUE_0, VALUE_MAX_16, true, true); // root -> bKGD -> bKGD_RGB addElement("bKGD_RGB", "bKGD", CHILD_POLICY_EMPTY); addAttribute("bKGD_RGB", "red", DATATYPE_INTEGER, true, null, VALUE_0, VALUE_MAX_16, true, true); addAttribute("bKGD_RGB", "green", DATATYPE_INTEGER, true, null, VALUE_0, VALUE_MAX_16, true, true); addAttribute("bKGD_RGB", "blue", DATATYPE_INTEGER, true, null, VALUE_0, VALUE_MAX_16, true, true); // root -> bKGD -> bKGD_Palette addElement("bKGD_Palette", "bKGD", CHILD_POLICY_EMPTY); addAttribute("bKGD_Palette", "index", DATATYPE_INTEGER, true, null, VALUE_0, VALUE_255, true, true); // root -> cHRM addElement("cHRM", CLibPNGMetadata.nativeMetadataFormatName, CHILD_POLICY_EMPTY); addAttribute("cHRM", "whitePointX", DATATYPE_INTEGER, true, null, VALUE_0, VALUE_MAX_16, true, true); addAttribute("cHRM", "whitePointY", DATATYPE_INTEGER, true, null, VALUE_0, VALUE_MAX_16, true, true); addAttribute("cHRM", "redX", DATATYPE_INTEGER, true, null, VALUE_0, VALUE_MAX_16, true, true); addAttribute("cHRM", "redY", DATATYPE_INTEGER, true, null, VALUE_0, VALUE_MAX_16, true, true); addAttribute("cHRM", "greenX", DATATYPE_INTEGER, true, null, VALUE_0, VALUE_MAX_16, true, true); addAttribute("cHRM", "greenY", DATATYPE_INTEGER, true, null, VALUE_0, VALUE_MAX_16, true, true); addAttribute("cHRM", "blueX", DATATYPE_INTEGER, true, null, VALUE_0, VALUE_MAX_16, true, true); addAttribute("cHRM", "blueY", DATATYPE_INTEGER, true, null, VALUE_0, VALUE_MAX_16, true, true); // root -> gAMA addElement("gAMA", CLibPNGMetadata.nativeMetadataFormatName, CHILD_POLICY_EMPTY); addAttribute("gAMA", "value", DATATYPE_INTEGER, true, null, VALUE_0, VALUE_MAX_32, true, true); // root -> hIST addElement("hIST", CLibPNGMetadata.nativeMetadataFormatName, 1, 256); // root -> hISTEntry addElement("hISTEntry", "hIST", CHILD_POLICY_EMPTY); addAttribute("hISTEntry", "index", DATATYPE_INTEGER, true, null, VALUE_0, VALUE_255, true, true); addAttribute("hISTEntry", "value", DATATYPE_INTEGER, true, null, VALUE_0, VALUE_MAX_16, true, true); // root -> iCCP addElement("iCCP", CLibPNGMetadata.nativeMetadataFormatName, CHILD_POLICY_EMPTY); addAttribute("iCCP", "profileName", DATATYPE_STRING, true, null); addAttribute("iCCP", "compressionMethod", DATATYPE_STRING, true, null, Arrays.asList(CLibPNGMetadata.iCCP_compressionMethodNames)); addObjectValue("iCCP", byte.class, 0, Integer.MAX_VALUE); // root -> iTXt addElement("iTXt", CLibPNGMetadata.nativeMetadataFormatName, 1, Integer.MAX_VALUE); // root -> iTXt -> iTXtEntry addElement("iTXtEntry", "iTXt", CHILD_POLICY_EMPTY); addAttribute("iTXtEntry", "keyword", DATATYPE_STRING, true, null); addBooleanAttribute("iTXtEntry", "compressionFlag", false, false); addAttribute("iTXtEntry", "compressionMethod", DATATYPE_STRING, true, null); addAttribute("iTXtEntry", "languageTag", DATATYPE_STRING, true, null); addAttribute("iTXtEntry", "translatedKeyword", DATATYPE_STRING, true, null); addAttribute("iTXtEntry", "text", DATATYPE_STRING, true, null); // root -> pHYS addElement("pHYS", CLibPNGMetadata.nativeMetadataFormatName, CHILD_POLICY_EMPTY); addAttribute("pHYS", "pixelsPerUnitXAxis", DATATYPE_INTEGER, true, null, VALUE_0, VALUE_MAX_32, true, true); addAttribute("pHYS", "pixelsPerUnitYAxis", DATATYPE_INTEGER, true, null, VALUE_0, VALUE_MAX_32, true, true); addAttribute("pHYS", "unitSpecifier", DATATYPE_STRING, true, null, Arrays.asList(CLibPNGMetadata.unitSpecifierNames)); // root -> sBIT addElement("sBIT", CLibPNGMetadata.nativeMetadataFormatName, CHILD_POLICY_CHOICE); // root -> sBIT -> sBIT_Grayscale addElement("sBIT_Grayscale", "sBIT", CHILD_POLICY_EMPTY); addAttribute("sBIT_Grayscale", "gray", DATATYPE_INTEGER, true, null, VALUE_0, VALUE_255, true, true); // root -> sBIT -> sBIT_GrayAlpha addElement("sBIT_GrayAlpha", "sBIT", CHILD_POLICY_EMPTY); addAttribute("sBIT_GrayAlpha", "gray", DATATYPE_INTEGER, true, null, VALUE_0, VALUE_255, true, true); addAttribute("sBIT_GrayAlpha", "alpha", DATATYPE_INTEGER, true, null, VALUE_0, VALUE_255, true, true); // root -> sBIT -> sBIT_RGB addElement("sBIT_RGB", "sBIT", CHILD_POLICY_EMPTY); addAttribute("sBIT_RGB", "red", DATATYPE_INTEGER, true, null, VALUE_0, VALUE_255, true, true); addAttribute("sBIT_RGB", "green", DATATYPE_INTEGER, true, null, VALUE_0, VALUE_255, true, true); addAttribute("sBIT_RGB", "blue", DATATYPE_INTEGER, true, null, VALUE_0, VALUE_255, true, true); // root -> sBIT -> sBIT_RGBAlpha addElement("sBIT_RGBAlpha", "sBIT", CHILD_POLICY_EMPTY); addAttribute("sBIT_RGBAlpha", "red", DATATYPE_INTEGER, true, null, VALUE_0, VALUE_255, true, true); addAttribute("sBIT_RGBAlpha", "green", DATATYPE_INTEGER, true, null, VALUE_0, VALUE_255, true, true); addAttribute("sBIT_RGBAlpha", "blue", DATATYPE_INTEGER, true, null, VALUE_0, VALUE_255, true, true); addAttribute("sBIT_RGBAlpha", "alpha", DATATYPE_INTEGER, true, null, VALUE_0, VALUE_255, true, true); // root -> sBIT -> sBIT_Palette addElement("sBIT_Palette", "sBIT", CHILD_POLICY_EMPTY); addAttribute("sBIT_Palette", "red", DATATYPE_INTEGER, true, null, VALUE_0, VALUE_255, true, true); addAttribute("sBIT_Palette", "green", DATATYPE_INTEGER, true, null, VALUE_0, VALUE_255, true, true); addAttribute("sBIT_Palette", "blue", DATATYPE_INTEGER, true, null, VALUE_0, VALUE_255, true, true); // root -> sPLT addElement("sPLT", CLibPNGMetadata.nativeMetadataFormatName, 1, 256); // root -> sPLT -> sPLTEntry addElement("sPLTEntry", "sPLT", CHILD_POLICY_EMPTY); addAttribute("sPLTEntry", "index", DATATYPE_INTEGER, true, null, VALUE_0, VALUE_255, true, true); addAttribute("sPLTEntry", "red", DATATYPE_INTEGER, true, null, VALUE_0, VALUE_255, true, true); addAttribute("sPLTEntry", "green", DATATYPE_INTEGER, true, null, VALUE_0, VALUE_255, true, true); addAttribute("sPLTEntry", "blue", DATATYPE_INTEGER, true, null, VALUE_0, VALUE_255, true, true); addAttribute("sPLTEntry", "alpha", DATATYPE_INTEGER, true, null, VALUE_0, VALUE_255, true, true); // root -> sRGB addElement("sRGB", CLibPNGMetadata.nativeMetadataFormatName, CHILD_POLICY_EMPTY); addAttribute("sRGB", "renderingIntent", DATATYPE_STRING, true, null, Arrays.asList(CLibPNGMetadata.renderingIntentNames)); // root -> tEXt addElement("tEXt", CLibPNGMetadata.nativeMetadataFormatName, 1, Integer.MAX_VALUE); // root -> tEXt -> tEXtEntry addElement("tEXtEntry", "tEXt", CHILD_POLICY_EMPTY); addAttribute("tEXtEntry", "keyword", DATATYPE_STRING, true, null); addAttribute("tEXtEntry", "value", DATATYPE_STRING, true, null); // root -> tIME addElement("tIME", CLibPNGMetadata.nativeMetadataFormatName, CHILD_POLICY_EMPTY); addAttribute("tIME", "year", DATATYPE_INTEGER, true, null, VALUE_0, VALUE_MAX_16, true, true); addAttribute("tIME", "month", DATATYPE_INTEGER, true, null, VALUE_1, VALUE_12, true, true); addAttribute("tIME", "day", DATATYPE_INTEGER, true, null, VALUE_1, VALUE_31, true, true); addAttribute("tIME", "hour", DATATYPE_INTEGER, true, null, VALUE_0, VALUE_23, true, true); addAttribute("tIME", "minute", DATATYPE_INTEGER, true, null, VALUE_0, VALUE_59, true, true); addAttribute("tIME", "second", DATATYPE_INTEGER, true, null, VALUE_0, VALUE_60, true, true); // root -> tRNS addElement("tRNS", CLibPNGMetadata.nativeMetadataFormatName, CHILD_POLICY_CHOICE); // root -> tRNS -> tRNS_Grayscale addElement("tRNS_Grayscale", "tRNS", CHILD_POLICY_EMPTY); addAttribute("tRNS_Grayscale", "gray", DATATYPE_INTEGER, true, null, VALUE_0, VALUE_MAX_16, true, true); // root -> tRNS -> tRNS_RGB addElement("tRNS_RGB", "tRNS", CHILD_POLICY_EMPTY); addAttribute("tRNS_RGB", "red", DATATYPE_INTEGER, true, null, VALUE_0, VALUE_MAX_16, true, true); addAttribute("tRNS_RGB", "green", DATATYPE_INTEGER, true, null, VALUE_0, VALUE_MAX_16, true, true); addAttribute("tRNS_RGB", "blue", DATATYPE_INTEGER, true, null, VALUE_0, VALUE_MAX_16, true, true); // root -> tRNS -> tRNS_Palette addElement("tRNS_Palette", "tRNS", CHILD_POLICY_EMPTY); addAttribute("tRNS_Palette", "index", DATATYPE_INTEGER, true, null, VALUE_0, VALUE_255, true, true); addAttribute("tRNS_Palette", "alpha", DATATYPE_INTEGER, true, null, VALUE_0, VALUE_255, true, true); // root -> zTXt addElement("zTXt", CLibPNGMetadata.nativeMetadataFormatName, 1, Integer.MAX_VALUE); // root -> zTXt -> zTXtEntry addElement("zTXtEntry", "zTXt", CHILD_POLICY_EMPTY); addAttribute("zTXtEntry", "keyword", DATATYPE_STRING, true, null); addAttribute("zTXtEntry", "compressionMethod", DATATYPE_STRING, true, null, Arrays.asList(CLibPNGMetadata.zTXt_compressionMethodNames)); addAttribute("zTXtEntry", "text", DATATYPE_STRING, true, null); // root -> UnknownChunks addElement("UnknownChunks", CLibPNGMetadata.nativeMetadataFormatName, 1, Integer.MAX_VALUE); // root -> UnknownChunks -> UnknownChunk addElement("UnknownChunk", "UnknownChunks", CHILD_POLICY_EMPTY); addAttribute("UnknownChunk", "type", DATATYPE_STRING, true, null); addObjectValue("UnknownChunk", byte.class, 0, Integer.MAX_VALUE); } public boolean canNodeAppear(String elementName, ImageTypeSpecifier imageType) { return true; } public static synchronized IIOMetadataFormat getInstance() { if (instance == null) { instance = new CLibPNGMetadataFormat(); } return instance; } } jai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/png/properties0000664000175100017510000000066710240246476030353 0ustar tilletille# # $RCSfile: properties,v $ # # Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved. # # Use is subject to license terms. # # $Revision: 1.2 $ # $Date: 2005-05-11 00:09:34 $ # $State: Exp $ # # Internationalization file for com.sun.media.imageioimpl.plugins.png CLibPNGImageReader0=Decoder cannot decode input. CLibPNGImageWriteParam0=Best Compression CLibPNGImageWriteParam1=Best Speed CLibPNGImageWriteParam2=No Compression ././@LongLink0000000000000000000000000000015000000000000011561 Lustar rootrootjai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/png/CLibPNGImageReaderSpi.javajai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/png/CLibPNGImageReaderSpi.j0000664000175100017510000001176310413303155032314 0ustar tilletille/* * $RCSfile: CLibPNGImageReaderSpi.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.2 $ * $Date: 2006-03-31 19:43:40 $ * $State: Exp $ */ package com.sun.media.imageioimpl.plugins.png; import java.util.List; import java.util.Locale; import javax.imageio.spi.ImageReaderSpi; import javax.imageio.stream.ImageInputStream; import javax.imageio.spi.ServiceRegistry; import java.io.IOException; import javax.imageio.ImageReader; import javax.imageio.IIOException; import com.sun.media.imageioimpl.common.PackageUtil; import com.sun.media.imageioimpl.common.ImageUtil; public class CLibPNGImageReaderSpi extends ImageReaderSpi { private static final String[] names = {"png", "PNG"}; private static final String[] suffixes = {"png"}; private static final String[] MIMETypes = {"image/png", "image/x-png"}; private static final String readerClassName = "com.sun.media.imageioimpl.plugins.png.CLibPNGImageReader"; private static final String[] writerSpiNames = { "com.sun.media.imageioimpl.plugins.png.CLibPNGImageWriterSpi" }; private boolean registered = false; public CLibPNGImageReaderSpi() { super(PackageUtil.getVendor(), PackageUtil.getVersion(), names, suffixes, MIMETypes, readerClassName, STANDARD_INPUT_TYPE, writerSpiNames, false, null, null, null, null, true, CLibPNGMetadata.nativeMetadataFormatName, "com.sun.media.imageioimpl.plugins.png.CLibPNGMetadataFormat", null, null); } public void onRegistration(ServiceRegistry registry, Class category) { if (registered) { return; } registered = true; // Branch as a function of codecLib availability. if(!PackageUtil.isCodecLibAvailable()) { // Deregister provider. registry.deregisterServiceProvider(this); } else { List list = ImageUtil.getJDKImageReaderWriterSPI(registry, "PNG", true); for (int i=0; i= 3 || rgbPalette != null)) || (icccs.getType() == ColorSpace.TYPE_GRAY && numBands < 3 && rgbPalette == null)) { cs = icccs; } } } int bitDepth = decoder.getBitDepth(); ImageTypeSpecifier type = createImageType(image, cs, bitDepth, null, null, null, null); types.add(type); if(type.getColorModel().getColorSpace().equals(cs)) { types.add(createImageType(image, null, bitDepth, null, null, null, null)); } } imageTypes.put(key, types); } // XXX Need also to use getBackground() to save the background // color somewhere, eventually as an image property with the // name "background_color" and with a java.awt.Color value. // See PNGImageDecoder or the PNG ImageReader for more info. // Looks like this needs to be set as a metadata entry. It is // obtained from the decoder using getBackground(). return types.iterator(); } // Override superclass method. protected void resetLocal() { decoder = null; imageTypes.clear(); super.resetLocal(); } public synchronized IIOMetadata getImageMetadata(int imageIndex) throws IIOException { if(input == null) { throw new IllegalStateException("input == null"); } seekToImage(imageIndex); CLibPNGMetadata im = new CLibPNGMetadata(); try { getImage(imageIndex); } catch(IOException e) { throw new IIOException("codecLib error", e); } im.readMetadata(this, decoder); return im; } /** * Package scope method to classes in package to emit warning messages. */ void forwardWarningMessage(String warning) { processWarningOccurred(warning); } } jai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/png/I18N.java0000664000175100017510000000420510203036165027535 0ustar tilletille/* * $RCSfile: I18N.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.1 $ * $Date: 2005-02-11 05:01:39 $ * $State: Exp $ */ package com.sun.media.imageioimpl.plugins.png; import com.sun.media.imageioimpl.common.I18NImpl; final class I18N extends I18NImpl { static String getString(String key) { return getString("com.sun.media.imageioimpl.plugins.png.I18N", key); } } ././@LongLink0000000000000000000000000000015000000000000011561 Lustar rootrootjai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/png/CLibPNGImageWriterSpi.javajai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/png/CLibPNGImageWriterSpi.j0000664000175100017510000001345110413303155032362 0ustar tilletille/* * $RCSfile: CLibPNGImageWriterSpi.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.2 $ * $Date: 2006-03-31 19:43:40 $ * $State: Exp $ */ package com.sun.media.imageioimpl.plugins.png; import java.awt.image.ColorModel; import java.awt.image.IndexColorModel; import java.awt.image.SampleModel; import java.util.List; import java.util.Locale; import javax.imageio.ImageWriter; import javax.imageio.ImageTypeSpecifier; import javax.imageio.metadata.IIOMetadataFormat; import javax.imageio.metadata.IIOMetadataFormatImpl; import javax.imageio.spi.ImageWriterSpi; import javax.imageio.spi.ServiceRegistry; import com.sun.media.imageioimpl.common.PackageUtil; import com.sun.media.imageioimpl.common.ImageUtil; /** */ public class CLibPNGImageWriterSpi extends ImageWriterSpi { private static final String[] names = {"png", "PNG"}; private static final String[] suffixes = { "png" }; private static final String[] MIMETypes = { "image/png", "image/x-png" }; private static final String writerClassName = "com.sun.media.imageioimpl.plugins.png.CLibPNGImageWriter"; private static final String[] readerSpiNames = { "com.sun.media.imageioimpl.plugins.png.CLibPNGImageReaderSpi" }; private boolean registered = false; public CLibPNGImageWriterSpi() { super(PackageUtil.getVendor(), PackageUtil.getVersion(), names, suffixes, MIMETypes, writerClassName, STANDARD_OUTPUT_TYPE, readerSpiNames, false, null, null, null, null, true, CLibPNGMetadata.nativeMetadataFormatName, "com.sun.media.imageioimpl.plugins.png.CLibPNGMetadataFormat", null, null); } public void onRegistration(ServiceRegistry registry, Class category) { if (registered) { return; } registered = true; // Branch as a function of codecLib availability. if(!PackageUtil.isCodecLibAvailable()) { // Deregister provider. registry.deregisterServiceProvider(this); } else { List list = ImageUtil.getJDKImageReaderWriterSPI(registry, "PNG", false); for (int i=0; i 4) { return false; } if (colorModel instanceof IndexColorModel) { return true; } boolean hasAlpha = colorModel != null && colorModel.hasAlpha(); if ((numBands == 1 || numBands == 3) && hasAlpha) { return false; } if ((numBands == 2 || numBands == 4) && !hasAlpha) { return false; } return true; } public String getDescription(Locale locale) { String desc = PackageUtil.getSpecificationTitle() + " natively-accelerated PNG Image Writer"; return desc; } public ImageWriter createWriterInstance(Object extension) { return new CLibPNGImageWriter(this); } } jai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/jpeg/0000775000175100017510000000000011650556207026366 5ustar tilletille././@LongLink0000000000000000000000000000015200000000000011563 Lustar rootrootjai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/jpeg/CLibJPEGImageWriterSpi.javajai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/jpeg/CLibJPEGImageWriterSpi0000664000175100017510000001356110423541222032376 0ustar tilletille/* * $RCSfile: CLibJPEGImageWriterSpi.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.4 $ * $Date: 2006-04-26 00:45:06 $ * $State: Exp $ */ package com.sun.media.imageioimpl.plugins.jpeg; import java.awt.image.ColorModel; import java.awt.image.IndexColorModel; import java.awt.image.SampleModel; import java.io.IOException; import java.util.List; import java.util.Locale; import javax.imageio.ImageWriter; import javax.imageio.ImageTypeSpecifier; import javax.imageio.metadata.IIOMetadataFormat; import javax.imageio.metadata.IIOMetadataFormatImpl; import javax.imageio.spi.ImageWriterSpi; import javax.imageio.spi.ServiceRegistry; import com.sun.media.imageioimpl.common.PackageUtil; import com.sun.media.imageioimpl.common.ImageUtil; /** */ public class CLibJPEGImageWriterSpi extends ImageWriterSpi { private static final String[] names = {"jpeg", "JPEG", "jpg", "JPG", "jfif", "JFIF", "jpeg-lossless", "JPEG-LOSSLESS", "jpeg-ls", "JPEG-LS"}; private static final String[] suffixes = {"jpeg", "jpg", "jfif", "jls"}; private static final String[] MIMETypes = { "image/jpeg" }; private static final String writerClassName = "com.sun.media.imageioimpl.plugins.jpeg.CLibJPEGImageWriter"; private static final String[] readerSpiNames = { "com.sun.media.imageioimpl.plugins.jpeg.CLibJPEGImageReaderSpi" }; private boolean registered = false; public CLibJPEGImageWriterSpi() { super(PackageUtil.getVendor(), PackageUtil.getVersion(), names, suffixes, MIMETypes, writerClassName, STANDARD_OUTPUT_TYPE, readerSpiNames, false, null, null, null, null, false, null, null, null, null); } public void onRegistration(ServiceRegistry registry, Class category) { if (registered) { return; } registered = true; // Branch as a function of codecLib availability. if(!PackageUtil.isCodecLibAvailable()) { // Deregister provider. registry.deregisterServiceProvider(this); } else { List list = ImageUtil.getJDKImageReaderWriterSPI(registry, "JPEG", false); for (int i=0; i 16) { return false; } // Check number of bands. int numBands = sampleModel.getNumBands(); if (numBands < 1 || numBands > 4) { return false; } return true; } public String getDescription(Locale locale) { String desc = PackageUtil.getSpecificationTitle() + " natively-accelerated JPEG Image Writer"; return desc; } public ImageWriter createWriterInstance(Object extension) throws IOException { return new CLibJPEGImageWriter(this); } } jai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/jpeg/properties0000664000175100017510000000070110203036165030470 0ustar tilletille# # $RCSfile: properties,v $ # # Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved. # # Use is subject to license terms. # # $Revision: 1.1 $ # $Date: 2005-02-11 05:01:30 $ # $State: Exp $ # # Internationalization file for com.sun.media.imageioimpl.plugins.jpeg CLibJPEGImageReader0=Decoder cannot decode input. CLibJPEGImageWriteParam0=Minimum useful CLibJPEGImageWriteParam1=Visually lossless CLibJPEGImageWriteParam2=Maximum useful ././@LongLink0000000000000000000000000000014700000000000011567 Lustar rootrootjai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/jpeg/CLibJPEGImageReader.javajai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/jpeg/CLibJPEGImageReader.ja0000664000175100017510000003125110423235255032243 0ustar tilletille/* * $RCSfile: CLibJPEGImageReader.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.10 $ * $Date: 2006-04-24 20:53:01 $ * $State: Exp $ */ package com.sun.media.imageioimpl.plugins.jpeg; import java.awt.color.ColorSpace; import java.awt.color.ICC_ColorSpace; import java.awt.color.ICC_Profile; import java.awt.image.BufferedImage; import java.awt.image.ColorModel; import java.awt.image.DataBuffer; import java.awt.image.MultiPixelPackedSampleModel; import java.awt.image.PixelInterleavedSampleModel; import java.awt.image.SampleModel; import java.io.File; import java.io.FileInputStream; import java.io.InputStream; import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import javax.imageio.IIOException; import javax.imageio.IIOImage; import javax.imageio.ImageReader; import javax.imageio.ImageReadParam; import javax.imageio.ImageTypeSpecifier; import javax.imageio.metadata.IIOMetadata; import javax.imageio.spi.ImageReaderSpi; import javax.imageio.stream.ImageInputStream; import com.sun.media.imageioimpl.common.InvertedCMYKColorSpace; import com.sun.media.imageioimpl.plugins.clib.CLibImageReader; import com.sun.media.imageioimpl.plugins.clib.InputStreamAdapter; import com.sun.medialib.codec.jpeg.Decoder; import com.sun.medialib.codec.jiio.mediaLibImage; final class CLibJPEGImageReader extends CLibImageReader { private static final boolean DEBUG = false; // XXX false for release private mediaLibImage infoImage = null; private int infoImageIndex = -1; private byte[] iccProfileData = null; private IIOMetadata imageMetadata = null; private int imageMetadataIndex = -1; private HashMap imageTypes = new HashMap(); private int bitDepth; // XXX Should depend on imageIndex. CLibJPEGImageReader(ImageReaderSpi originatingProvider) { super(originatingProvider); } // Implement abstract method defined in superclass. protected final synchronized mediaLibImage decode(InputStream stream) throws IOException { if(DEBUG) System.out.println("In decode()"); mediaLibImage mlImage = null; Decoder decoder = null; try { if(stream instanceof InputStreamAdapter) { ImageInputStream iis = ((InputStreamAdapter)stream).getWrappedStream(); decoder = new Decoder(iis); } else { decoder = new Decoder(stream); } //decoder.setType(Decoder.JPEG_TYPE_UNKNOWN); mlImage = decoder.decode(null); // Set the ICC profile data. iccProfileData = decoder.getEmbeddedICCProfile(); // If there is a profile need to invert the data if they // are YCCK or CMYK originally. if(iccProfileData != null && mlImage.getType() == mediaLibImage.MLIB_BYTE) { int format = mlImage.getFormat(); if(format == mediaLibImage.MLIB_FORMAT_CMYK || format == mediaLibImage.MLIB_FORMAT_YCCK) { long t0 = System.currentTimeMillis(); byte[] data = mlImage.getByteData(); int len = data.length; for(int i = mlImage.getOffset(); i < len; i++) { data[i] = (byte)(255 - data[i]&0xff); } } } } catch(Throwable t) { throw new IIOException("codecLib error", t); } if(mlImage == null) { throw new IIOException(I18N.getString("CLibJPEGImageReader0")); } // Set variable indicating bit depth. try { bitDepth = decoder.getDepth(); } catch(Throwable t) { throw new IIOException("codecLib error", t); } // Free native resources. decoder.dispose(); if(DEBUG) { System.out.println("type = "+mlImage.getType()); System.out.println("channels = "+mlImage.getChannels()); System.out.println("width = "+mlImage.getWidth()); System.out.println("height = "+mlImage.getHeight()); System.out.println("stride = "+mlImage.getStride()); System.out.println("offset = "+mlImage.getOffset()); System.out.println("bitOffset = "+mlImage.getBitOffset()); System.out.println("format = "+mlImage.getFormat()); } return mlImage; } // Retrieve mediaLibImage containing everything except possibly the // decoded image data. If the real image has already been decoded // then it will be returned. private synchronized mediaLibImage getInfoImage(int imageIndex) throws IOException { if(DEBUG) System.out.println("In getInfoImage()"); if(infoImage == null || imageIndex != infoImageIndex) { // Use the cached image if it has the correct index. if(imageIndex == getImageIndex()) { if(DEBUG) { System.out.println("Using cached image."); } infoImage = getImage(imageIndex); infoImageIndex = imageIndex; return infoImage; } if(input == null) { throw new IllegalStateException("input == null"); } // Check the input and set local variable. ImageInputStream iis = null; if(input instanceof ImageInputStream) { iis = (ImageInputStream)input; } else { throw new IllegalArgumentException ("!(input instanceof ImageInputStream)"); } seekToImage(imageIndex); // Mark the input. iis.mark(); Decoder decoder = null; try { // Create the decoder decoder = new Decoder(iis); // Set the informational image. infoImage = decoder.getSize(); // Set the ICC profile data. iccProfileData = decoder.getEmbeddedICCProfile(); } catch(Throwable t) { throw new IIOException("codecLib error", t); } // XXX The lines marked "XXX" are a workaround for getSize() // not correctly setting the format of infoImage. if(infoImage == null || (infoImage.getFormat() == // XXX mediaLibImage.MLIB_FORMAT_UNKNOWN && // XXX ((infoImage = getImage(imageIndex)) == null))) { // XXX throw new IIOException(I18N.getString("CLibJPEGImageReader0")); } infoImageIndex = imageIndex; try { // Set variable indicating bit depth. bitDepth = decoder.getDepth(); } catch(Throwable t) { throw new IIOException("codecLib error", t); } // Reset the input to the marked position. iis.reset(); // Free native resources. decoder.dispose(); if(DEBUG) { System.out.println("type = "+infoImage.getType()); System.out.println("channels = "+infoImage.getChannels()); System.out.println("width = "+infoImage.getWidth()); System.out.println("height = "+infoImage.getHeight()); System.out.println("stride = "+infoImage.getStride()); System.out.println("offset = "+infoImage.getOffset()); System.out.println("bitOffset = "+infoImage.getBitOffset()); System.out.println("format = "+infoImage.getFormat()); } } return infoImage; } public int getWidth(int imageIndex) throws IOException { if(DEBUG) System.out.println("In getWidth()"); return getInfoImage(imageIndex).getWidth(); } public int getHeight(int imageIndex) throws IOException { if(DEBUG) System.out.println("In getHeight()"); return getInfoImage(imageIndex).getHeight(); } public Iterator getImageTypes(int imageIndex) throws IOException { if(DEBUG) System.out.println("In getImageTypes()"); seekToImage(imageIndex); ArrayList types = null; synchronized(imageTypes) { Integer key = new Integer(imageIndex); if(imageTypes.containsKey(key)) { types = (ArrayList)imageTypes.get(key); } else { types = new ArrayList(); // Get the informational image. mediaLibImage mlImage = getInfoImage(imageIndex); ColorSpace cs; // Add profile-based type if an ICC profile is present. if(iccProfileData != null) { ICC_Profile profile = ICC_Profile.getInstance(iccProfileData); cs = new ICC_ColorSpace(profile); types.add(createImageType(mlImage, cs, bitDepth, null, null, null, null)); } // Add a standard type. cs = mlImage.getFormat() == mediaLibImage.MLIB_FORMAT_CMYK ? InvertedCMYKColorSpace.getInstance() : null; types.add(createImageType(mlImage, cs, bitDepth, null, null, null, null)); } } return types.iterator(); } public synchronized IIOMetadata getImageMetadata(int imageIndex) throws IOException { if(input == null) { throw new IllegalStateException("input == null"); } if(imageMetadata == null || imageIndex != imageMetadataIndex) { seekToImage(imageIndex); ImageInputStream stream = (ImageInputStream)input; long pos = stream.getStreamPosition(); try { imageMetadata = new CLibJPEGMetadata(stream); imageMetadataIndex = imageIndex; } catch(IIOException e) { throw e; } finally { stream.seek(pos); } } return imageMetadata; } // Override thumbnail methods. public boolean readerSupportsThumbnails() { return true; } public int getNumThumbnails(int imageIndex) throws IOException { CLibJPEGMetadata metadata = (CLibJPEGMetadata)getImageMetadata(imageIndex); return metadata.getNumThumbnails(); } public BufferedImage readThumbnail(int imageIndex, int thumbnailIndex) throws IOException { CLibJPEGMetadata metadata = (CLibJPEGMetadata)getImageMetadata(imageIndex); return metadata.getThumbnail(thumbnailIndex); } // Override superclass method. protected void resetLocal() { infoImage = null; infoImageIndex = -1; iccProfileData = null; imageMetadata = null; imageMetadataIndex = -1; imageTypes.clear(); super.resetLocal(); } } ././@LongLink0000000000000000000000000000014700000000000011567 Lustar rootrootjai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/jpeg/CLibJPEGImageWriter.javajai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/jpeg/CLibJPEGImageWriter.ja0000664000175100017510000003322510423544546032326 0ustar tilletille/* * $RCSfile: CLibJPEGImageWriter.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.5 $ * $Date: 2006-04-26 01:14:14 $ * $State: Exp $ */ package com.sun.media.imageioimpl.plugins.jpeg; import java.awt.image.BufferedImage; import java.awt.image.ColorModel; import java.awt.image.DirectColorModel; import java.awt.image.IndexColorModel; import java.awt.image.PackedColorModel; import java.awt.image.Raster; import java.awt.image.RenderedImage; import java.awt.image.WritableRaster; import java.io.IOException; import java.io.OutputStream; import java.util.Locale; import javax.imageio.IIOException; import javax.imageio.IIOImage; import javax.imageio.ImageWriter; import javax.imageio.ImageWriteParam; import javax.imageio.ImageTypeSpecifier; import javax.imageio.metadata.IIOMetadata; import javax.imageio.spi.ImageWriterSpi; import javax.imageio.stream.ImageOutputStream; import com.sun.media.imageioimpl.common.ImageUtil; import com.sun.media.imageioimpl.plugins.clib.CLibImageWriter; import com.sun.media.imageioimpl.plugins.clib.OutputStreamAdapter; import com.sun.medialib.codec.jpeg.Encoder; import com.sun.medialib.codec.jiio.Constants; import com.sun.medialib.codec.jiio.mediaLibImage; final class CLibJPEGImageWriter extends CLibImageWriter { private Encoder encoder; /** * Convert an IndexColorModel-based image to 3-band component RGB. * * @param im The source image. * @throws IllegalArgumentException if the parameter is null. * @throws IllegalArgumentException if the source does is not indexed. */ private static BufferedImage convertTo3BandRGB(RenderedImage im) { // Check parameter. if(im == null) { throw new IllegalArgumentException("im == null"); } ColorModel cm = im.getColorModel(); if(!(cm instanceof IndexColorModel)) { throw new IllegalArgumentException ("!(im.getColorModel() instanceof IndexColorModel)"); } Raster src; if(im.getNumXTiles() == 1 && im.getNumYTiles() == 1) { // Image is not tiled so just get a reference to the tile. src = im.getTile(im.getMinTileX(), im.getMinTileY()); if (src.getWidth() != im.getWidth() || src.getHeight() != im.getHeight()) { src = src.createChild(src.getMinX(), src.getMinY(), im.getWidth(), im.getHeight(), src.getMinX(), src.getMinY(), null); } } else { // Image is tiled so need to get a contiguous raster. src = im.getData(); } // This is probably not the most efficient approach given that // the mediaLibImage will eventually need to be in component form. BufferedImage dst = ((IndexColorModel)cm).convertToIntDiscrete(src, false); if(dst.getSampleModel().getNumBands() == 4) { // // Without copying data create a BufferedImage which has // only the RGB bands, not the alpha band. // WritableRaster rgbaRas = dst.getRaster(); WritableRaster rgbRas = rgbaRas.createWritableChild(0, 0, dst.getWidth(), dst.getHeight(), 0, 0, new int[] {0, 1, 2}); PackedColorModel pcm = (PackedColorModel)dst.getColorModel(); int bits = pcm.getComponentSize(0) + pcm.getComponentSize(1) + pcm.getComponentSize(2); DirectColorModel dcm = new DirectColorModel(bits, pcm.getMask(0), pcm.getMask(1), pcm.getMask(2)); dst = new BufferedImage(dcm, rgbRas, false, null); } return dst; } CLibJPEGImageWriter(ImageWriterSpi originatingProvider) throws IOException { super(originatingProvider); try { encoder = new Encoder(); encoder.setExtend(Encoder.JPEG_IMAGE_NONEXTENDED); } catch(Throwable t) { throw new IIOException("codecLib error", t); } } public ImageWriteParam getDefaultWriteParam() { return new CLibJPEGImageWriteParam(getLocale()); } public void write(IIOMetadata streamMetadata, IIOImage image, ImageWriteParam param) throws IOException { if(output == null) { throw new IllegalStateException("output == null"); } OutputStream stream = null; if(output instanceof ImageOutputStream) { stream = new OutputStreamAdapter((ImageOutputStream)output); } else { throw new IllegalArgumentException ("!(output instanceof ImageOutputStream)"); } RenderedImage renderedImage = image.getRenderedImage(); if(renderedImage.getColorModel() instanceof IndexColorModel) { renderedImage = convertTo3BandRGB(renderedImage); } // Test for all. ImageUtil.canEncodeImage(this, renderedImage.getColorModel(), renderedImage.getSampleModel()); // Test for baseline. int bitDepth = renderedImage.getColorModel().getComponentSize(0); if((param == null || (param.getCompressionMode() == ImageWriteParam.MODE_EXPLICIT && !param.isCompressionLossless())) && bitDepth > 12) { throw new IIOException ("JPEG baseline encoding is limited to 12 bits: "+this); } // Set compression mode and quality from ImageWriteParam, if any. if(param != null && param.getCompressionMode() == ImageWriteParam.MODE_EXPLICIT) { if(param.isCompressionLossless()) { try { if(bitDepth >= 2 && bitDepth <= 16 && bitDepth % 8 != 0) { encoder.setDepth(bitDepth); } if(param.getCompressionType().equalsIgnoreCase (CLibJPEGImageWriteParam.LOSSLESS_COMPRESSION_TYPE)) { encoder.setMode(Encoder.JPEG_MODE_LOSSLESS); } else { encoder.setMode(Encoder.JPEG_MODE_HPLOCO); } } catch(Throwable t) { throw new IIOException("codecLib error", t); } } else { try { encoder.setMode(Encoder.JPEG_MODE_BASELINE); // XXX Q == 100 caused a core dump during testing. encoder.setQuality((int)(param.getCompressionQuality()*100)); } catch(Throwable t) { throw new IIOException("codecLib error", t); } } } else { try { encoder.setMode(Encoder.JPEG_MODE_BASELINE); encoder.setQuality(75); } catch(Throwable t) { throw new IIOException("codecLib error", t); } } int[] supportedFormats = param == null || (param.getCompressionMode() == ImageWriteParam.MODE_EXPLICIT && !param.isCompressionLossless()) ? new int [] {Constants.MLIB_FORMAT_GRAYSCALE, Constants.MLIB_FORMAT_GRAYSCALE_ALPHA, Constants.MLIB_FORMAT_BGR, Constants.MLIB_FORMAT_RGB, Constants.MLIB_FORMAT_CMYK } : // baseline new int [] {Constants.MLIB_FORMAT_GRAYSCALE, Constants.MLIB_FORMAT_RGB}; // lossless & LS mediaLibImage mlibImage = getMediaLibImage(renderedImage, param, false, supportedFormats); try { if(mlibImage.getChannels() == 2) { // GRAYSCALE_ALPHA encoder.setType(Encoder.JPEG_TYPE_GRAYSCALE); } else if(mlibImage.getChannels() == 4) { // XXX The selection of CMYK (Adobe transform 0) or // YCCK (Adobe transform 2) should probably be made // on the basis of image metadata passed in so this // code should be modified once the writer supports // image metadata. Until then select CMYK type which // will generate Adobe transform 0 and non-subsampled // data. if(mlibImage.getFormat() == Constants.MLIB_FORMAT_CMYK) { // CMYK encoder.setType(Encoder.JPEG_TYPE_CMYK); } else if(mlibImage.getFormat() == Constants.MLIB_FORMAT_YCCK) { // YCCK encoder.setType(Encoder.JPEG_TYPE_YCCK); } } encoder.encode(stream, mlibImage); } catch(Throwable t) { throw new IIOException("codecLib error", t); } } } /** * This differs from the core JPEG ImageWriteParam in that: * *

*/ final class CLibJPEGImageWriteParam extends ImageWriteParam { private static final float DEFAULT_COMPRESSION_QUALITY = 0.75F; static final String LOSSY_COMPRESSION_TYPE = "JPEG"; static final String LOSSLESS_COMPRESSION_TYPE = "JPEG-LOSSLESS"; static final String LS_COMPRESSION_TYPE = "JPEG-LS"; private static final String[] compressionQualityDescriptions = new String[] { I18N.getString("CLibJPEGImageWriteParam0"), I18N.getString("CLibJPEGImageWriteParam1"), I18N.getString("CLibJPEGImageWriteParam2") }; CLibJPEGImageWriteParam(Locale locale) { super(locale); canWriteCompressed = true; compressionMode = MODE_EXPLICIT; compressionQuality = DEFAULT_COMPRESSION_QUALITY; compressionType = LOSSY_COMPRESSION_TYPE; compressionTypes = new String[] {LOSSY_COMPRESSION_TYPE, LOSSLESS_COMPRESSION_TYPE, LS_COMPRESSION_TYPE}; } public String[] getCompressionQualityDescriptions() { super.getCompressionQualityDescriptions(); // Performs checks. return compressionQualityDescriptions; } public float[] getCompressionQualityValues() { super.getCompressionQualityValues(); // Performs checks. return new float[] { 0.05F, // "Minimum useful" 0.75F, // "Visually lossless" 0.95F }; // "Maximum useful" } public boolean isCompressionLossless() { super.isCompressionLossless(); // Performs checks. return !compressionType.equalsIgnoreCase(LOSSY_COMPRESSION_TYPE); } public void setCompressionMode(int mode) { if(mode == MODE_DISABLED || mode == MODE_COPY_FROM_METADATA) { throw new UnsupportedOperationException ("mode == MODE_DISABLED || mode == MODE_COPY_FROM_METADATA"); } super.setCompressionMode(mode); // This sets the instance variable. } public void unsetCompression() { super.unsetCompression(); // Performs checks. compressionQuality = DEFAULT_COMPRESSION_QUALITY; compressionType = LOSSY_COMPRESSION_TYPE; } } ././@LongLink0000000000000000000000000000015200000000000011563 Lustar rootrootjai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/jpeg/CLibJPEGImageReaderSpi.javajai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/jpeg/CLibJPEGImageReaderSpi0000664000175100017510000001410210423235255032322 0ustar tilletille/* * $RCSfile: CLibJPEGImageReaderSpi.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.4 $ * $Date: 2006-04-24 20:53:01 $ * $State: Exp $ */ package com.sun.media.imageioimpl.plugins.jpeg; import java.util.Arrays; import java.util.Iterator; import java.util.List; import java.util.Locale; import javax.imageio.spi.ImageReaderSpi; import javax.imageio.spi.ServiceRegistry; import javax.imageio.stream.ImageInputStream; import java.io.IOException; import javax.imageio.ImageReader; import javax.imageio.IIOException; import com.sun.media.imageioimpl.common.PackageUtil; import com.sun.media.imageioimpl.common.ImageUtil; public class CLibJPEGImageReaderSpi extends ImageReaderSpi { private static final String[] names = {"jpeg", "JPEG", "jpg", "JPG", "jfif", "JFIF", "jpeg-lossless", "JPEG-LOSSLESS", "jpeg-ls", "JPEG-LS"}; private static final String[] suffixes = {"jpeg", "jpg", "jfif", "jls"}; private static final String[] MIMETypes = {"image/jpeg"}; private static final String readerClassName = "com.sun.media.imageioimpl.plugins.jpeg.CLibJPEGImageReader"; private static final String[] writerSpiNames = { "com.sun.media.imageioimpl.plugins.jpeg.CLibJPEGImageWriterSpi" }; private boolean registered = false; public CLibJPEGImageReaderSpi() { super(PackageUtil.getVendor(), PackageUtil.getVersion(), names, suffixes, MIMETypes, readerClassName, STANDARD_INPUT_TYPE, writerSpiNames, false, // supportsStandardStreamMetadataFormat null, // nativeStreamMetadataFormatName null, // nativeStreamMetadataFormatClassName null, // extraStreamMetadataFormatNames null, // extraStreamMetadataFormatClassNames true, // supportsStandardImageMetadataFormat CLibJPEGMetadata.NATIVE_FORMAT, CLibJPEGMetadata.NATIVE_FORMAT_CLASS, new String[] {CLibJPEGMetadata.TIFF_FORMAT}, new String[] {CLibJPEGMetadata.TIFF_FORMAT_CLASS}); } public void onRegistration(ServiceRegistry registry, Class category) { if (registered) { return; } registered = true; // Branch as a function of codecLib availability. if(!PackageUtil.isCodecLibAvailable()) { // Deregister provider. registry.deregisterServiceProvider(this); } else { List list = ImageUtil.getJDKImageReaderWriterSPI(registry, "JPEG", true); for (int i=0; i= 0xC0) && (byte2 <= 0xC3)) // not progressive, can decode break; int length = iis.read() << 8; length += iis.read(); length -= 2; while (length > 0) length -= iis.skipBytes(length); } while(true); iis.reset(); return true; } public ImageReader createReaderInstance(Object extension) throws IIOException { return new CLibJPEGImageReader(this); } } jai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/jpeg/I18N.java0000664000175100017510000000420710203036165027700 0ustar tilletille/* * $RCSfile: I18N.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.1 $ * $Date: 2005-02-11 05:01:30 $ * $State: Exp $ */ package com.sun.media.imageioimpl.plugins.jpeg; import com.sun.media.imageioimpl.common.I18NImpl; final class I18N extends I18NImpl { static String getString(String key) { return getString("com.sun.media.imageioimpl.plugins.jpeg.I18N", key); } } jai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/jpeg/CLibJPEGMetadata.java0000664000175100017510000020344210665066541032160 0ustar tilletille/* * $RCSfile: CLibJPEGMetadata.java,v $ * * * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.7 $ * $Date: 2007-08-28 18:45:53 $ * $State: Exp $ */ package com.sun.media.imageioimpl.plugins.jpeg; import java.awt.Dimension; import java.awt.Transparency; import java.awt.color.ColorSpace; import java.awt.color.ICC_Profile; import java.awt.image.BufferedImage; import java.awt.image.ColorModel; import java.awt.image.ComponentColorModel; import java.awt.image.DataBuffer; import java.awt.image.DataBufferByte; import java.awt.image.IndexColorModel; import java.awt.image.Raster; import java.awt.image.RenderedImage; import java.awt.image.SampleModel; import java.awt.image.WritableRaster; import java.io.ByteArrayInputStream; import java.io.EOFException; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.nio.ByteOrder; import java.util.ArrayList; import java.util.Arrays; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.SortedMap; import java.util.TreeMap; import javax.imageio.IIOException; import javax.imageio.IIOImage; import javax.imageio.ImageIO; import javax.imageio.ImageReader; import javax.imageio.ImageTypeSpecifier; import javax.imageio.metadata.IIOMetadata; import javax.imageio.metadata.IIOMetadataFormatImpl; import javax.imageio.metadata.IIOMetadataNode; import javax.imageio.metadata.IIOInvalidTreeException; import javax.imageio.plugins.jpeg.JPEGHuffmanTable; import javax.imageio.plugins.jpeg.JPEGQTable; import javax.imageio.stream.ImageInputStream; import javax.imageio.stream.MemoryCacheImageInputStream; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import com.sun.media.imageio.plugins.tiff.BaselineTIFFTagSet; import com.sun.media.imageio.plugins.tiff.EXIFGPSTagSet; import com.sun.media.imageio.plugins.tiff.EXIFInteroperabilityTagSet; import com.sun.media.imageio.plugins.tiff.EXIFParentTIFFTagSet; import com.sun.media.imageio.plugins.tiff.EXIFTIFFTagSet; import com.sun.media.imageio.plugins.tiff.TIFFDirectory; import com.sun.media.imageio.plugins.tiff.TIFFField; import com.sun.media.imageio.plugins.tiff.TIFFTag; import com.sun.media.imageio.plugins.tiff.TIFFTagSet; public class CLibJPEGMetadata extends IIOMetadata { // --- Constants --- static final String NATIVE_FORMAT = "javax_imageio_jpeg_image_1.0"; // XXX Reference to a non-API J2SE class: static final String NATIVE_FORMAT_CLASS = "com.sun.imageio.plugins.jpeg.JPEGImageMetadataFormat"; static final String TIFF_FORMAT = "com_sun_media_imageio_plugins_tiff_image_1.0"; static final String TIFF_FORMAT_CLASS = "com.sun.media.imageioimpl.plugins.tiff.TIFFImageMetadataFormat"; // Marker codes from J2SE in numerically increasing order. /** For temporary use in arithmetic coding */ static final int TEM = 0x01; // Codes 0x02 - 0xBF are reserved // SOF markers for Nondifferential Huffman coding /** Baseline DCT */ static final int SOF0 = 0xC0; /** Extended Sequential DCT */ static final int SOF1 = 0xC1; /** Progressive DCT */ static final int SOF2 = 0xC2; /** Lossless Sequential */ static final int SOF3 = 0xC3; /** Define Huffman Tables */ static final int DHT = 0xC4; // SOF markers for Differential Huffman coding /** Differential Sequential DCT */ static final int SOF5 = 0xC5; /** Differential Progressive DCT */ static final int SOF6 = 0xC6; /** Differential Lossless */ static final int SOF7 = 0xC7; /** Reserved for JPEG extensions */ static final int JPG = 0xC8; // SOF markers for Nondifferential arithmetic coding /** Extended Sequential DCT, Arithmetic coding */ static final int SOF9 = 0xC9; /** Progressive DCT, Arithmetic coding */ static final int SOF10 = 0xCA; /** Lossless Sequential, Arithmetic coding */ static final int SOF11 = 0xCB; /** Define Arithmetic conditioning tables */ static final int DAC = 0xCC; // SOF markers for Differential arithmetic coding /** Differential Sequential DCT, Arithmetic coding */ static final int SOF13 = 0xCD; /** Differential Progressive DCT, Arithmetic coding */ static final int SOF14 = 0xCE; /** Differential Lossless, Arithmetic coding */ static final int SOF15 = 0xCF; // Restart Markers static final int RST0 = 0xD0; static final int RST1 = 0xD1; static final int RST2 = 0xD2; static final int RST3 = 0xD3; static final int RST4 = 0xD4; static final int RST5 = 0xD5; static final int RST6 = 0xD6; static final int RST7 = 0xD7; /** Number of restart markers */ static final int RESTART_RANGE = 8; /** Start of Image */ static final int SOI = 0xD8; /** End of Image */ static final int EOI = 0xD9; /** Start of Scan */ static final int SOS = 0xDA; /** Define Quantisation Tables */ static final int DQT = 0xDB; /** Define Number of lines */ static final int DNL = 0xDC; /** Define Restart Interval */ static final int DRI = 0xDD; /** Define Heirarchical progression */ static final int DHP = 0xDE; /** Expand reference image(s) */ static final int EXP = 0xDF; // Application markers /** APP0 used by JFIF */ static final int APP0 = 0xE0; static final int APP1 = 0xE1; static final int APP2 = 0xE2; static final int APP3 = 0xE3; static final int APP4 = 0xE4; static final int APP5 = 0xE5; static final int APP6 = 0xE6; static final int APP7 = 0xE7; static final int APP8 = 0xE8; static final int APP9 = 0xE9; static final int APP10 = 0xEA; static final int APP11 = 0xEB; static final int APP12 = 0xEC; static final int APP13 = 0xED; /** APP14 used by Adobe */ static final int APP14 = 0xEE; static final int APP15 = 0xEF; // codes 0xF0 to 0xFD are reserved /** Comment marker */ static final int COM = 0xFE; // Marker codes for JPEG-LS /** JPEG-LS SOF marker */ // This was SOF48 in an earlier revision of the JPEG-LS specification. // "55" is the numerical value of SOF55 - SOF0 (= 247 - 192). static final int SOF55 = 0xF7; /** JPEG-LS parameters */ static final int LSE = 0xF2; // Min and max APPn codes. static final int APPN_MIN = APP0; static final int APPN_MAX = APP15; // Min and max contiguous SOFn codes. static final int SOFN_MIN = SOF0; static final int SOFN_MAX = SOF15; // Min and Max RSTn codes. static final int RST_MIN = RST0; static final int RST_MAX = RST7; // Specific segment types defined as (code << 8) | X. static final int APP0_JFIF = (APP0 << 8) | 0; static final int APP0_JFXX = (APP0 << 8) | 1; static final int APP1_EXIF = (APP1 << 8) | 0; static final int APP2_ICC = (APP2 << 8) | 0; static final int APP14_ADOBE = (APP14 << 8) | 0; static final int UNKNOWN_MARKER = 0xffff; static final int SOF_MARKER = (SOF0 << 8) | 0; // Resolution unit types. static final int JFIF_RESUNITS_ASPECT = 0; static final int JFIF_RESUNITS_DPI = 1; static final int JFIF_RESUNITS_DPC = 2; // Thumbnail types static final int THUMBNAIL_JPEG = 0x10; static final int THUMBNAIL_PALETTE = 0x11; static final int THUMBNAIL_RGB = 0x12; // Adobe transform type. static final int ADOBE_TRANSFORM_UNKNOWN = 0; static final int ADOBE_TRANSFORM_YCC = 1; static final int ADOBE_TRANSFORM_YCCK = 2; // Zig-zag to natural re-ordering array. static final int [] zigzag = { 0, 1, 5, 6, 14, 15, 27, 28, 2, 4, 7, 13, 16, 26, 29, 42, 3, 8, 12, 17, 25, 30, 41, 43, 9, 11, 18, 24, 31, 40, 44, 53, 10, 19, 23, 32, 39, 45, 52, 54, 20, 22, 33, 38, 46, 51, 55, 60, 21, 34, 37, 47, 50, 56, 59, 61, 35, 36, 48, 49, 57, 58, 62, 63 }; // --- Static methods --- private static IIOImage getThumbnail(ImageInputStream stream, int len, int thumbnailType, int w, int h) throws IOException { IIOImage result; long startPos = stream.getStreamPosition(); if(thumbnailType == THUMBNAIL_JPEG) { Iterator readers = ImageIO.getImageReaders(stream); if(readers == null || !readers.hasNext()) return null; ImageReader reader = (ImageReader)readers.next(); reader.setInput(stream); BufferedImage image = reader.read(0, null); IIOMetadata metadata = null; try { metadata = reader.getImageMetadata(0); } catch(Exception e) { // Ignore it } result = new IIOImage(image, null, metadata); } else { int numBands; ColorModel cm; if(thumbnailType == THUMBNAIL_PALETTE) { if(len < 768 + w*h) { return null; } numBands = 1; byte[] palette = new byte[768]; stream.readFully(palette); byte[] r = new byte[256]; byte[] g = new byte[256]; byte[] b = new byte[256]; for(int i = 0, off = 0; i < 256; i++) { r[i] = palette[off++]; g[i] = palette[off++]; b[i] = palette[off++]; } cm = new IndexColorModel(8, 256, r, g, b); } else { if(len < 3*w*h) { return null; } numBands = 3; ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_sRGB); cm = new ComponentColorModel(cs, false, false, Transparency.OPAQUE, DataBuffer.TYPE_BYTE); } byte[] data = new byte[w*h*numBands]; stream.readFully(data); DataBufferByte db = new DataBufferByte(data, data.length); WritableRaster wr = Raster.createInterleavedRaster(db, w, h, w*numBands, numBands, new int[] {0, 1, 2}, null); BufferedImage image = new BufferedImage(cm, wr, false, null); result = new IIOImage(image, null, null); } stream.seek(startPos + len); return result; } // --- Instance variables --- /** Whether the object may be edited. */ private boolean isReadOnly = true; // APP0 JFIF marker segment parameters. boolean app0JFIFPresent; int majorVersion = 1; int minorVersion = 2; int resUnits; // (0 = aspect ratio; 1 = dots/inch; 2 = dots/cm) int Xdensity = 1; int Ydensity = 1; int thumbWidth = 0; int thumbHeight = 0; BufferedImage jfifThumbnail; // APP0 JFIF thumbnail(s). boolean app0JFXXPresent; List extensionCodes; // Integers 0x10, 0x11, 0x12 List jfxxThumbnails; // IIOImages // APP2 ICC_PROFILE marker segment parameters. boolean app2ICCPresent; ICC_Profile profile = null; // DQT marker segment parameters. boolean dqtPresent; List qtables; // Each element is a List of QTables // DHT marker segment parameters. boolean dhtPresent; List htables; // Each element is a List of HuffmanTables // DRI marker segment parameters. boolean driPresent; int driInterval; // COM marker segment parameters. boolean comPresent; List comments; // byte[]s // Unknown marker segment parameters. boolean unknownPresent; List markerTags; // Integers List unknownData; // byte[] (NB: 'length' parameter is array length) // APP14 Adobe marker segment parameters. boolean app14AdobePresent; int version = 100; int flags0 = 0; int flags1 = 0; int transform; // 0 = Unknown, 1 = YCbCr, 2 = YCCK // SOF marker segment parameters. boolean sofPresent; int sofProcess; int samplePrecision = 8; int numLines; int samplesPerLine; int numFrameComponents; int[] componentId; int[] hSamplingFactor; int[] vSamplingFactor; int[] qtableSelector; // SOS marker segment parameters. boolean sosPresent; int numScanComponents; int[] componentSelector; int[] dcHuffTable; int[] acHuffTable; int startSpectralSelection; int endSpectralSelection; int approxHigh; int approxLow; // Embedded TIFF stream from EXIF segment. byte[] exifData = null; /** Marker codes in the order encountered. */ private List markers = null; // List of Integer // Standard metadata variables. private boolean hasAlpha = false; // Agregated list of thumbnails: JFIF > JFXX > EXIF. private boolean thumbnailsInitialized = false; private List thumbnails = new ArrayList(); CLibJPEGMetadata() { super(true, NATIVE_FORMAT, NATIVE_FORMAT_CLASS, new String[] {TIFF_FORMAT}, new String[] {TIFF_FORMAT_CLASS}); this.isReadOnly = isReadOnly; } CLibJPEGMetadata(ImageInputStream stream) throws IIOException { this(); try { initializeFromStream(stream); } catch(IOException e) { throw new IIOException("Cannot initialize JPEG metadata!", e); } } private class QTable { private static final int QTABLE_SIZE = 64; int elementPrecision; int tableID; JPEGQTable table; int length; QTable(ImageInputStream stream) throws IOException { elementPrecision = (int)stream.readBits(4); tableID = (int)stream.readBits(4); byte[] tmp = new byte[QTABLE_SIZE]; stream.readFully(tmp); int[] data = new int[QTABLE_SIZE]; for (int i = 0; i < QTABLE_SIZE; i++) { data[i] = tmp[zigzag[i]] & 0xff; } table = new JPEGQTable(data); length = data.length + 1; } } private class HuffmanTable { private static final int NUM_LENGTHS = 16; int tableClass; int tableID; JPEGHuffmanTable table; int length; HuffmanTable(ImageInputStream stream) throws IOException { tableClass = (int)stream.readBits(4); tableID = (int)stream.readBits(4); short[] lengths = new short[NUM_LENGTHS]; for (int i = 0; i < NUM_LENGTHS; i++) { lengths[i] = (short)stream.read(); } int numValues = 0; for (int i = 0; i < NUM_LENGTHS; i++) { numValues += lengths[i]; } short[] values = new short[numValues]; for (int i = 0; i < numValues; i++) { values[i] = (short)stream.read(); } table = new JPEGHuffmanTable(lengths, values); length = 1 + NUM_LENGTHS + values.length; } } private synchronized void initializeFromStream(ImageInputStream iis) throws IOException { iis.mark(); iis.setByteOrder(ByteOrder.BIG_ENDIAN); markers = new ArrayList(); boolean isICCProfileValid = true; int numICCProfileChunks = 0; long[] iccProfileChunkOffsets = null; int[] iccProfileChunkLengths = null; while(true) { try { // 0xff denotes a potential marker. if(iis.read() == 0xff) { // Get next byte. int code = iis.read(); // Is a marker if and only if code not in {0x00, 0xff}. // Continue to next marker if this is not a marker or if // it is an empty marker. if(code == 0x00 || code == 0xff || code == SOI || code == TEM || (code >= RST_MIN && code <= RST_MAX)) { continue; } // If at the end, quit. if(code == EOI) { break; } // Get the content length. int dataLength = iis.readUnsignedShort() - 2; if(APPN_MIN <= code && code <= APPN_MAX) { long pos = iis.getStreamPosition(); boolean appnAdded = false; switch(code) { case APP0: if(dataLength >= 5) { byte[] b = new byte[5]; iis.readFully(b); String id = new String(b); if(id.startsWith("JFIF") && !app0JFIFPresent) { app0JFIFPresent = true; markers.add(new Integer(APP0_JFIF)); majorVersion = iis.read(); minorVersion = iis.read(); resUnits = iis.read(); Xdensity = iis.readUnsignedShort(); Ydensity = iis.readUnsignedShort(); thumbWidth = iis.read(); thumbHeight = iis.read(); if(thumbWidth > 0 && thumbHeight > 0) { IIOImage imiio = getThumbnail(iis, dataLength - 14, THUMBNAIL_RGB, thumbWidth, thumbHeight); if(imiio != null) { jfifThumbnail = (BufferedImage) imiio.getRenderedImage(); } } appnAdded = true; } else if(id.startsWith("JFXX")) { if(!app0JFXXPresent) { extensionCodes = new ArrayList(1); jfxxThumbnails = new ArrayList(1); app0JFXXPresent = true; } markers.add(new Integer(APP0_JFXX)); int extCode = iis.read(); extensionCodes.add(new Integer(extCode)); int w = 0, h = 0, offset = 6; if(extCode != THUMBNAIL_JPEG) { w = iis.read(); h = iis.read(); offset += 2; } IIOImage imiio = getThumbnail(iis, dataLength - offset, extCode, w, h); if(imiio != null) { jfxxThumbnails.add(imiio); } appnAdded = true; } } break; case APP1: if(dataLength >= 6) { byte[] b = new byte[6]; iis.readFully(b); if(b[0] == (byte)'E' && b[1] == (byte)'x' && b[2] == (byte)'i' && b[3] == (byte)'f' && b[4] == (byte)0 && b[5] == (byte)0) { exifData = new byte[dataLength - 6]; iis.readFully(exifData); } } case APP2: if(dataLength >= 12) { byte[] b = new byte[12]; iis.readFully(b); String id = new String(b); if(id.startsWith("ICC_PROFILE")) { if(!isICCProfileValid) { iis.skipBytes(dataLength - 12); continue; } int chunkNum = iis.read(); int numChunks = iis.read(); if(numChunks == 0 || chunkNum == 0 || chunkNum > numChunks || (app2ICCPresent && (numChunks != numICCProfileChunks || iccProfileChunkOffsets[chunkNum] != 0L))) { isICCProfileValid = false; iis.skipBytes(dataLength - 14); continue; } if(!app2ICCPresent) { app2ICCPresent = true; // Only flag one marker even though // multiple may be present. markers.add(new Integer(APP2_ICC)); numICCProfileChunks = numChunks; if(numChunks == 1) { b = new byte[dataLength - 14]; iis.readFully(b); profile = ICC_Profile.getInstance(b); } else { iccProfileChunkOffsets = new long[numChunks + 1]; iccProfileChunkLengths = new int[numChunks + 1]; iccProfileChunkOffsets[chunkNum] = iis.getStreamPosition(); iccProfileChunkLengths[chunkNum] = dataLength - 14; iis.skipBytes(dataLength - 14); } } else { iccProfileChunkOffsets[chunkNum] = iis.getStreamPosition(); iccProfileChunkLengths[chunkNum] = dataLength - 14; iis.skipBytes(dataLength - 14); } appnAdded = true; } } break; case APP14: if(dataLength >= 5) { byte[] b = new byte[5]; iis.readFully(b); String id = new String(b); if(id.startsWith("Adobe") && !app14AdobePresent) { // Adobe segment app14AdobePresent = true; markers.add(new Integer(APP14_ADOBE)); version = iis.readUnsignedShort(); flags0 = iis.readUnsignedShort(); flags1 = iis.readUnsignedShort(); transform = iis.read(); iis.skipBytes(dataLength - 12); appnAdded = true; } } break; default: appnAdded = false; break; } if(!appnAdded) { iis.seek(pos); addUnknownMarkerSegment(iis, code, dataLength); } } else if(code == DQT) { if(!dqtPresent) { dqtPresent = true; qtables = new ArrayList(1); } markers.add(new Integer(DQT)); List l = new ArrayList(1); do { QTable t = new QTable(iis); l.add(t); dataLength -= t.length; } while(dataLength > 0); qtables.add(l); } else if(code == DHT) { if(!dhtPresent) { dhtPresent = true; htables = new ArrayList(1); } markers.add(new Integer(DHT)); List l = new ArrayList(1); do { HuffmanTable t = new HuffmanTable(iis); l.add(t); dataLength -= t.length; } while(dataLength > 0); htables.add(l); } else if(code == DRI) { if(!driPresent) { driPresent = true; } markers.add(new Integer(DRI)); driInterval = iis.readUnsignedShort(); } else if(code == COM) { if(!comPresent) { comPresent = true; comments = new ArrayList(1); } markers.add(new Integer(COM)); byte[] b = new byte[dataLength]; iis.readFully(b); comments.add(b); } else if((code >= SOFN_MIN && code <= SOFN_MAX) || code == SOF55) { // SOFn if(!sofPresent) { sofPresent = true; sofProcess = code - SOFN_MIN; samplePrecision = iis.read(); numLines = iis.readUnsignedShort(); samplesPerLine = iis.readUnsignedShort(); numFrameComponents = iis.read(); componentId = new int[numFrameComponents]; hSamplingFactor = new int[numFrameComponents]; vSamplingFactor = new int[numFrameComponents]; qtableSelector = new int[numFrameComponents]; for(int i = 0; i < numFrameComponents; i++) { componentId[i] = iis.read(); hSamplingFactor[i] = (int)iis.readBits(4); vSamplingFactor[i] = (int)iis.readBits(4); qtableSelector[i] = iis.read(); } markers.add(new Integer(SOF_MARKER)); } } else if(code == SOS) { if(!sosPresent) { sosPresent = true; numScanComponents = iis.read(); componentSelector = new int[numScanComponents]; dcHuffTable = new int[numScanComponents]; acHuffTable = new int[numScanComponents]; for(int i = 0; i < numScanComponents; i++) { componentSelector[i] = iis.read(); dcHuffTable[i] = (int)iis.readBits(4); acHuffTable[i] = (int)iis.readBits(4); } startSpectralSelection = iis.read(); endSpectralSelection = iis.read(); approxHigh = (int)iis.readBits(4); approxLow = (int)iis.readBits(4); markers.add(new Integer(SOS)); } break; } else { // Any other marker addUnknownMarkerSegment(iis, code, dataLength); } } } catch(EOFException eofe) { // XXX Should this be caught? break; } } if(app2ICCPresent && isICCProfileValid && profile == null) { int profileDataLength = 0; for(int i = 1; i <= numICCProfileChunks; i++) { if(iccProfileChunkOffsets[i] == 0L) { isICCProfileValid = false; break; } profileDataLength += iccProfileChunkLengths[i]; } if(isICCProfileValid) { byte[] b = new byte[profileDataLength]; int off = 0; for(int i = 1; i <= numICCProfileChunks; i++) { iis.seek(iccProfileChunkOffsets[i]); iis.read(b, off, iccProfileChunkLengths[i]); off += iccProfileChunkLengths[i]; } profile = ICC_Profile.getInstance(b); } } iis.reset(); } private void addUnknownMarkerSegment(ImageInputStream stream, int code, int len) throws IOException { if(!unknownPresent) { unknownPresent = true; markerTags = new ArrayList(1); unknownData = new ArrayList(1); } markerTags.add(new Integer(code)); byte[] b = new byte[len]; stream.readFully(b); unknownData.add(b); markers.add(new Integer(UNKNOWN_MARKER)); } public boolean isReadOnly() { return isReadOnly; } public Node getAsTree(String formatName) { if (formatName.equals(nativeMetadataFormatName)) { return getNativeTree(); } else if (formatName.equals (IIOMetadataFormatImpl.standardMetadataFormatName)) { return getStandardTree(); } else if(formatName.equals(TIFF_FORMAT)) { return getTIFFTree(); } else { throw new IllegalArgumentException("Not a recognized format!"); } } public void mergeTree(String formatName, Node root) throws IIOInvalidTreeException { if(isReadOnly) { throw new IllegalStateException("isReadOnly() == true!"); } } public void reset() { if(isReadOnly) { throw new IllegalStateException("isReadOnly() == true!"); } } // Native tree method. private Node getNativeTree() { int jfxxIndex = 0; int dqtIndex = 0; int dhtIndex = 0; int comIndex = 0; int unknownIndex = 0; IIOMetadataNode root = new IIOMetadataNode(nativeMetadataFormatName); IIOMetadataNode JPEGvariety = new IIOMetadataNode("JPEGvariety"); root.appendChild(JPEGvariety); IIOMetadataNode markerSequence = new IIOMetadataNode("markerSequence"); root.appendChild(markerSequence); IIOMetadataNode app0JFIF = null; if(app0JFIFPresent || app0JFXXPresent || app2ICCPresent) { app0JFIF = new IIOMetadataNode("app0JFIF"); app0JFIF.setAttribute("majorVersion", Integer.toString(majorVersion)); app0JFIF.setAttribute("minorVersion", Integer.toString(minorVersion)); app0JFIF.setAttribute("resUnits", Integer.toString(resUnits)); app0JFIF.setAttribute("Xdensity", Integer.toString(Xdensity)); app0JFIF.setAttribute("Ydensity", Integer.toString(Ydensity)); app0JFIF.setAttribute("thumbWidth", Integer.toString(thumbWidth)); app0JFIF.setAttribute("thumbHeight", Integer.toString(thumbHeight)); JPEGvariety.appendChild(app0JFIF); } IIOMetadataNode JFXX = null; if(app0JFXXPresent) { JFXX = new IIOMetadataNode("JFXX"); app0JFIF.appendChild(JFXX); } Iterator markerIter = markers.iterator(); while(markerIter.hasNext()) { int marker = ((Integer)markerIter.next()).intValue(); switch(marker) { case APP0_JFIF: // Do nothing: already handled above. break; case APP0_JFXX: IIOMetadataNode app0JFXX = new IIOMetadataNode("app0JFXX"); Integer extensionCode = (Integer)extensionCodes.get(jfxxIndex); app0JFXX.setAttribute("extensionCode", extensionCode.toString()); IIOMetadataNode JFIFthumb = null; switch(extensionCode.intValue()) { case THUMBNAIL_JPEG: JFIFthumb = new IIOMetadataNode("JFIFthumbJPEG"); break; case THUMBNAIL_PALETTE: JFIFthumb = new IIOMetadataNode("JFIFthumbPalette"); break; case THUMBNAIL_RGB: JFIFthumb = new IIOMetadataNode("JFIFthumbRGB"); break; default: // No JFIFthumb node will be appended. } if(JFIFthumb != null) { IIOImage img = (IIOImage)jfxxThumbnails.get(jfxxIndex++); if(extensionCode.intValue() == THUMBNAIL_JPEG) { IIOMetadata thumbMetadata = img.getMetadata(); if(thumbMetadata != null) { Node thumbTree = thumbMetadata.getAsTree(nativeMetadataFormatName); if(thumbTree instanceof IIOMetadataNode) { IIOMetadataNode elt = (IIOMetadataNode)thumbTree; NodeList elts = elt.getElementsByTagName("markerSequence"); if(elts.getLength() > 0) { JFIFthumb.appendChild(elts.item(0)); } } } } else { BufferedImage thumb = (BufferedImage)img.getRenderedImage(); JFIFthumb.setAttribute("thumbWidth", Integer.toString(thumb.getWidth())); JFIFthumb.setAttribute("thumbHeight", Integer.toString(thumb.getHeight())); } // Add thumbnail as a user object even though not in // metadata specification. JFIFthumb.setUserObject(img); app0JFXX.appendChild(JFIFthumb); } JFXX.appendChild(app0JFXX); break; case APP2_ICC: IIOMetadataNode app2ICC = new IIOMetadataNode("app2ICC"); app2ICC.setUserObject(profile); app0JFIF.appendChild(app2ICC); break; case DQT: IIOMetadataNode dqt = new IIOMetadataNode("dqt"); List tables = (List)qtables.get(dqtIndex++); int numTables = tables.size(); for(int j = 0; j < numTables; j++) { IIOMetadataNode dqtable = new IIOMetadataNode("dqtable"); QTable t = (QTable)tables.get(j); dqtable.setAttribute("elementPrecision", Integer.toString(t.elementPrecision)); dqtable.setAttribute("qtableId", Integer.toString(t.tableID)); dqtable.setUserObject(t.table); dqt.appendChild(dqtable); } markerSequence.appendChild(dqt); break; case DHT: IIOMetadataNode dht = new IIOMetadataNode("dht"); tables = (List)htables.get(dhtIndex++); numTables = tables.size(); for(int j = 0; j < numTables; j++) { IIOMetadataNode dhtable = new IIOMetadataNode("dhtable"); HuffmanTable t = (HuffmanTable)tables.get(j); dhtable.setAttribute("class", Integer.toString(t.tableClass)); dhtable.setAttribute("htableId", Integer.toString(t.tableID)); dhtable.setUserObject(t.table); dht.appendChild(dhtable); } markerSequence.appendChild(dht); break; case DRI: IIOMetadataNode dri = new IIOMetadataNode("dri"); dri.setAttribute("interval", Integer.toString(driInterval)); markerSequence.appendChild(dri); break; case COM: IIOMetadataNode com = new IIOMetadataNode("com"); com.setUserObject(comments.get(comIndex++)); markerSequence.appendChild(com); break; case UNKNOWN_MARKER: IIOMetadataNode unknown = new IIOMetadataNode("unknown"); Integer markerTag = (Integer)markerTags.get(unknownIndex); unknown.setAttribute("MarkerTag", markerTag.toString()); unknown.setUserObject(unknownData.get(unknownIndex++)); markerSequence.appendChild(unknown); break; case APP14_ADOBE: IIOMetadataNode app14Adobe = new IIOMetadataNode("app14Adobe"); app14Adobe.setAttribute("version", Integer.toString(version)); app14Adobe.setAttribute("flags0", Integer.toString(flags0)); app14Adobe.setAttribute("flags1", Integer.toString(flags1)); app14Adobe.setAttribute("transform", Integer.toString(transform)); markerSequence.appendChild(app14Adobe); break; case SOF_MARKER: IIOMetadataNode sof = new IIOMetadataNode("sof"); sof.setAttribute("process", Integer.toString(sofProcess)); sof.setAttribute("samplePrecision", Integer.toString(samplePrecision)); sof.setAttribute("numLines", Integer.toString(numLines)); sof.setAttribute("samplesPerLine", Integer.toString(samplesPerLine)); sof.setAttribute("numFrameComponents", Integer.toString(numFrameComponents)); for(int i = 0; i < numFrameComponents; i++) { IIOMetadataNode componentSpec = new IIOMetadataNode("componentSpec"); componentSpec.setAttribute("componentId", Integer.toString(componentId[i])); componentSpec.setAttribute("HsamplingFactor", Integer.toString(hSamplingFactor[i])); componentSpec.setAttribute("VsamplingFactor", Integer.toString(vSamplingFactor[i])); componentSpec.setAttribute("QtableSelector", Integer.toString(qtableSelector[i])); sof.appendChild(componentSpec); } markerSequence.appendChild(sof); break; case SOS: IIOMetadataNode sos = new IIOMetadataNode("sos"); sos.setAttribute("numScanComponents", Integer.toString(numScanComponents)); sos.setAttribute("startSpectralSelection", Integer.toString(startSpectralSelection)); sos.setAttribute("endSpectralSelection", Integer.toString(endSpectralSelection)); sos.setAttribute("approxHigh", Integer.toString(approxHigh)); sos.setAttribute("approxLow", Integer.toString(approxLow)); for(int i = 0; i < numScanComponents; i++) { IIOMetadataNode scanComponentSpec = new IIOMetadataNode("scanComponentSpec"); scanComponentSpec.setAttribute("componentSelector", Integer.toString(componentSelector[i])); scanComponentSpec.setAttribute("dcHuffTable", Integer.toString(dcHuffTable[i])); scanComponentSpec.setAttribute("acHuffTable", Integer.toString(acHuffTable[i])); sos.appendChild(scanComponentSpec); } markerSequence.appendChild(sos); break; } } return root; } // Standard tree node methods protected IIOMetadataNode getStandardChromaNode() { if(!sofPresent) { // No image, so no chroma return null; } IIOMetadataNode chroma = new IIOMetadataNode("Chroma"); IIOMetadataNode csType = new IIOMetadataNode("ColorSpaceType"); chroma.appendChild(csType); IIOMetadataNode numChanNode = new IIOMetadataNode("NumChannels"); chroma.appendChild(numChanNode); numChanNode.setAttribute("value", Integer.toString(numFrameComponents)); // Check JFIF presence. if(app0JFIFPresent) { if(numFrameComponents == 1) { csType.setAttribute("name", "GRAY"); } else { csType.setAttribute("name", "YCbCr"); } return chroma; } // How about an Adobe marker segment? if(app14AdobePresent){ switch(transform) { case ADOBE_TRANSFORM_YCCK: // YCCK csType.setAttribute("name", "YCCK"); break; case ADOBE_TRANSFORM_YCC: // YCC csType.setAttribute("name", "YCbCr"); break; case ADOBE_TRANSFORM_UNKNOWN: // Unknown if(numFrameComponents == 3) { csType.setAttribute("name", "RGB"); } else if(numFrameComponents == 4) { csType.setAttribute("name", "CMYK"); } break; } return chroma; } // Initially assume no opacity. hasAlpha = false; // Neither marker. Check components if(numFrameComponents < 3) { csType.setAttribute("name", "GRAY"); if(numFrameComponents == 2) { hasAlpha = true; } return chroma; } boolean idsAreJFIF = true; for(int i = 0; i < componentId.length; i++) { int id = componentId[i]; if((id < 1) || (id >= componentId.length)) { idsAreJFIF = false; } } if(idsAreJFIF) { csType.setAttribute("name", "YCbCr"); if(numFrameComponents == 4) { hasAlpha = true; } return chroma; } // Check against the letters if(componentId[0] == 'R' && componentId[1] == 'G' && componentId[2] == 'B'){ csType.setAttribute("name", "RGB"); if(numFrameComponents == 4 && componentId[3] == 'A') { hasAlpha = true; } return chroma; } if(componentId[0] == 'Y' && componentId[1] == 'C' && componentId[2] == 'c'){ csType.setAttribute("name", "PhotoYCC"); if(numFrameComponents == 4 && componentId[3] == 'A') { hasAlpha = true; } return chroma; } // Finally, 3-channel subsampled are YCbCr, unsubsampled are RGB // 4-channel subsampled are YCbCrA, unsubsampled are CMYK boolean subsampled = false; int hfactor = hSamplingFactor[0]; int vfactor = vSamplingFactor[0]; for(int i = 1; i < componentId.length; i++) { if(hSamplingFactor[i] != hfactor || vSamplingFactor[i] != vfactor){ subsampled = true; break; } } if(subsampled) { csType.setAttribute("name", "YCbCr"); if(numFrameComponents == 4) { hasAlpha = true; } return chroma; } // Not subsampled. numFrameComponents < 3 is taken care of above if(numFrameComponents == 3) { csType.setAttribute("name", "RGB"); } else { csType.setAttribute("name", "CMYK"); } return chroma; } protected IIOMetadataNode getStandardCompressionNode() { IIOMetadataNode compression = null; if(sofPresent || sosPresent) { compression = new IIOMetadataNode("Compression"); if(sofPresent) { // Process 55 is JPEG-LS, others are lossless JPEG. boolean isLossless = sofProcess == 3 || sofProcess == 7 || sofProcess == 11 || sofProcess == 15 || sofProcess == 55; // CompressionTypeName IIOMetadataNode name = new IIOMetadataNode("CompressionTypeName"); String compressionType = isLossless ? (sofProcess == 55 ? "JPEG-LS" : "JPEG-LOSSLESS") : "JPEG"; name.setAttribute("value", compressionType); compression.appendChild(name); // Lossless - false IIOMetadataNode lossless = new IIOMetadataNode("Lossless"); lossless.setAttribute("value", isLossless ? "true" : "false"); compression.appendChild(lossless); } if(sosPresent) { IIOMetadataNode prog = new IIOMetadataNode("NumProgressiveScans"); prog.setAttribute("value", "1"); compression.appendChild(prog); } } return compression; } protected IIOMetadataNode getStandardDimensionNode() { IIOMetadataNode dim = new IIOMetadataNode("Dimension"); IIOMetadataNode orient = new IIOMetadataNode("ImageOrientation"); orient.setAttribute("value", "normal"); dim.appendChild(orient); if(app0JFIFPresent) { float aspectRatio; if(resUnits == JFIF_RESUNITS_ASPECT) { // Aspect ratio. aspectRatio = (float)Xdensity/(float)Ydensity; } else { // Density. aspectRatio = (float)Ydensity/(float)Xdensity; } IIOMetadataNode aspect = new IIOMetadataNode("PixelAspectRatio"); aspect.setAttribute("value", Float.toString(aspectRatio)); dim.insertBefore(aspect, orient); if(resUnits != JFIF_RESUNITS_ASPECT) { // 1 == dpi, 2 == dpc float scale = (resUnits == JFIF_RESUNITS_DPI) ? 25.4F : 10.0F; IIOMetadataNode horiz = new IIOMetadataNode("HorizontalPixelSize"); horiz.setAttribute("value", Float.toString(scale/Xdensity)); dim.appendChild(horiz); IIOMetadataNode vert = new IIOMetadataNode("VerticalPixelSize"); vert.setAttribute("value", Float.toString(scale/Ydensity)); dim.appendChild(vert); } } return dim; } protected IIOMetadataNode getStandardTextNode() { IIOMetadataNode text = null; if(comPresent) { text = new IIOMetadataNode("Text"); Iterator iter = comments.iterator(); while (iter.hasNext()) { IIOMetadataNode entry = new IIOMetadataNode("TextEntry"); entry.setAttribute("keyword", "comment"); byte[] data = (byte[])iter.next(); try { entry.setAttribute("value", new String(data, "ISO-8859-1")); } catch(UnsupportedEncodingException e) { entry.setAttribute("value", new String(data)); } text.appendChild(entry); } } return text; } // This method assumes that getStandardChromaNode() has already been // called to initialize hasAlpha. protected IIOMetadataNode getStandardTransparencyNode() { IIOMetadataNode trans = null; if (hasAlpha == true) { trans = new IIOMetadataNode("Transparency"); IIOMetadataNode alpha = new IIOMetadataNode("Alpha"); alpha.setAttribute("value", "nonpremultiplied"); // Always assume trans.appendChild(alpha); } return trans; } // TIFF tree method private Node getTIFFTree() { String metadataName = TIFF_FORMAT; BaselineTIFFTagSet base = BaselineTIFFTagSet.getInstance(); TIFFDirectory dir = new TIFFDirectory(new TIFFTagSet[] { base, EXIFParentTIFFTagSet.getInstance() }, null); if(sofPresent) { // sofProcess -> Compression ? int compression = BaselineTIFFTagSet.COMPRESSION_JPEG; TIFFField compressionField = new TIFFField(base.getTag(BaselineTIFFTagSet.TAG_COMPRESSION), compression); dir.addTIFFField(compressionField); // samplePrecision -> BitsPerSample char[] bitsPerSample = new char[numFrameComponents]; Arrays.fill(bitsPerSample, (char)(samplePrecision & 0xff)); TIFFField bitsPerSampleField = new TIFFField( base.getTag(BaselineTIFFTagSet.TAG_BITS_PER_SAMPLE), TIFFTag.TIFF_SHORT, bitsPerSample.length, bitsPerSample); dir.addTIFFField(bitsPerSampleField); // numLines -> ImageLength TIFFField imageLengthField = new TIFFField(base.getTag(BaselineTIFFTagSet.TAG_IMAGE_LENGTH), numLines); dir.addTIFFField(imageLengthField); // samplesPerLine -> ImageWidth TIFFField imageWidthField = new TIFFField(base.getTag(BaselineTIFFTagSet.TAG_IMAGE_WIDTH), samplesPerLine); dir.addTIFFField(imageWidthField); // numFrameComponents -> SamplesPerPixel TIFFField samplesPerPixelField = new TIFFField(base.getTag(BaselineTIFFTagSet.TAG_SAMPLES_PER_PIXEL), numFrameComponents); dir.addTIFFField(samplesPerPixelField); // componentId -> PhotometricInterpretation + ExtraSamples IIOMetadataNode chroma = getStandardChromaNode(); if(chroma != null) { IIOMetadataNode csType = (IIOMetadataNode)chroma.getElementsByTagName("ColorSpaceType").item(0); String name = csType.getAttribute("name"); int photometricInterpretation = -1; if(name.equals("GRAY")) { photometricInterpretation = BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_BLACK_IS_ZERO; } else if(name.equals("YCbCr") || name.equals("PhotoYCC")) { // NOTE: PhotoYCC -> YCbCr photometricInterpretation = BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_Y_CB_CR; } else if(name.equals("RGB")) { photometricInterpretation = BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_RGB; } else if(name.equals("CMYK") || name.equals("YCCK")) { // NOTE: YCCK -> CMYK photometricInterpretation = BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_CMYK; } if(photometricInterpretation != -1) { TIFFField photometricInterpretationField = new TIFFField(base.getTag(BaselineTIFFTagSet.TAG_PHOTOMETRIC_INTERPRETATION), photometricInterpretation); dir.addTIFFField(photometricInterpretationField); } if(hasAlpha) { char[] extraSamples = new char[] {BaselineTIFFTagSet.EXTRA_SAMPLES_ASSOCIATED_ALPHA}; TIFFField extraSamplesField = new TIFFField( base.getTag(BaselineTIFFTagSet.TAG_EXTRA_SAMPLES), TIFFTag.TIFF_SHORT, extraSamples.length, extraSamples); dir.addTIFFField(extraSamplesField); } } // chroma != null } // sofPresent // JFIF APP0 -> Resolution fields. if(app0JFIFPresent) { long[][] xResolution = new long[][] {{Xdensity, 1}}; TIFFField XResolutionField = new TIFFField(base.getTag(BaselineTIFFTagSet.TAG_X_RESOLUTION), TIFFTag.TIFF_RATIONAL, 1, xResolution); dir.addTIFFField(XResolutionField); long[][] yResolution = new long[][] {{Ydensity, 1}}; TIFFField YResolutionField = new TIFFField(base.getTag(BaselineTIFFTagSet.TAG_Y_RESOLUTION), TIFFTag.TIFF_RATIONAL, 1, yResolution); dir.addTIFFField(YResolutionField); int resolutionUnit = BaselineTIFFTagSet.RESOLUTION_UNIT_NONE; switch(resUnits) { case JFIF_RESUNITS_ASPECT: resolutionUnit = BaselineTIFFTagSet.RESOLUTION_UNIT_NONE; case JFIF_RESUNITS_DPI: resolutionUnit = BaselineTIFFTagSet.RESOLUTION_UNIT_INCH; break; case JFIF_RESUNITS_DPC: resolutionUnit = BaselineTIFFTagSet.RESOLUTION_UNIT_CENTIMETER; break; } TIFFField ResolutionUnitField = new TIFFField(base.getTag (BaselineTIFFTagSet.TAG_RESOLUTION_UNIT), resolutionUnit); dir.addTIFFField(ResolutionUnitField); } // DQT + DHT -> JPEGTables. byte[] jpegTablesData = null; if(dqtPresent || dqtPresent) { // Determine length of JPEGTables data. int jpegTablesLength = 2; // SOI if(dqtPresent) { Iterator dqts = qtables.iterator(); while(dqts.hasNext()) { Iterator qtiter = ((List)dqts.next()).iterator(); while(qtiter.hasNext()) { QTable qt = (QTable)qtiter.next(); jpegTablesLength += 4 + qt.length; } } } if(dhtPresent) { Iterator dhts = htables.iterator(); while(dhts.hasNext()) { Iterator htiter = ((List)dhts.next()).iterator(); while(htiter.hasNext()) { HuffmanTable ht = (HuffmanTable)htiter.next(); jpegTablesLength += 4 + ht.length; } } } jpegTablesLength += 2; // EOI // Allocate space. jpegTablesData = new byte[jpegTablesLength]; // SOI jpegTablesData[0] = (byte)0xff; jpegTablesData[1] = (byte)SOI; int jpoff = 2; if(dqtPresent) { Iterator dqts = qtables.iterator(); while(dqts.hasNext()) { Iterator qtiter = ((List)dqts.next()).iterator(); while(qtiter.hasNext()) { jpegTablesData[jpoff++] = (byte)0xff; jpegTablesData[jpoff++] = (byte)DQT; QTable qt = (QTable)qtiter.next(); int qtlength = qt.length + 2; jpegTablesData[jpoff++] = (byte)((qtlength & 0xff00) >> 8); jpegTablesData[jpoff++] = (byte)(qtlength & 0xff); jpegTablesData[jpoff++] = (byte)(((qt.elementPrecision & 0xf0) << 4) | (qt.tableID & 0x0f)); int[] table = qt.table.getTable(); int qlen = table.length; for(int i = 0; i < qlen; i++) { jpegTablesData[jpoff + zigzag[i]] = (byte)table[i]; } jpoff += qlen; } } } if(dhtPresent) { Iterator dhts = htables.iterator(); while(dhts.hasNext()) { Iterator htiter = ((List)dhts.next()).iterator(); while(htiter.hasNext()) { jpegTablesData[jpoff++] = (byte)0xff; jpegTablesData[jpoff++] = (byte)DHT; HuffmanTable ht = (HuffmanTable)htiter.next(); int htlength = ht.length + 2; jpegTablesData[jpoff++] = (byte)((htlength & 0xff00) >> 8); jpegTablesData[jpoff++] = (byte)(htlength & 0xff); jpegTablesData[jpoff++] = (byte)(((ht.tableClass & 0x0f) << 4) | (ht.tableID & 0x0f)); short[] lengths = ht.table.getLengths(); int numLengths = lengths.length; for(int i = 0; i < numLengths; i++) { jpegTablesData[jpoff++] = (byte)lengths[i]; } short[] values = ht.table.getValues(); int numValues = values.length; for(int i = 0; i < numValues; i++) { jpegTablesData[jpoff++] = (byte)values[i]; } } } } jpegTablesData[jpoff++] = (byte)0xff; jpegTablesData[jpoff] = (byte)EOI; } if(jpegTablesData != null) { TIFFField JPEGTablesField = new TIFFField(base.getTag(BaselineTIFFTagSet.TAG_JPEG_TABLES), TIFFTag.TIFF_UNDEFINED, jpegTablesData.length, jpegTablesData); dir.addTIFFField(JPEGTablesField); } IIOMetadata tiffMetadata = dir.getAsMetadata(); if(exifData != null) { try { Iterator tiffReaders = ImageIO.getImageReadersByFormatName("TIFF"); if(tiffReaders != null && tiffReaders.hasNext()) { ImageReader tiffReader = (ImageReader)tiffReaders.next(); ByteArrayInputStream bais = new ByteArrayInputStream(exifData); ImageInputStream exifStream = new MemoryCacheImageInputStream(bais); tiffReader.setInput(exifStream); IIOMetadata exifMetadata = tiffReader.getImageMetadata(0); tiffMetadata.mergeTree(metadataName, exifMetadata.getAsTree(metadataName)); tiffReader.reset(); } } catch(IOException ioe) { // Ignore it. } } return tiffMetadata.getAsTree(metadataName); } // Thumbnail methods private void initializeThumbnails() { synchronized(thumbnails) { if(!thumbnailsInitialized) { // JFIF/JFXX are not supposed to coexist in the same // JPEG stream but in reality sometimes they do. // JFIF thumbnail if(app0JFIFPresent && jfifThumbnail != null) { thumbnails.add(jfifThumbnail); } // JFXX thumbnail(s) if(app0JFXXPresent && jfxxThumbnails != null) { int numJFXX = jfxxThumbnails.size(); for(int i = 0; i < numJFXX; i++) { IIOImage img = (IIOImage)jfxxThumbnails.get(i); BufferedImage jfxxThumbnail = (BufferedImage)img.getRenderedImage(); thumbnails.add(jfxxThumbnail); } } // EXIF thumbnail if(exifData != null) { try { Iterator tiffReaders = ImageIO.getImageReadersByFormatName("TIFF"); if(tiffReaders != null && tiffReaders.hasNext()) { ImageReader tiffReader = (ImageReader)tiffReaders.next(); ByteArrayInputStream bais = new ByteArrayInputStream(exifData); ImageInputStream exifStream = new MemoryCacheImageInputStream(bais); tiffReader.setInput(exifStream); if(tiffReader.getNumImages(true) > 1) { BufferedImage exifThumbnail = tiffReader.read(1, null); thumbnails.add(exifThumbnail); } tiffReader.reset(); } } catch(IOException ioe) { // Ignore it. } } thumbnailsInitialized = true; } // if(!thumbnailsInitialized) } // sychronized } int getNumThumbnails() throws IOException { initializeThumbnails(); return thumbnails.size(); } BufferedImage getThumbnail(int thumbnailIndex) throws IOException { if(thumbnailIndex < 0) { throw new IndexOutOfBoundsException("thumbnailIndex < 0!"); } initializeThumbnails(); if(thumbnailIndex >= thumbnails.size()) { throw new IndexOutOfBoundsException ("thumbnailIndex > getNumThumbnails()"); } return (BufferedImage)thumbnails.get(thumbnailIndex); } } jai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/jpeg2000/0000775000175100017510000000000011650556210026662 5ustar tilletille././@LongLink0000000000000000000000000000015700000000000011570 Lustar rootrootjai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/jpeg2000/ImageInputStreamWrapper.javajai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/jpeg2000/ImageInputStreamWr0000664000175100017510000000705310203036165032334 0ustar tilletille/* * $RCSfile: ImageInputStreamWrapper.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.1 $ * $Date: 2005-02-11 05:01:32 $ * $State: Exp $ */ package com.sun.media.imageioimpl.plugins.jpeg2000; import java.io.InputStream; import java.io.IOException; import javax.imageio.stream.ImageInputStream; /** * This class is designed to wrap a ImageInputStream into * a InputStream. The reason is that ImageInputStream * implements DataInput but doesn't extend * InputStream. However, the JJ2000 JPEG 2000 packages accepts * a InputStream when reads a JPEG 2000 image file. */ public class ImageInputStreamWrapper extends InputStream { /** The ImageInputStream to be wrapped. */ private ImageInputStream src; /** Constructs an ImageInputStreamWrapper from the provided * ImageInputStream. * * @param src The ImageInputStream to be wrapped. */ public ImageInputStreamWrapper(ImageInputStream src) { this.src = src; } // Override the methods defined in InputStream public int read() throws IOException { return src.read(); } public void close() throws IOException { src.close(); } public synchronized void mark(int readlimit) { src.mark(); } public boolean markSupported() { return true; } public int read(byte b[]) throws IOException { return src.read(b, 0, b.length); } public int read(byte b[], int off, int len) throws IOException { return src.read(b, off, len); } public synchronized void reset() throws IOException { src.reset(); } public long skip(long n) throws IOException { return src.skipBytes(n); } } jai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/jpeg2000/Box.java0000664000175100017510000005554210667605610030276 0ustar tilletille/* * $RCSfile: Box.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.6 $ * $Date: 2007-09-05 20:03:20 $ * $State: Exp $ */ package com.sun.media.imageioimpl.plugins.jpeg2000; import java.lang.reflect.Constructor; import java.lang.reflect.Method; import java.lang.reflect.InvocationTargetException; import javax.imageio.metadata.IIOInvalidTreeException; import javax.imageio.metadata.IIOMetadataNode; import java.io.EOFException; import java.io.IOException; import java.util.Enumeration; import java.util.Hashtable; import java.util.StringTokenizer; import org.w3c.dom.NamedNodeMap; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import javax.imageio.IIOException; import javax.imageio.stream.ImageOutputStream; import javax.imageio.stream.ImageInputStream; import com.sun.media.imageioimpl.common.ImageUtil; /** * This class is defined to create the box of JP2 file format. A box has * a length, a type, an optional extra length and its content. The subclasses * should explain the content information. */ public class Box { /** The table to link tag names for all the JP2 boxes. */ private static Hashtable names = new Hashtable(); // Initializes the hash table "names". static { //children for the root names.put(new Integer(0x6A502020), "JPEG2000SignatureBox"); names.put(new Integer(0x66747970), "JPEG2000FileTypeBox"); // children for the boxes other than //JPEG2000SignatureBox/JPEG2000FileTypeBox names.put(new Integer(0x6A703269), "JPEG2000IntellectualPropertyRightsBox"); names.put(new Integer(0x786D6C20), "JPEG2000XMLBox"); names.put(new Integer(0x75756964), "JPEG2000UUIDBox"); names.put(new Integer(0x75696E66), "JPEG2000UUIDInfoBox"); // Children of HeadCStream names.put(new Integer(0x6a703268), "JPEG2000HeaderSuperBox"); names.put(new Integer(0x6a703263), "JPEG2000CodeStreamBox"); // Children of JPEG2000HeaderSuperBox names.put(new Integer(0x69686472), "JPEG2000HeaderBox"); // Optional boxes in JPEG2000HeaderSuperBox names.put(new Integer(0x62706363), "JPEG2000BitsPerComponentBox"); names.put(new Integer(0x636f6c72), "JPEG2000ColorSpecificationBox"); names.put(new Integer(0x70636c72), "JPEG2000PaletteBox"); names.put(new Integer(0x636d6170), "JPEG2000ComponentMappingBox"); names.put(new Integer(0x63646566), "JPEG2000ChannelDefinitionBox"); names.put(new Integer(0x72657320), "JPEG2000ResolutionBox"); // Children of JPEG2000ResolutionBox names.put(new Integer(0x72657363), "JPEG2000CaptureResolutionBox"); names.put(new Integer(0x72657364), "JPEG2000DefaultDisplayResolutionBox"); // Children of JPEG2000UUIDInfoBox names.put(new Integer(0x756c7374), "JPEG2000UUIDListBox"); names.put(new Integer(0x75726c20), "JPEG2000DataEntryURLBox"); } /** A Hashtable contains the class names for each type of the boxes. * This table will be used to construct a Box object from a Node object * by using reflection. */ private static Hashtable boxClasses = new Hashtable(); // Initializes the hash table "boxClasses". static { //children for the root boxClasses.put(new Integer(0x6A502020), SignatureBox.class); boxClasses.put(new Integer(0x66747970), FileTypeBox.class); // children for the boxes other than //JPEG2000SignatureBox/JPEG2000FileTypeBox boxClasses.put(new Integer(0x6A703269), Box.class); boxClasses.put(new Integer(0x786D6C20), XMLBox.class); boxClasses.put(new Integer(0x75756964), UUIDBox.class); // Children of JPEG2000HeaderSuperBox boxClasses.put(new Integer(0x69686472), HeaderBox.class); // Optional boxes in JPEG2000HeaderSuperBox boxClasses.put(new Integer(0x62706363), BitsPerComponentBox.class); boxClasses.put(new Integer(0x636f6c72), ColorSpecificationBox.class); boxClasses.put(new Integer(0x70636c72), PaletteBox.class); boxClasses.put(new Integer(0x636d6170), ComponentMappingBox.class); boxClasses.put(new Integer(0x63646566), ChannelDefinitionBox.class); boxClasses.put(new Integer(0x72657320), ResolutionBox.class); // Children of JPEG2000ResolutionBox boxClasses.put(new Integer(0x72657363), ResolutionBox.class); boxClasses.put(new Integer(0x72657364), ResolutionBox.class); // Children of JPEG2000UUIDInfoBox boxClasses.put(new Integer(0x756c7374), UUIDListBox.class); boxClasses.put(new Integer(0x75726c20), DataEntryURLBox.class); } /** Returns the XML tag name defined in JP2 XML xsd/dtd for the box * with the provided type. If the type is * not known, the string "unknown" is returned. */ public static String getName(int type) { String name = (String)names.get(new Integer(type)); return name == null ? "unknown" : name; } /** Returns the Box class for the box with the provided type. */ public static Class getBoxClass(int type) { if (type == 0x6a703268 || type == 0x72657320) return null; return (Class)boxClasses.get(new Integer(type)); } /** Returns the type String based on the provided name. */ public static String getTypeByName(String name) { Enumeration keys = names.keys(); while (keys.hasMoreElements()) { Integer i = (Integer)keys.nextElement(); if (name.equals(names.get(i))) return getTypeString(i.intValue()); } return null; } /** Creates a Box object with the provided type * based on the provided Node object based on reflection. */ public static Box createBox(int type, Node node) throws IIOInvalidTreeException { Class boxClass = (Class)boxClasses.get(new Integer(type)); try { // gets the constructor with NodeBox instance. e.printStackTrace(); return new Box(node); } catch(InvocationTargetException e) { e.printStackTrace(); return new Box(node); } catch (IllegalAccessException e) { e.printStackTrace(); return new Box(node); } catch (InstantiationException e) { e.printStackTrace(); return new Box(node); } return null; } /** Extracts the value of the attribute from name. */ public static Object getAttribute(Node node, String name) { NamedNodeMap map = node.getAttributes(); node = map.getNamedItem(name); return (node != null) ? node.getNodeValue() : null; } /** Parses the byte array expressed by a string. */ public static byte[] parseByteArray(String value) { if (value == null) return null; StringTokenizer token = new StringTokenizer(value); int count = token.countTokens(); byte[] buf = new byte[count]; int i = 0; while(token.hasMoreElements()) { buf[i++] = new Byte(token.nextToken()).byteValue(); } return buf; } /** Parses the integer array expressed a string. */ protected static int[] parseIntArray(String value) { if (value == null) return null; StringTokenizer token = new StringTokenizer(value); int count = token.countTokens(); int[] buf = new int[count]; int i = 0; while(token.hasMoreElements()) { buf[i++] = new Integer(token.nextToken()).intValue(); } return buf; } /** Gets its String value from an IIOMetadataNode. */ protected static String getStringElementValue(Node node) { if (node instanceof IIOMetadataNode) { Object obj = ((IIOMetadataNode)node).getUserObject(); if (obj instanceof String) return (String)obj; } return node.getNodeValue(); } /** Gets its byte value from an IIOMetadataNode. */ protected static byte getByteElementValue(Node node) { if (node instanceof IIOMetadataNode) { Object obj = ((IIOMetadataNode)node).getUserObject(); if (obj instanceof Byte) return ((Byte)obj).byteValue(); } String value = node.getNodeValue(); if (value != null) return new Byte(value).byteValue(); return (byte)0; } /** Gets its integer value from an IIOMetadataNode. */ protected static int getIntElementValue(Node node) { if (node instanceof IIOMetadataNode) { Object obj = ((IIOMetadataNode)node).getUserObject(); if (obj instanceof Integer) return ((Integer)obj).intValue(); } String value = node.getNodeValue(); if (value != null) return new Integer(value).intValue(); return 0; } /** Gets its short value from an IIOMetadataNode. */ protected static short getShortElementValue(Node node) { if (node instanceof IIOMetadataNode) { Object obj = ((IIOMetadataNode)node).getUserObject(); if (obj instanceof Short) return ((Short)obj).shortValue(); } String value = node.getNodeValue(); if (value != null) return new Short(value).shortValue(); return (short)0; } /** Gets the byte array from an IIOMetadataNode. */ protected static byte[] getByteArrayElementValue(Node node) { if (node instanceof IIOMetadataNode) { Object obj = ((IIOMetadataNode)node).getUserObject(); if (obj instanceof byte[]) return (byte[])obj; } return parseByteArray(node.getNodeValue()); } /** Gets the integer array from an IIOMetadataNode. */ protected static int[] getIntArrayElementValue(Node node) { if (node instanceof IIOMetadataNode) { Object obj = ((IIOMetadataNode)node).getUserObject(); if (obj instanceof int[]) return (int[])obj; } return parseIntArray(node.getNodeValue()); } /** Copies that four bytes of an integer into the byte array. Necessary * for the subclasses to compose the content array from the data elements */ public static void copyInt(byte[] data, int pos, int value) { data[pos++] = (byte)(value >> 24); data[pos++] = (byte)(value >> 16); data[pos++] = (byte)(value >> 8); data[pos++] = (byte)(value & 0xFF); } /** Converts the box type from integer to string. This is necessary because * type is defined as String in xsd/dtd and integer in the box classes. */ public static String getTypeString(int type) { byte[] buf = new byte[4]; for (int i = 3; i >= 0; i--) { buf[i] = (byte)(type & 0xFF); type >>>= 8; } return new String(buf); } /** * Converts the box type from integer to string. This is necessary because * type is defined as String in xsd/dtd and integer in the box classes. */ public static int getTypeInt(String s) { byte[] buf = s.getBytes(); int t = buf[0]; for (int i = 1; i < 4; i++) { t = (t <<8) | buf[i]; } return t; } /** Box length, extra length, type and content data array */ protected int length; protected long extraLength; protected int type; protected byte[] data; /** Constructs a Box instance using the provided * the box type and the box content in byte array format. * * @param length The provided box length. * @param type The provided box type. * @param data The provided box content in a byte array. * * @throws IllegalArgumentException If the length of the content byte array * is not length - 8. */ public Box(int length, int type, byte[] data) { this.type = type; setLength(length); setContent(data); } /** Constructs a Box instance using the provided * the box type, the box extra length, and the box content in byte * array format. In this case, the length of the box is set to 1, * which indicates the extra length is meaningful. * * @param length The provided box length. * @param type The provided box type. * @param extraLength The provided box extra length. * @param data The provided box content in a byte array. * * @throws IllegalArgumentException If the length of the content byte array * is not extra length - 16. */ public Box(int length, int type, long extraLength, byte[] data) { this.type = type; setLength(length); if (length == 1) setExtraLength(extraLength); setContent(data); } /** Constructs a Box instance from the provided * ImageInputStream at the specified position. * * @param iis The ImageInputStream contains the box. * @param pos The position from where to read the box. * @throws IOException If any IOException is thrown in the called read * methods. */ public Box(ImageInputStream iis, int pos) throws IOException { read(iis, pos); } /** * Constructs a Box from an "unknown" Node. This node has at * least the attribute "Type", and may have the attribute "Length", * "ExtraLength" and a child "Content". The child node content is a * IIOMetaDataNode with a byte[] user object. */ public Box(Node node) throws IIOInvalidTreeException { NodeList children = node.getChildNodes(); String value = (String)Box.getAttribute(node, "Type"); type = getTypeInt(value); if (value == null || names.get(new Integer(type)) == null) throw new IIOInvalidTreeException("Type is not defined", node); value = (String)Box.getAttribute(node, "Length"); if (value != null) length = new Integer(value).intValue(); value = (String)Box.getAttribute(node, "ExtraLength"); if (value != null) extraLength = new Long(value).longValue(); for (int i = 0; i < children.getLength(); i++) { Node child = children.item(i); if ("Content".equals(child.getNodeName())) { if (child instanceof IIOMetadataNode) { IIOMetadataNode cnode = (IIOMetadataNode)child; try { data = (byte[])cnode.getUserObject(); } catch (Exception e) { } }else { data = getByteArrayElementValue(child); } if (data == null) { value = node.getNodeValue(); if (value != null) data = value.getBytes(); } } } } /** Creates an IIOMetadataNode from this * box. The format of this node is defined in the XML dtd and xsd * for the JP2 image file. */ public IIOMetadataNode getNativeNode() { String name = Box.getName(getType()); if (name == null) name = "unknown"; IIOMetadataNode node = new IIOMetadataNode(name); setDefaultAttributes(node); IIOMetadataNode child = new IIOMetadataNode("Content"); child.setUserObject(data); child.setNodeValue(ImageUtil.convertObjectToString(data)); node.appendChild(child); return node; } /** Creates an IIOMetadataNode from this * box. The format of this node is defined in the XML dtd and xsd * for the JP2 image file. * * This method is designed for the types of boxes whose XML tree * only has 2 levels. */ protected IIOMetadataNode getNativeNodeForSimpleBox() { try { Method m = this.getClass().getMethod("getElementNames", (Class[])null); String[] elementNames = (String[])m.invoke(null, (Object[])null); IIOMetadataNode node = new IIOMetadataNode(Box.getName(getType())); setDefaultAttributes(node); for (int i = 0; i < elementNames.length; i++) { IIOMetadataNode child = new IIOMetadataNode(elementNames[i]); m = this.getClass().getMethod("get" + elementNames[i], (Class[])null); Object obj = m.invoke(this, (Object[])null); child.setUserObject(obj); child.setNodeValue(ImageUtil.convertObjectToString(obj)); node.appendChild(child); } return node; } catch (Exception e) { throw new IllegalArgumentException(I18N.getString("Box0")); } } /** Sets the default attributes, "Length", "Type", and "ExtraLength", to * the provided IIOMetadataNode. */ protected void setDefaultAttributes(IIOMetadataNode node) { node.setAttribute("Length", Integer.toString(length)); node.setAttribute("Type", getTypeString(type)); if (length == 1) { node.setAttribute("ExtraLength", Long.toString(extraLength)); } } /** Returns the box length. */ public int getLength() { return length; } /** Returns the box type. */ public int getType() { return type; } /** Returns the box extra length. */ public long getExtraLength() { return extraLength; } /** Returns the box content in byte array. */ public byte[] getContent() { if (data == null) compose(); return data; } /** Sets the box length to the provided value. */ public void setLength(int length) { this.length = length; } /** Sets the box extra length length to the provided value. */ public void setExtraLength(long extraLength) { if (length != 1) throw new IllegalArgumentException(I18N.getString("Box1")); this.extraLength = extraLength; } /** Sets the box content. If the content length is not length -8 or * extra length - 16, IllegalArgumentException will be thrown. */ public void setContent(byte[] data) { if (data != null && ((length ==1 && (extraLength - 16 != data.length)) || (length != 1 && length - 8 != data.length))) throw new IllegalArgumentException(I18N.getString("Box2")); this.data = data; if (data != null) parse(data); } /** Writes this box instance into a ImageOutputStream. */ public void write(ImageOutputStream ios) throws IOException { ios.writeInt(length); ios.writeInt(type); if (length == 1) { ios.writeLong(extraLength); ios.write(data, 0, (int)extraLength); } else if (data != null) ios.write(data, 0, length); } /** Reads a box from the ImageInputStream= 8 && length < (1 << 32)) { // Length given by L parameter. dataLength = length - 8; } else { // Illegal value for L parameter. throw new IIOException("Illegal value "+length+ " for box length parameter."); } data = new byte[dataLength]; iis.readFully(data); iis.reset(); } /** Parses the data elements from the byte array. The subclasses should * override this method. */ protected void parse(byte[] data) { } /** Composes the content byte array from the data elements. */ protected void compose() { } } jai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/jpeg2000/PaletteBox.java0000664000175100017510000002157210203036165031576 0ustar tilletille/* * $RCSfile: PaletteBox.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.1 $ * $Date: 2005-02-11 05:01:36 $ * $State: Exp $ */ package com.sun.media.imageioimpl.plugins.jpeg2000; import java.awt.image.IndexColorModel; import javax.imageio.metadata.IIOInvalidTreeException; import javax.imageio.metadata.IIOMetadataNode; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import com.sun.media.imageioimpl.common.ImageUtil; /** This class is designed to represent a palette box for JPEG 2000 JP2 file * format. A palette box has a length, and a fixed type of "pclr". * * Its content contains the number of palette entry, the number of color * components, the bit depths of the output components, the LUT. * * Currently, only 8-bit color index is supported. */ public class PaletteBox extends Box { /** The value of the data elements. */ private int numEntries; private int numComps; private byte[] bitDepth; private byte[][] lut; /** Compute the length of this box. */ private static int computeLength(IndexColorModel icm) { int size = icm.getMapSize(); int[] comp = icm.getComponentSize(); return 11 + comp.length + size * comp.length; } /** Gets the size of the components or the bit depth for all the color * coomponents. */ private static byte[] getCompSize(IndexColorModel icm) { int[] comp = icm.getComponentSize(); int size = comp.length; byte[] buf = new byte[size]; for (int i = 0; i < size; i++) buf[i] = (byte)(comp[i] - 1); return buf; } /** Gets the LUT from the IndexColorModel as an two-dimensional * byte array. */ private static byte[][] getLUT(IndexColorModel icm) { int[] comp = icm.getComponentSize(); int size = icm.getMapSize(); byte[][] lut = new byte[comp.length][size]; icm.getReds(lut[0]); icm.getGreens(lut[1]); icm.getBlues(lut[2]); if (comp.length == 4) icm.getAlphas(lut[3]); return lut; } /** Constructs a PlatteBox from an * IndexColorModel. */ public PaletteBox(IndexColorModel icm) { this(computeLength(icm), getCompSize(icm), getLUT(icm)); } /** Constructs a PlatteBox from an * org.w3c.dom.Node. */ public PaletteBox(Node node) throws IIOInvalidTreeException { super(node); byte[][] tlut = null; int index = 0; NodeList children = node.getChildNodes(); for (int i = 0; i < children.getLength(); i++) { Node child = children.item(i); String name = child.getNodeName(); if ("NumberEntries".equals(name)) { numEntries = Box.getIntElementValue(child); } if ("NumberColors".equals(name)) { numComps = Box.getIntElementValue(child); } if ("BitDepth".equals(name)) { bitDepth = Box.getByteArrayElementValue(child); } if ("LUT".equals(name)) { tlut = new byte[numEntries][]; NodeList children1 = child.getChildNodes(); for (int j = 0; j PlatteBox from the provided length, bit * depths of the color components and the LUT. */ public PaletteBox(int length, byte[] comp, byte[][] lut) { super(length, 0x70636C72, null); this.bitDepth = comp; this.lut = lut; this.numEntries = lut[0].length; this.numComps = lut.length; } /** Constructs a PlatteBox from the provided byte array. */ public PaletteBox(byte[] data) { super(8 + data.length, 0x70636C72, data); } /** Return the number of palette entries. */ public int getNumEntries() { return numEntries; } /** Return the number of color components. */ public int getNumComp() { return numComps; } /** Return the bit depths for all the color components. */ public byte[] getBitDepths() { return bitDepth; } /** Return the LUT. */ public byte[][] getLUT() { return lut; } /** creates an IIOMetadataNode from this palette box. * The format of this node is defined in the XML dtd and xsd * for the JP2 image file. */ public IIOMetadataNode getNativeNode() { IIOMetadataNode node = new IIOMetadataNode(Box.getName(getType())); setDefaultAttributes(node); IIOMetadataNode child = new IIOMetadataNode("NumberEntries"); child.setUserObject(new Integer(numEntries)); child.setNodeValue("" + numEntries); node.appendChild(child); child = new IIOMetadataNode("NumberColors"); child.setUserObject(new Integer(numComps)); child.setNodeValue("" + numComps); node.appendChild(child); child = new IIOMetadataNode("BitDepth"); child.setUserObject(bitDepth); child.setNodeValue(ImageUtil.convertObjectToString(bitDepth)); node.appendChild(child); child = new IIOMetadataNode("LUT"); for (int i = 0; i < numEntries; i++) { IIOMetadataNode child1 = new IIOMetadataNode("LUTRow"); byte[] row = new byte[numComps]; for (int j = 0; j < numComps; j++) row[j] = lut[j][i]; child1.setUserObject(row); child1.setNodeValue(ImageUtil.convertObjectToString(row)); child.appendChild(child1); } node.appendChild(child); return node; } protected void parse(byte[] data) { if (data == null) return; numEntries = (short)(((data[0] & 0xFF) << 8) | (data[1] & 0xFF)); numComps = data[2]; bitDepth = new byte[numComps]; System.arraycopy(data, 3, bitDepth, 0, numComps); lut = new byte[numComps][numEntries]; for (int i = 0, k = 3 + numComps; i < numEntries; i++) for (int j = 0; j < numComps; j++) lut[j][i] = data[k++]; } protected void compose() { if (data != null) return; data = new byte[3 + numComps + numEntries * numComps]; data[0] = (byte)(numEntries >> 8); data[1] = (byte)(numEntries & 0xFF); data[2] = (byte)numComps; System.arraycopy(bitDepth, 0, data, 3, numComps); for (int i = 0, k = 3 + numComps; i < numEntries; i++) for (int j = 0; j < numComps; j++) data[k++] = lut[j][i]; } } ././@LongLink0000000000000000000000000000015400000000000011565 Lustar rootrootjai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/jpeg2000/ChannelDefinitionBox.javajai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/jpeg2000/ChannelDefinitionB0000664000175100017510000002323710203036165032272 0ustar tilletille/* * $RCSfile: ChannelDefinitionBox.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.1 $ * $Date: 2005-02-11 05:01:31 $ * $State: Exp $ */ package com.sun.media.imageioimpl.plugins.jpeg2000; import java.awt.image.ColorModel; import javax.imageio.metadata.IIOInvalidTreeException; import javax.imageio.metadata.IIOMetadataNode; import org.w3c.dom.Node; import org.w3c.dom.NodeList; /** This class is designed to represent a Channel Definition Box of * JPEG JP2 file format. A Channel Definition Box has a length, and * a fixed type of "cdef". Its content defines the type of the image * channels: color channel, alpha channel or premultiplied alpha channel. */ public class ChannelDefinitionBox extends Box { /** The cached data elements. */ private short num; private short[] channels; private short[] types; private short[] associations; /** Computes the length of this box from the provided * ColorModel. */ private static int computeLength(ColorModel colorModel) { int length = colorModel.getComponentSize().length - 1; return 10 + (colorModel.isAlphaPremultiplied() ? length * 18 : length * 12); } /** Fills the channel definitions into the arrays based on the number * of components and isPremultiplied. */ public static void fillBasedOnBands(int numComps, boolean isPremultiplied, short[] c, short[] t, short[] a) { int num = numComps * (isPremultiplied ? 3 : 2); if (isPremultiplied) { for (int i = numComps * 2; i < num; i++) { c[i] = (short)(i - numComps * 2); t[i] = 2; // 2 -- premultiplied a[i] = (short)(i + 1 - numComps * 2); } } for (int i = 0; i < numComps; i++) { int j = i + numComps; c[i] = (short)i; t[i] = 0; // The original channel a[j] = a[i] = (short)(i + 1); c[j] = (short)numComps; t[j] = 1; // 1 -- transparency } } /** Constructs a ChannelDefinitionBox based on the provided * ColorModel. */ public ChannelDefinitionBox(ColorModel colorModel) { super(computeLength(colorModel), 0x63646566, null); // creates the buffers for the channel definitions. short length = (short)(colorModel.getComponentSize().length - 1); num = (short)(length * (colorModel.isAlphaPremultiplied() ? 3 : 2)); channels = new short[num]; types = new short[num]; associations = new short[num]; // fills the arrays. fillBasedOnBands(length, colorModel.isAlphaPremultiplied(), channels, types, associations); } /** Constructs a ChannelDefinitionBox based on the provided * content in byte array. */ public ChannelDefinitionBox(byte[] data) { super(8 + data.length, 0x63646566, data); } /** Constructs a ChannelDefinitionBox based on the provided * channel definitions. */ public ChannelDefinitionBox(short[] channel, short[] types, short[] associations) { super(10 + channel.length * 6, 0x63646566, null); this.num = (short)channel.length; this.channels = channel; this.types = types; this.associations = associations; } /** Constructs a ChannelDefinitionBox based on the provided * org.w3c.dom.Node. */ public ChannelDefinitionBox(Node node) throws IIOInvalidTreeException { super(node); NodeList children = node.getChildNodes(); int index = 0; for (int i = 0; i < children.getLength(); i++) { Node child = children.item(i); String name = child.getNodeName(); if ("NumberOfDefinition".equals(name)) { num = Box.getShortElementValue(child); } if ("Definitions".equals(name)) { channels = new short[num]; types = new short[num]; associations = new short[num]; NodeList children1 = child.getChildNodes(); for (int j = 0; j < children1.getLength(); j++) { child = children1.item(j); name = child.getNodeName(); if ("ChannelNumber".equals(name)) { channels[index] = Box.getShortElementValue(child); } if ("ChannelType".equals(name)) { types[index] = Box.getShortElementValue(child); } if ("Association".equals(name)) { associations[index++] = Box.getShortElementValue(child); } } } } } /** Parse the channel definitions from the content data array. */ protected void parse(byte[] data) { num = (short)((data[0] << 8) | data[1]); channels = new short[num]; types = new short[num]; associations = new short[num]; for (int i = 0, j = 2; i < num; i++) { channels[i] = (short)(((data[j++] & 0xFF) << 8) + (data[j++] & 0xFF)); types[i] = (short)(((data[j++] & 0xFF) << 8) + (data[j++] & 0xFF)); associations[i] = (short)(((data[j++] & 0xFF) << 8) + (data[j++] & 0xFF)); } } /** Returns the defined channels. */ public short[] getChannel() { return channels; } /** Returns the channel types. */ public short[] getTypes() { return types; } /** Returns the association which associates a color channel to a color * component in the color space of the image. */ public short[] getAssociation() { return associations; } /** Creates an IIOMetadataNode from this channel definition * box. The format of this node is defined in the XML dtd and xsd * for the JP2 image file. */ public IIOMetadataNode getNativeNode() { IIOMetadataNode node = new IIOMetadataNode(Box.getName(getType())); setDefaultAttributes(node); IIOMetadataNode child = new IIOMetadataNode("NumberOfDefinition"); child.setUserObject(new Short(num)); child.setNodeValue("" + num); node.appendChild(child); child = new IIOMetadataNode("Definitions"); node.appendChild(child); for (int i = 0; i < num; i++) { IIOMetadataNode child1 = new IIOMetadataNode("ChannelNumber"); child1.setUserObject(new Short(channels[i])); child1.setNodeValue("" + channels[i]); child.appendChild(child1); child1 = new IIOMetadataNode("ChannelType"); child1.setUserObject(new Short(types[i])); child1.setNodeValue("" + types[i]); child.appendChild(child1); child1 = new IIOMetadataNode("Association"); child1.setUserObject(new Short(associations[i])); child1.setNodeValue("" + associations[i]); child.appendChild(child1); } return node; } protected void compose() { if (data != null) return; int len = num * 6 + 2; data = new byte[len]; data[0] = (byte)(num >> 8); data[1] = (byte)(num & 0xFF); for (int i = 0, j = 2; i < num; i++) { data[j++] = (byte)(channels[i] >> 8); data[j++] = (byte)(channels[i] & 0xFF); data[j++] = (byte)(types[i] >> 8); data[j++] = (byte)(types[i] & 0xFF); data[j++] = (byte)(associations[i] >> 8); data[j++] = (byte)(associations[i] & 0xFF); } } } jai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/jpeg2000/XMLBox.java0000664000175100017510000001027010203036165030631 0ustar tilletille/* * $RCSfile: XMLBox.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.1 $ * $Date: 2005-02-11 05:01:37 $ * $State: Exp $ */ package com.sun.media.imageioimpl.plugins.jpeg2000; import javax.imageio.metadata.IIOInvalidTreeException; import javax.imageio.metadata.IIOMetadataNode; import org.w3c.dom.Node; import org.w3c.dom.NodeList; /** This class is defined to represent a XML box of JPEG JP2 * file format. This type of box has a length, a type of "xml ". Its * content is a text string of a XML instance. */ public class XMLBox extends Box { /** Cache the element names for this box's xml definition */ private static String[] elementNames = {"Content"}; /** This method will be called by the getNativeNodeForSimpleBox of the * class Box to get the element names. */ public static String[] getElementNames() { return elementNames; } /** Create a Box from its content. */ public XMLBox(byte[] data) { super(8 + data.length, 0x786D6C20, data); } /** Constructs a UUIDListBox based on the provided * org.w3c.dom.Node. */ public XMLBox(Node node) throws IIOInvalidTreeException { super(node); NodeList children = node.getChildNodes(); for (int i = 0; i < children.getLength(); i++) { Node child = children.item(i); String name = child.getNodeName(); if ("Content".equals(name)) { String value = child.getNodeValue(); if (value != null) data = value.getBytes(); else if (child instanceof IIOMetadataNode) { value = (String)((IIOMetadataNode)child).getUserObject(); if (value != null) data = value.getBytes(); } } } } /** Creates an IIOMetadataNode from this XML * box. The format of this node is defined in the XML dtd and xsd * for the JP2 image file. */ public IIOMetadataNode getNativeNode() { try { IIOMetadataNode node = new IIOMetadataNode(Box.getName(getType())); setDefaultAttributes(node); IIOMetadataNode child = new IIOMetadataNode("Content"); String value = null; if (data != null) value = new String(data); child.setUserObject(value); child.setNodeValue(value); node.appendChild(child); return node; } catch (Exception e) { throw new IllegalArgumentException(I18N.getString("Box0")); } } } ././@LongLink0000000000000000000000000000015600000000000011567 Lustar rootrootjai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/jpeg2000/J2KImageWriteParamJava.javajai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/jpeg2000/J2KImageWriteParam0000664000175100017510000014313710504346562032147 0ustar tilletille/* * $RCSfile: J2KImageWriteParamJava.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.2 $ * $Date: 2006-09-20 23:23:30 $ * $State: Exp $ */ package com.sun.media.imageioimpl.plugins.jpeg2000; import java.awt.Rectangle; import java.awt.image.Raster; import java.awt.image.RenderedImage; import java.util.Collections; import java.util.Locale; import java.util.Iterator; import javax.imageio.IIOImage; import javax.imageio.ImageWriteParam; import jj2000.j2k.*; import jj2000.j2k.roi.*; import jj2000.j2k.quantization.*; import jj2000.j2k.wavelet.analysis.AnWTFilterSpec; import jj2000.j2k.image.forwcomptransf.ForwCompTransfSpec; import jj2000.j2k.entropy.CBlkSizeSpec; import jj2000.j2k.entropy.PrecinctSizeSpec; import jj2000.j2k.entropy.ProgressionSpec; import jj2000.j2k.image.BlkImgDataSrc; import jj2000.j2k.entropy.encoder.LayersInfo; import com.sun.media.imageio.plugins.jpeg2000.J2KImageWriteParam; /** * A subclass of ImageWriteParam for writing images in * the JPEG 2000 format. * *

JPEG 2000 plugin supports to losslessly or lossy compress gray-scale, * RGB, and RGBA images with byte, unsigned short or short data type. It also * supports losslessly compress bilevel, and 8-bit indexed. The result data * is in the format of JP2 (JPEG 2000 Part 1 or baseline format). * *

Many encoding parameters for JPEG 2000 can be tile-component specific. * These parameters are marked as Yes in the column * TC_SPEC in the following parameter table. * They must be provided according to the pattern: * [<tile-component idx>] <param> (repeated as many time as needed), * where <tile-component idx> respect the following policy according to * the degree of priority: * * * * * *
(1) t<idx> c<idx> : Tile-component specification.
(2) t<idx> : Tile specification.
(3) c<idx> : Component specification.
(4) <void> : Default specification.
*

Where the priorities of the specifications are: * (1) > (2) > (3) > (4), (">" means "overrides") * <idx>: "," separates indexes, "-" separates bounds of indexes list. * (for example, 0,2-4 means indexes 0,2,3 and 4). * *

The parameters for encoding JPEG 2000 are listed in the following table: * * *

* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
JPEG 2000 Plugin Decoding Parameters
Parameter Name DescriptionTC_SPEC
encodingRate The bitrate in bits-per-pixel for encoding. Should be set when * lossy compression scheme is used. With the default value * Double.MAX_VALUE, a lossless compression will be done. * No
lossless Indicates using the loseless scheme or not. It is equivalent to * use reversible quantization and 5x3 integer wavelet filters. The * default is true. * No
componentTransformation Specifies to utilize the component transformation on some tiles. * If the wavelet transform is reversible (w5x3 filter), the Reversible * Component Transformation (RCT) is applied. If not reversible * (w9x7 filter), the Irreversible Component Transformation (ICT) is used. * Yes, Tile_Specific
filters Specifies which wavelet filters to use for the specified * tile-components. JPEG 2000 part I only supports w5x3 and w9x7 filters. * Yes
decompositionLevel Specifies the wavelet decomposition levels to apply to * the image. If it is 0, no wavelet transform is performed, in which * case the original image data will be sent to the encoder and an example * is the binary data. All components and all tiles have the same number * of decomposition levels. The default value is 5. * No
guardBits The number of bits used for each tile-component in the quantizer * to avoid overflow. It takes values in the range 0 through 7. The * default value is 2. * Yes
quantizationStep This parameter specifies the base normalized quantization step * size for the tiles/components. It is normalized to a dynamic range * of 1 in the image domain. This parameter is ignored in reversible * coding. The default value is 0.0078125. * Yes
quantizationType Specifies which quantization type to use for specified * tiles/components. Not specified for lossless compression. By default, * the quantization step size is "expounded". Supported quantization * types specification are : "reversible" (no quantization), "derived" * (derived quantization step size) and "expounded". * Yes
codeBlockSize Specifies the maximum code-block size to use for tile-component. * The maximum width and height is 1024, however the block size * (i.e. width x height) must not exceed 4096. The minimum width and * height is 4. The default values are (64, 64). * Yes
progressionType Specifies which type of progression should be used when generating * the codestream. *

The format is [<tile index>] * res|layer|res-pos|pos-comp|comp-pos [res_start comp_start layer_end * res_end comp_end prog] [[res_start comp_start layer_end res_end * comp_end prog]...] [[<tile-component idx]...]. *

The value "res" generates a resolution progressive * codestream with the number of layers specified by "layers" parameter. * The value "layer" generates a layer progressive codestream with * multiple layers. In any case, the rate-allocation algorithm optimizes * for best quality in each layer. The quality measure is mean squared * error (MSE) or a weighted version of it (WMSE). If no progression * type is specified or imposed by other parameters, the default value * is "layer". It is also possible to describe progression order * changes. In this case, "res_start" is the index (from 0) of the * first resolution level, "comp_start" is the index (from 0) of the * first component, "layer_end" is the index (from 0) of the first layer * not included, "res_end" is the index (from 0) of the first * resolution level not included, "comp_end" is index (from 0) of * the first component not included and "prog" is the progression type * to be used for the rest of the tile/image. Several progression * order changes can be specified, one after the other. *

Yes
packPacketHeaderInTile Indicates that the packet headers are packed in the tiles' headers. * The default is false. * No
packPacketHeaderInMain Indicates that the packet headers are packed in the main header. * The default is false. * No
packetPerTilePart Specifies the maximum number of packets to be put into one tile-part. * Zero means putting all packets in the first tile-part of each tile. * No
ROIs Specifies ROIs shape and location. The component index specifies * which components contain the ROI. If this parameter is used, the * codestream is layer progressive by default unless it is overridden by * the progressionType. A rectanglar or circular ROI can be * specified in the format: [<component idx>] R <left> * <top> <width> <height> or [<component idx>] C * <center x> <center y> <radius>. An arbitrary shape * can be assigned by [<component idx>] A <PGM file> * Yes, component-specified
startLevelROI This parameter defines the lowest resolution levels to belong to * the ROI. By doing this, it is possible to avoid getting * information for the ROI at an early stage of transmission. * startLevelROI = 0 means the lowest resolution level belongs to * the ROI, 1 means the second lowest etc. The default values, -1, * deactivates this parameter. * No
alignROI By specifying this parameter, the ROI mask will be limited to * covering only entire code-blocks. The ROI coding can then be * performed without any actual scaling of the coefficients but by * instead scaling the distortion estimates. * No
bypass Uses the lazy coding mode with the entropy coder. This will bypass * the MQ coder for some of the coding passes, where the distribution * is often close to uniform. Since the MQ codeword will be terminated * at least once per lazy pass, it is important to use an efficient * termination algorithm, methodForMQTermination. * true enables, and false disables it. The default value is false. * Yes
resetMQ If this is enabled the probability estimates of the MQ coder are * reset after each arithmetically coded (i.e. non-lazy) coding pass. * true enables, and false disables it. The default value is false. * Yes
terminateOnByte If this is enabled the codeword (raw or MQ) is terminated on a byte * boundary after each coding pass. In this case it is important to use * an efficient termination algorithm, "methodForMQTermination". * true enables, and false disables it. The default value is false. * Yes
causalCXInfo Uses vertically stripe causal context formation. If this is * enabled the context formation process in one stripe is independant of * the next stripe (i.e. the one below it). true enables, and false * disables it. The default value is false. * Yes
codeSegSymbol Inserts an error resilience segmentation symbol in the MQ codeword * at the end of each bit-plane (cleanup pass). Decoders can use this * information to detect and conceal errors. true enables, and false * disables it. The default value is false. * Yes
methodForMQTermination Specifies the algorithm used to terminate the MQ codeword. The * most efficient one is "near_opt", which delivers a codeword which * in almost all cases is the shortest possible. The "easy" is a * simpler algorithm that delivers a codeword length that is close * to the previous one (in average 1 bit longer). The "predict" is * almost the same as the "easy" but it leaves error resilient * information on the spare least significant bits (in average 3.5 bits), * which can be used by a decoder to detect errors. The "full" algorithm * performs a full flush of the MQ coder and is highly inefficient. It * is important to use a good termination policy since the MQ codeword * can be terminated quite often, specially if the "bypass" or * "terminateOnByte" parameters are enabled (in the normal case it would * be terminated once per code-block, while "terminateOnByte" is specified * it will be done almost 3 times per bit-plane in each code-block). * The default value is "near_opt". * Yes
methodForMQLengthCalc Specifies the algorithm to use in calculating the necessary MQ * length for each decoding pass. The best one is "near_opt", which * performs a rather sophisticated calculation and provides the best * results. The "lazy_good" and "lazy" are very simple algorithms * that provide rather conservative results. "lazy_good" performs * slightly better. Please use the default unless the experiments * show the benefits of different length calculation algorithms. * The default value is "near_opt". * Yes
precinctPartition Specifies precinct partition dimensions for tiles/components. They * are stored from those applied to the highest resolution to those * applied to the remaining resolutions in decreasing order. If less * values than the number of decomposition levels are specified, then * the last two values are used for the remaining resolutions. * Yes
layers Explicitly specifies the codestream layer formation parameters. * The rate (double) parameter specifies the bitrate to which the first * layer should be optimized. The layers (int) parameter, if present, * specifies the number of extra layers that should be added for * scalability. These extra layers are not optimized. Any extra rate * and layers parameters add more layers, in the same way. An * additional layer is always added at the end, which is optimized * to the overall target bitrate of the bit stream. Any layers * (optimized or not) whose target bitrate is higher that the overall * target bitrate are silently ignored. The bitrates of the extra layers * that are added through the layers parameter are approximately * log-spaced between the other target bitrates. If several (rate, layers) * constructs appear the rate parameters must appear in increasing order. * The rate allocation algorithm ensures that all coded layers have a * minimal reasonable size, if not these layers are silently ignored. * Default: 0.015 +20 2.0 +10. * No
SOPSpecifies whether start of packet (SOP) markers should be used. * true enables, false disables it. The default value is false. * Yes
EPHSpecifies whether end of packet header (EPH) markers should be used. * true enables, false disables it. The default value is false. * Yes
*/ public class J2KImageWriteParamJava extends ImageWriteParam { /** * Indicates that the packet headers are packed in the tiles' headers. */ private boolean packPacketHeaderInTile = false; /** * Indicates that the packet headers are packed in the main header. */ private boolean packPacketHeaderInMain = false; /** * Specifies the maximum number of packets to be put into one tile-part. * Zero means include all packets in first tile-part of each tile. */ private int packetPerTilePart = 0; /** * The bitrate in bits-per-pixel for encoding. Should be set when lossy * compression scheme is used. The default is * Double.MAX_VALUE. */ private double encodingRate = Double.MAX_VALUE; /** * Indicates using the loseless scheme or not. It is equivalent to * use reversible quantization and 5x3 integer wavelet filters. */ private boolean lossless = true; /** Specifies to utilize the component transformation with some tiles. * If the wavelet transform is reversible (w5x3 filter), the * Reversible Component Transformation (RCT) is applied. If not reversible * (w9x7 filter), the Irreversible Component Transformation (ICT) * is used. */ private ForwCompTransfSpec componentTransformation = null; private boolean enableCT = true; /** Specifies which filters to use for the specified tile-components. * JPEG 2000 part I only supports w5x3 and w9x7 filters. */ private AnWTFilterSpec filters = null; /** Specifies the number of wavelet decomposition levels to apply to * the image. If it is 0, no wavelet transform is performed, in which * case the original image data will be sent to the encoder and an * example is the binary data. All components and all tiles have * the same number of decomposition levels. Default: 5. */ private IntegerSpec decompositionLevel = null; // = 5; /** The number of bits used for each tile-component in * the quantizer to avoid overflow. It takes values in the range 0 * through 7. Default: 2. */ private GuardBitsSpec guardBits = null; /** This parameter specifies the base normalized quantization step * size for the tiles/components. It is normalized to a dynamic range * of 1 in the image domain. This parameter is ignored in reversible * coding. Default: 0.0078125. */ private QuantStepSizeSpec quantizationStep = null; /** Specifies which quantization type to use for specified * tiles/components. Not specified for lossless compression. By * default , the quantization step size is "expounded". Supported * quantization types specification are : "reversible" (no quantization), * "derived" (derived quantization step size) and "expounded". */ private QuantTypeSpec quantizationType = null; /** This parameter defines the lowest resolution levels to belong to * the ROI. By doing this, it is possible to avoid only getting * information for the ROI at an early stage of transmission. * startLevelROI = 0 means the lowest resolution level belongs to * the ROI, 1 means the second lowest etc. The default values, -1, * deactivates this parameter. */ private int startLevelROI = -1; /** By specifying this parameter, the ROI mask will be limited to * covering only entire code-blocks. The ROI coding can then be * performed without any actual scaling of the coefficients but * by instead scaling the distortion estimates. */ private boolean alignROI = false; /** Specifies ROIs shape and location. The component index specifies * which components contain the ROI. If this parameter is used, the * codestream is layer progressive by default unless it is * overridden by the progressionType. */ private MaxShiftSpec ROIs = null; /** Specifies the maximum code-block size to use for tile-component. * The maximum width and height is 1024, however the image area * (i.e. width x height) must not exceed 4096. The minimum * width and height is 4. Default: 64 64. */ private CBlkSizeSpec codeBlockSize = null; /** Uses the lazy coding mode with the entropy coder. This will bypass * the MQ coder for some of the coding passes, where the distribution * is often close to uniform. Since the MQ codeword will be terminated * at least once per lazy pass, it is important to use an efficient * termination algorithm, methodForMQTermination. * true enables, and false disables it. Default: false. */ private StringSpec bypass = null; /** If this is enabled the probability estimates of the MQ coder are * reset after each arithmetically coded (i.e. non-lazy) coding pass. * true enables, and false disables it. Default: false. */ private StringSpec resetMQ = null; /** If this is enabled the codeword (raw or MQ) is terminated on a byte * boundary after each coding pass. In this case it is important to * use an efficient termination algorithm, the "methodForMQTermination". * true enables, and false disables it. Default: false. */ private StringSpec terminateOnByte = null; /** Uses vertically stripe causal context formation. If this is * enabled the context formation process in one stripe is independant * of the next stripe (i.e. the one below it). true enables, and * false disables it. Default: false. */ private StringSpec causalCXInfo = null; /** Inserts an error resilience segmentation symbol in the MQ codeword * at the end of each bit-plane (cleanup pass). Decoders can use this * information to detect and conceal errors. true enables, * and false disables it. Default: false. */ private StringSpec codeSegSymbol = null; /** Specifies the algorithm used to terminate the MQ codeword. The * most efficient one is "near_opt", which delivers a codeword which * in almost all cases is the shortest possible. The "easy" is a * simpler algorithm that delivers a codeword length that is close * to the previous one (in average 1 bit longer). The "predict" is * almost the same as the "easy" but it leaves error resilient * information on the spare least significant bits (in average * 3.5 bits), which can be used by a decoder to detect errors. * The "full" algorithm performs a full flush of the MQ coder and * is highly inefficient. It is important to use a good termination * policy since the MQ codeword can be terminated quite often, * specially if the "bypass" or "terminateOnByte" parameters are * enabled (in the normal case it would be terminated once per * code-block, while "terminateOnByte" is specified it will be * done almost 3 times per bit-plane in each code-block). * Default: near_opt. */ private StringSpec methodForMQTermination = null; /** Specifies the algorithm to use in calculating the necessary MQ * length for each decoding pass. The best one is "near_opt", which * performs a rather sophisticated calculation and provides the best * results. The "lazy_good" and "lazy" are very simple algorithms * that provide rather conservative results. "lazy_good" performs * slightly better. Please use the default unless the experiments * show the benefits of different length calculation algorithms. * Default: near_opt. */ private StringSpec methodForMQLengthCalc = null; /** Specifies precinct partition dimensions for tiles/components. They * are stored from those applied to the highest resolution to those * applied to the remaining resolutions in decreasing order. If less * values than the number of decomposition levels are specified, then * the last two values are used for the remaining resolutions. */ private PrecinctSizeSpec precinctPartition = null; /** Specifies which type of progression should be used when generating * the codestream. The value "res" generates a resolution progressive * codestream with the number of layers specified by "layers" parameter. * The value "layer" generates a layer progressive codestream with * multiple layers. In any case, the rate-allocation algorithm optimizes * for best quality in each layer. The quality measure is mean squared * error (MSE) or a weighted version of it (WMSE). If no progression * type is specified or imposed by other modules, the default value * is "layer". It is also possible to describe progression order * changes. In this case, "res_start" is the index (from 0) of the * first resolution level, "comp_start" is the index (from 0) of the * first component, "ly_end" is the index (from 0) of the first layer * not included, "res_end" is the index (from 0) of the first * resolution level not included, "comp_end" is index (from 0) of * the first component not included and "prog" is the progression type * to be used for the rest of the tile/image. Several progression * order changes can be specified, one after the other. */ private ProgressionSpec progressionType = null; /** * The specified (tile-component) progression. Will be used to generate * the progression type. */ private String progressionName = null; /** Explicitly specifies the codestream layer formation parameters. * The rate (double) parameter specifies the bitrate to which the first * layer should be optimized. The layers (int) parameter, if present, * specifies the number of extra layers that should be added for * scalability. These extra layers are not optimized. Any extra rate * and layers parameters add more layers, in the same way. An * additional layer is always added at the end, which is optimized * to the overall target bitrate of the bit stream. Any layers * (optimized or not) whose target bitrate is higher that the * overall target bitrate are silently ignored. The bitrates of * the extra layers that are added through the layers parameter * are approximately log-spaced between the other target bitrates. * If several (rate, layers) constructs appear the rate parameters * must appear in increasing order. The rate allocation algorithm * ensures that all coded layers have a minimal reasonable size, * if not these layers are silently ignored. Default: 0.015 +20 2.0 +10. */ private String layers = "0.015 +20 2.0 +10"; /** Specifies whether end of packet header (EPH) markers should be used. * true enables, false disables it. Default: false. */ private StringSpec EPH = null; /** Specifies whether start of packet (SOP) markers should be used. * true enables, false disables it. Default: false. */ private StringSpec SOP = null; private int numTiles; private int numComponents; private RenderedImage imgsrc; private Raster raster; private int minX; private int minY; /** Constructor to set locales. */ public J2KImageWriteParamJava(RenderedImage imgsrc, Locale locale) { super(locale); setDefaults(imgsrc); } /** Constructor to set locales. */ public J2KImageWriteParamJava(IIOImage image, ImageWriteParam param) { super(param.getLocale()); if(image != null) { if (image.hasRaster()) setDefaults(image.getRaster()); else setDefaults(image.getRenderedImage()); } setSourceRegion(param.getSourceRegion()); setSourceBands(param.getSourceBands()); try { setTiling(param.getTileWidth(), param.getTileHeight(), param.getTileGridXOffset(), param.getTileGridYOffset()); } catch (IllegalStateException e) { // tileing is not set do nothing. } setDestinationOffset(param.getDestinationOffset()); setSourceSubsampling(param.getSourceXSubsampling(), param.getSourceYSubsampling(), param.getSubsamplingXOffset(), param.getSubsamplingYOffset()); setDestinationType(param.getDestinationType()); J2KImageWriteParam j2kParam; if(param instanceof J2KImageWriteParam) { j2kParam = (J2KImageWriteParam)param; } else { j2kParam = new J2KImageWriteParam(); } setDecompositionLevel(""+j2kParam.getNumDecompositionLevels()); setEncodingRate(j2kParam.getEncodingRate()); setLossless(j2kParam.getLossless()); setFilters(j2kParam.getFilter()); setEPH("" + j2kParam.getEPH()); setSOP("" + j2kParam.getSOP()); setProgressionName(j2kParam.getProgressionType()); int[] size = j2kParam.getCodeBlockSize(); setCodeBlockSize("" + size[0] +" " + size[1]); enableCT = j2kParam.getComponentTransformation(); setComponentTransformation("" + enableCT); } /** * Constructs a J2KImageWriteParamJava object with default * values for all parameters. */ public J2KImageWriteParamJava() { super(); setSuperProperties(); } /** * Constructs a J2KImageWriteParamJava object with default * values for all parameters. */ public J2KImageWriteParamJava(RenderedImage imgsrc) { super(); setDefaults(imgsrc); } /** * Constructs a J2KImageWriteParamJava object with default * values for all parameters. */ public J2KImageWriteParamJava(Raster raster) { super(); setDefaults(raster); } private void setSuperProperties() { canOffsetTiles = true; canWriteTiles = true; canOffsetTiles = true; canWriteProgressive = true; tilingMode = MODE_EXPLICIT; } /** Set source */ private void setDefaults(Raster raster) { // override the params in the super class setSuperProperties(); if (raster != null) { this.raster = raster; tileGridXOffset = raster.getMinX(); tileGridYOffset = raster.getMinY(); tileWidth = raster.getWidth(); tileHeight = raster.getHeight(); tilingSet = true; numTiles = 1; numComponents = raster.getSampleModel().getNumBands(); } setDefaults(); } /** Set source */ private void setDefaults(RenderedImage imgsrc) { // override the params in the super class setSuperProperties(); tilingMode = MODE_EXPLICIT; if (imgsrc != null) { this.imgsrc = imgsrc; tileGridXOffset = imgsrc.getTileGridXOffset(); tileGridYOffset = imgsrc.getTileGridYOffset(); tileWidth = imgsrc.getTileWidth(); tileHeight = imgsrc.getTileHeight(); tilingSet = true; numTiles = imgsrc.getNumXTiles() * imgsrc.getNumYTiles(); numComponents = imgsrc.getSampleModel().getNumBands(); } setDefaults(); } private void setDefaults() { setROIs(null); setQuantizationType(null); setQuantizationStep(null); setGuardBits(null); setFilters(null); setDecompositionLevel(null); setComponentTransformation(null); setMethodForMQLengthCalc(null); setMethodForMQTermination(null); setCodeSegSymbol(null); setCausalCXInfo(null); setTerminateOnByte(null); setResetMQ(null); setBypass(null); setCodeBlockSize(null); setPrecinctPartition(null); setSOP(null); setEPH(null); } /** Sets encodingRate */ public void setEncodingRate(double rate) { this.encodingRate = rate; } /** Gets encodingRate */ public double getEncodingRate() { return encodingRate; } /** Sets lossless */ public void setLossless(boolean lossless) { this.lossless = lossless; } /** Gets encodingRate */ public boolean getLossless() { return lossless; } /** Sets packetPerTilePart */ public void setPacketPerTilePart(int packetPerTilePart) { if (packetPerTilePart < 0) throw new IllegalArgumentException(I18N.getString("J2KImageWriteParamJava0")); this.packetPerTilePart = packetPerTilePart; if (packetPerTilePart > 0) { setSOP("true"); setEPH("true"); } } /** Gets packetPerTilePart */ public int getPacketPerTilePart() { return packetPerTilePart; } /** Sets packPacketHeaderInTile */ public void setPackPacketHeaderInTile(boolean packPacketHeaderInTile) { this.packPacketHeaderInTile = packPacketHeaderInTile; if (packPacketHeaderInTile) { setSOP("true"); setEPH("true"); } } /** Gets packPacketHeaderInTile */ public boolean getPackPacketHeaderInTile() { return packPacketHeaderInTile; } /** Sets packPacketHeaderInMain */ public void setPackPacketHeaderInMain(boolean packPacketHeaderInMain) { this.packPacketHeaderInMain = packPacketHeaderInMain; if (packPacketHeaderInMain) { setSOP("true"); setEPH("true"); } } /** Gets packPacketHeaderInMain */ public boolean getPackPacketHeaderInMain() { return packPacketHeaderInMain; } /** Sets alignROI */ public void setAlignROI(boolean align) { alignROI = align; } /** Gets alignROI */ public boolean getAlignROI() { return alignROI; } /** Sets ROIs */ public void setROIs(String values) { ROIs = new MaxShiftSpec(numTiles, numComponents, ModuleSpec.SPEC_TYPE_TILE_COMP, values); } /** Gets ROIs */ public MaxShiftSpec getROIs() { return ROIs; } /** Sets quantizationType */ public void setQuantizationType(String values) { quantizationType = new QuantTypeSpec(numTiles, numComponents, ModuleSpec.SPEC_TYPE_TILE_COMP, this, values); } /** Gets quantizationType */ public QuantTypeSpec getQuantizationType() { return quantizationType; } /** Sets quantizationStep */ public void setQuantizationStep(String values) { quantizationStep = new QuantStepSizeSpec(numTiles, numComponents, ModuleSpec.SPEC_TYPE_TILE_COMP, this, values); } /** Gets quantizationStep */ public QuantStepSizeSpec getQuantizationStep() { return quantizationStep; } /** Sets guardBits */ public void setGuardBits(String values) { guardBits = new GuardBitsSpec(numTiles, numComponents, ModuleSpec.SPEC_TYPE_TILE_COMP, this, values); } /** Gets guardBits */ public GuardBitsSpec getGuardBits() { return guardBits; } /** Sets filters */ // NOTE This also sets quantizationType and componentTransformation. public void setFilters(String values) { if (J2KImageWriteParam.FILTER_97.equals(values)) setQuantizationType ("expounded"); else setQuantizationType("reversible"); filters = new AnWTFilterSpec(numTiles, numComponents, ModuleSpec.SPEC_TYPE_TILE_COMP, (QuantTypeSpec)quantizationType, this, values); setComponentTransformation(""+enableCT); } /** Gets filters */ public AnWTFilterSpec getFilters() { return filters; } /** Sets decompositionLevel */ public void setDecompositionLevel(String values) { decompositionLevel = new IntegerSpec(numTiles, numComponents, ModuleSpec.SPEC_TYPE_TILE_COMP, this, values, "5"); // NOTE The precinctPartition depends upon decompositionLevel // so it needs to be re-initialized. Note that the parameter of // setPrecinctPartition() is not used in the current implementation. setPrecinctPartition(null); } /** Gets decompositionLevel */ public IntegerSpec getDecompositionLevel() { return decompositionLevel; } /** Sets componentTransformation */ // NOTE This requires filters having been set previously. public void setComponentTransformation(String values) { componentTransformation = new ForwCompTransfSpec(numTiles, numComponents, ModuleSpec.SPEC_TYPE_TILE, (AnWTFilterSpec)filters, this, values); } /** Gets componentTransformation */ public ForwCompTransfSpec getComponentTransformation() { return componentTransformation; } /** Sets methodForMQLengthCalc */ public void setMethodForMQLengthCalc(String values) { String[] strLcs = {"near_opt","lazy_good","lazy"}; methodForMQLengthCalc = new StringSpec(numTiles, numComponents, ModuleSpec.SPEC_TYPE_TILE_COMP, "near_opt", strLcs, this, values); } /** Gets methodForMQLengthCalc */ public StringSpec getMethodForMQLengthCalc() { return methodForMQLengthCalc; } /** Sets methodForMQTermination */ public void setMethodForMQTermination(String values) { String[] strTerm = {"near_opt","easy","predict","full"}; methodForMQTermination = new StringSpec(numTiles, numComponents, ModuleSpec.SPEC_TYPE_TILE_COMP, "near_opt", strTerm, this, values); } /** Gets methodForMQTermination */ public StringSpec getMethodForMQTermination() { return methodForMQTermination; } /** Sets codeSegSymbol */ public void setCodeSegSymbol(String values) { String[] strBoolean = {"true","false"}; codeSegSymbol = new StringSpec(numTiles, numComponents, ModuleSpec.SPEC_TYPE_TILE_COMP, "false", strBoolean, this, values); } /** Gets codeSegSymbol */ public StringSpec getCodeSegSymbol() { return codeSegSymbol; } /** Sets causalCXInfo */ public void setCausalCXInfo(String values) { String[] strBoolean = {"true","false"}; causalCXInfo = new StringSpec(numTiles, numComponents, ModuleSpec.SPEC_TYPE_TILE_COMP, "false", strBoolean, this, values); } /** Gets causalCXInfo */ public StringSpec getCausalCXInfo() { return causalCXInfo; } /** Sets terminateOnByte */ public void setTerminateOnByte(String values) { String[] strBoolean = {"true","false"}; terminateOnByte = new StringSpec(numTiles, numComponents, ModuleSpec.SPEC_TYPE_TILE_COMP, "false", strBoolean, this, values); } /** Gets terminateOnByte */ public StringSpec getTerminateOnByte() { return terminateOnByte; } /** Sets resetMQ */ public void setResetMQ(String values) { String[] strBoolean = {"true","false"}; resetMQ = new StringSpec(numTiles, numComponents, ModuleSpec.SPEC_TYPE_TILE_COMP, "false", strBoolean, this, values); } /** Gets resetMQ */ public StringSpec getResetMQ() { return resetMQ; } /** Sets bypass */ public void setBypass(String values) { String[] strBoolean = {"true","false"}; bypass = new StringSpec(numTiles, numComponents, ModuleSpec.SPEC_TYPE_TILE_COMP, "false", strBoolean, this, values); } /** Gets bypass */ public StringSpec getBypass() { return bypass; } /** Sets codeBlockSize */ public void setCodeBlockSize(String values) { codeBlockSize = new CBlkSizeSpec(numTiles, numComponents, ModuleSpec.SPEC_TYPE_TILE_COMP, this, values); } /** Gets codeBlockSize */ public CBlkSizeSpec getCodeBlockSize() { return codeBlockSize; } /** Sets precinctPartition */ public void setPrecinctPartition(String values) { String[] strBoolean = {"true","false"}; if (imgsrc != null) precinctPartition = new PrecinctSizeSpec(numTiles, numComponents, ModuleSpec.SPEC_TYPE_TILE_COMP, new RenderedImageSrc(imgsrc, this, null), decompositionLevel, this, values); else if (raster != null) precinctPartition = new PrecinctSizeSpec(numTiles, numComponents, ModuleSpec.SPEC_TYPE_TILE_COMP, new RenderedImageSrc(raster, this, null), decompositionLevel, this, values); } /** Gets precinctPartition */ public PrecinctSizeSpec getPrecinctPartition() { return precinctPartition; } /** Sets SOP */ public void setSOP(String values) { String[] strBoolean = {"true","false"}; SOP = new StringSpec(numTiles, numComponents, ModuleSpec.SPEC_TYPE_TILE_COMP, "false", strBoolean, this, values); } /** Gets SOP */ public StringSpec getSOP() { return SOP; } /** Sets EPH */ public void setEPH(String values) { String[] strBoolean = {"true","false"}; EPH = new StringSpec(numTiles, numComponents, ModuleSpec.SPEC_TYPE_TILE_COMP, "false", strBoolean, this, values); } /** Gets EPH */ public StringSpec getEPH() { return EPH; } /** Sets progressionName */ public void setProgressionName(String values) { progressionName = values; } /** Gets progressionType */ public String getProgressionName() { return progressionName; } /** Sets progressionType */ public void setProgressionType(LayersInfo lyrs, String values) { String[] strBoolean = {"true","false"}; progressionType = new ProgressionSpec(numTiles, numComponents, lyrs.getTotNumLayers(), decompositionLevel, ModuleSpec.SPEC_TYPE_TILE_COMP, this, values); } /** Gets progressionType */ public ProgressionSpec getProgressionType() { return progressionType; } /** Sets the startLevelROI */ public void setStartLevelROI(int value) { startLevelROI = value; } /** Gets startLevel */ public int getStartLevelROI() { return startLevelROI; } /** Sets the layers */ public void setLayers(String value) { layers = value; } /** Gets layers */ public String getLayers() { return layers; } /** Sets minX */ public void setMinX(int minX) { this.minX = minX; } /** Gets minX */ public int getMinX() { return minX; } /** Sets minY */ public void setMinY(int minY) { this.minY = minY; } /** Gets minY */ public int getMinY() { return minY; } /** Gets the number of tiles */ public int getNumTiles() { Rectangle sourceRegion = getSourceRegion(); if (sourceRegion == null) { if (imgsrc != null) sourceRegion = new Rectangle(imgsrc.getMinX(), imgsrc.getMinY(), imgsrc.getWidth(), imgsrc.getHeight()); else sourceRegion = raster.getBounds(); } else { if (imgsrc != null) sourceRegion = sourceRegion.intersection(new Rectangle(imgsrc.getMinX(), imgsrc.getMinY(), imgsrc.getWidth(), imgsrc.getHeight())); else sourceRegion = sourceRegion.intersection(raster.getBounds()); } int scaleX = getSourceXSubsampling(); int scaleY = getSourceYSubsampling(); int xOffset = getSubsamplingXOffset(); int yOffset = getSubsamplingYOffset(); int w = (sourceRegion.width - xOffset + scaleX - 1) / scaleX; int h = (sourceRegion.height - yOffset + scaleY - 1) / scaleY; minX = (sourceRegion.x + xOffset) / scaleX; minY = (sourceRegion.y + yOffset) / scaleY; numTiles = (int)((Math.floor((minX + w + tileWidth - 1.0) / tileWidth) - Math.floor((double)minX/tileWidth) ) * (Math.floor((minY + h + tileHeight - 1.0) / tileHeight) - Math.floor((double)minY/tileHeight) ) ); tileGridXOffset += (minX - tileGridXOffset) / tileWidth * tileWidth; tileGridYOffset += (minY - tileGridYOffset) / tileHeight * tileHeight; return numTiles; } /** Gets the number of components */ public int getNumComponents() { return numComponents; } /** Override the method setSourceBands in the super class. This method * should be called before any tile-specific parameter setting method * to be called. */ public void setSourceBands(int[] bands) { super.setSourceBands(bands); if (bands != null) { numComponents = bands.length; setDefaults(); } } /** Override the method setTiling in the super class. This method * should be called before any tile-specific parameter setting method * to be called. */ public void setTiling(int tw, int th, int xOff, int yOff) { super.setTiling(tw, th, xOff, yOff); getNumTiles(); setDefaults(); } /** Override the method setSourceSubsampling in the super class. This * method should be called before any tile-specific parameter setting * method to be called. */ public void setSourceSubsampling(int sx, int sy, int xOff, int yOff) { super.setSourceSubsampling(sx, sy, xOff, yOff); getNumTiles(); setDefaults(); } } ././@LongLink0000000000000000000000000000015600000000000011567 Lustar rootrootjai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/jpeg2000/J2KImageWriterCodecLib.javajai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/jpeg2000/J2KImageWriterCode0000664000175100017510000007641210505066255032143 0ustar tilletille/* * $RCSfile: J2KImageWriterCodecLib.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.3 $ * $Date: 2006-09-22 23:07:25 $ * $State: Exp $ */ package com.sun.media.imageioimpl.plugins.jpeg2000; import java.awt.Point; import java.awt.Rectangle; import java.awt.image.ColorModel; import java.awt.image.DataBuffer; import java.awt.image.DataBufferByte; import java.awt.image.IndexColorModel; import java.awt.image.Raster; import java.awt.image.RenderedImage; import java.awt.image.SampleModel; import java.awt.image.WritableRaster; import java.io.IOException; import java.util.Arrays; import java.util.List; import javax.imageio.IIOImage; import javax.imageio.IIOException; import javax.imageio.ImageTypeSpecifier; import javax.imageio.ImageWriteParam; import javax.imageio.ImageWriter; import javax.imageio.metadata.IIOMetadata; import javax.imageio.metadata.IIOMetadataFormatImpl; import javax.imageio.metadata.IIOMetadataNode; import javax.imageio.metadata.IIOInvalidTreeException; import javax.imageio.spi.ImageWriterSpi; import javax.imageio.stream.ImageOutputStream; import com.sun.media.imageio.plugins.jpeg2000.J2KImageWriteParam; import com.sun.media.imageioimpl.common.ImageUtil; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import com.sun.medialib.codec.jp2k.CompParams; import com.sun.medialib.codec.jp2k.Constants; import com.sun.medialib.codec.jp2k.Encoder; import com.sun.medialib.codec.jp2k.Params; import com.sun.medialib.codec.jp2k.Size; import com.sun.medialib.codec.jiio.*; public class J2KImageWriterCodecLib extends ImageWriter { /** When the writing is aborted, RenderedImageSrc throws a * RuntimeException. */ public static String WRITE_ABORTED = "Write aborted."; /** The output stream to write into */ private ImageOutputStream stream = null; /** The metadata format object. */ private J2KMetadataFormat format; /** medialib encoder. */ private Encoder encoder; /** size parameters for medialib. */ private Size size; /** The tile width for encoding */ private int tileWidth; /** The tile height for encoding */ private int tileHeight; /** The tile grid offset for encoding */ private int tileXOffset, tileYOffset; /** The source -> destination transformation */ private int scaleX, scaleY, xOffset, yOffset; /** The source bands to be encoded. */ private int[] sourceBands = null; /** The number of components in the image */ private int numComp; private RenderedImage input; private J2KImageWriteParam param; /** The input source raster. */ private Raster inputRaster; private Rectangle destinationRegion = null; private SampleModel sampleModel; /** Coordinate transform or sub selection is needed before encoding. */ private boolean noTransform = true; private boolean noSubband = true; /** Indicates a raster rather than a RenderedImage * to be encoded. */ private boolean writeRaster = false; /** Constructs J2KImageWriter based on the provided * ImageWriterSpi. */ public J2KImageWriterCodecLib(ImageWriterSpi originator) { super(originator); } public void setOutput(Object output) { super.setOutput(output); // validates output if (output != null) { if (!(output instanceof ImageOutputStream)) throw new IllegalArgumentException(I18N.getString("J2KImageWriter0")); this.stream = (ImageOutputStream)output; } else this.stream = null; } public ImageWriteParam getDefaultWriteParam() { return new J2KImageWriteParam(); } public IIOMetadata convertStreamMetadata(IIOMetadata inData, ImageWriteParam param) { return null; } public void write(IIOMetadata streamMetadata, IIOImage image, ImageWriteParam param) throws java.io.IOException { if (stream == null) { throw new IllegalStateException(I18N.getString("J2KImageWriterMedialib1")); } if (image == null) { throw new IllegalArgumentException(I18N.getString("J2KImageWriterMedialib2")); } clearAbortRequest(); processImageStarted(0); encoder = new Encoder(stream); writeRaster = image.hasRaster(); ColorModel colorModel = null; if (writeRaster) { inputRaster = image.getRaster(); sampleModel = inputRaster.getSampleModel(); } else { input = image.getRenderedImage(); sampleModel = input.getSampleModel(); colorModel = input.getColorModel(); } if (param == null) param = new J2KImageWriteParam(); if(param instanceof J2KImageWriteParam) { J2KImageWriteParam j2kParam = (J2KImageWriteParam)param; if (!writeRaster && input.getColorModel() instanceof IndexColorModel) { j2kParam.setLossless(true); j2kParam.setEncodingRate(Double.MAX_VALUE); j2kParam.setFilter(J2KImageWriteParam.FILTER_53); } else if (j2kParam.getEncodingRate() == Double.MAX_VALUE) { j2kParam.setLossless(true); j2kParam.setFilter(J2KImageWriteParam.FILTER_53); } } setParameters(param); Rectangle sourceRegion = param.getSourceRegion(); if (sourceRegion == null) { if (writeRaster) sourceRegion = inputRaster.getBounds(); else sourceRegion = new Rectangle(input.getMinX(), input.getMinY(), input.getWidth(), input.getHeight()); } else { if (writeRaster) sourceRegion = sourceRegion.intersection(inputRaster.getBounds()); else sourceRegion = sourceRegion.intersection(new Rectangle(input.getMinX(), input.getMinY(), input.getWidth(), input.getHeight())); } if (sourceRegion.isEmpty()) throw new RuntimeException(I18N.getString("J2KImageWriterCodecLib0")); try { tileWidth = param.getTileWidth(); tileHeight = param.getTileHeight(); tileXOffset = param.getTileGridXOffset(); tileYOffset = param.getTileGridYOffset(); } catch (IllegalStateException e) { param.setTilingMode(ImageWriteParam.MODE_EXPLICIT); if (writeRaster) { param.setTiling(inputRaster.getWidth(), inputRaster.getHeight(), inputRaster.getMinX(), inputRaster.getMinY()); } else { param.setTiling(input.getTileWidth(), input.getTileHeight(), input.getTileGridXOffset(), input.getTileGridYOffset()); } tileWidth = param.getTileWidth(); tileHeight = param.getTileHeight(); tileXOffset = param.getTileGridXOffset(); tileYOffset = param.getTileGridYOffset(); } scaleX = param.getSourceXSubsampling(); scaleY = param.getSourceYSubsampling(); xOffset = param.getSubsamplingXOffset(); yOffset = param.getSubsamplingYOffset(); sourceRegion.translate(xOffset, yOffset); sourceRegion.width -= xOffset; sourceRegion.height -= yOffset; xOffset = sourceRegion.x % scaleX; yOffset = sourceRegion.y % scaleY; int minX = sourceRegion.x / scaleX; int minY = sourceRegion.y / scaleY; int w = (sourceRegion.width + scaleX - 1) / scaleX; int h = (sourceRegion.height + scaleY - 1) / scaleY; tileXOffset += (minX - tileXOffset)/tileWidth * tileWidth; tileYOffset += (minY - tileYOffset)/tileHeight * tileHeight; destinationRegion = new Rectangle(minX, minY, w, h); if (!destinationRegion.equals(sourceRegion) || tileWidth != sampleModel.getWidth() || tileHeight != sampleModel.getHeight() || (!writeRaster && (tileXOffset != input.getTileGridXOffset() || tileYOffset != input.getTileGridYOffset())) || (writeRaster && (tileXOffset != inputRaster.getMinX() || tileYOffset != inputRaster.getMinY()))) noTransform = false; numComp = sampleModel.getNumBands(); sourceBands = param.getSourceBands(); if (sourceBands != null) { sampleModel = sampleModel.createSubsetSampleModel(sourceBands); colorModel = null; noSubband = false; } else { sourceBands = new int[numComp]; for (int i = 0; i < numComp; i++) sourceBands[i] = i; } numComp = sourceBands.length; sampleModel = sampleModel.createCompatibleSampleModel(tileWidth, tileHeight); setSize(); setCompParameters(colorModel, sampleModel, param); encoder.setMode(Constants.JP2K_COMPOSITE_TILE); /* XXX J2KMetadata metadata = (J2KMetadata)image.getMetadata(); ImageTypeSpecifier type = null; if (colorModel != null) type = new ImageTypeSpecifier(colorModel, sampleModel); J2KMetadata metadata1 = new J2KMetadata(colorModel, sampleModel, destinationRegion.width, destinationRegion.height, param, this); if (metadata == null) metadata = metadata1; else metadata.mergeTree("com_sun_media_imageio_plugins_jpeg2000_image_1.0", metadata1.getAsTree("com_sun_media_imageio_plugins_jpeg2000_image_1.0")); */ //write the metadata if (!((J2KImageWriteParam)param).getWriteCodeStreamOnly()) { IIOMetadata inMetadata = image.getMetadata(); J2KMetadata metadata1 = new J2KMetadata(colorModel, sampleModel, destinationRegion.width, destinationRegion.height, param, this); J2KMetadata metadata = null; if (inMetadata == null) { metadata = metadata1; } else { // Convert the input metadata tree to a J2KMetadata. if(colorModel != null) { ImageTypeSpecifier imageType = new ImageTypeSpecifier(colorModel, sampleModel); metadata = (J2KMetadata)convertImageMetadata(inMetadata, imageType, param); } else { String metaFormat = null; List metaFormats = Arrays.asList(inMetadata.getMetadataFormatNames()); if(metaFormats.contains(J2KMetadata.nativeMetadataFormatName)) { // Initialize from native image metadata format. metaFormat = J2KMetadata.nativeMetadataFormatName; } else if(inMetadata.isStandardMetadataFormatSupported()) { // Initialize from standard metadata form of the // input tree. metaFormat = IIOMetadataFormatImpl.standardMetadataFormatName; } metadata = new J2KMetadata(); if(metaFormat != null) { metadata.setFromTree(metaFormat, inMetadata.getAsTree(metaFormat)); } } metadata.mergeTree(J2KMetadata.nativeMetadataFormatName, metadata1.getAsTree(J2KMetadata.nativeMetadataFormatName)); } writeMetadata(metadata); } else { encoder.setEncodeCodeStreamOnly(); } for (int y = getMinTileY(); y <= getMaxTileY(); y++) { for (int x = getMinTileX(); x <= getMaxTileX(); x++) { Raster currentTile = getTile(x, y); int sourceFormatTag = MediaLibAccessor.findCompatibleTag(currentTile); MediaLibAccessor accessor = new MediaLibAccessor(currentTile, currentTile.getBounds(), sourceFormatTag, true); mediaLibImage[] mlImage = accessor.getMediaLibImages(); encoder.encode(mlImage, x + y * size.nxtiles); float percentage = (x + y * size.nxtiles + 1.0F) / (size.nxtiles * size.nytiles); processImageProgress(percentage * 100.0F); } } } public IIOMetadata getDefaultImageMetadata(ImageTypeSpecifier imageType, ImageWriteParam param) { return new J2KMetadata(imageType, param, this); } public IIOMetadata getDefaultStreamMetadata(ImageWriteParam param) { return null; } public IIOMetadata convertImageMetadata(IIOMetadata inData, ImageTypeSpecifier imageType, ImageWriteParam param) { // Check arguments. if(inData == null) { throw new IllegalArgumentException("inData == null!"); } if(imageType == null) { throw new IllegalArgumentException("imageType == null!"); } // If it's one of ours, return a clone. if (inData instanceof J2KMetadata) { return (IIOMetadata)((J2KMetadata)inData).clone(); } try { J2KMetadata outData = new J2KMetadata(); List formats = Arrays.asList(inData.getMetadataFormatNames()); String format = null; if(formats.contains(J2KMetadata.nativeMetadataFormatName)) { // Initialize from native image metadata format. format = J2KMetadata.nativeMetadataFormatName; } else if(inData.isStandardMetadataFormatSupported()) { // Initialize from standard metadata form of the input tree. format = IIOMetadataFormatImpl.standardMetadataFormatName; } if(format != null) { outData.setFromTree(format, inData.getAsTree(format)); return outData; } } catch(IIOInvalidTreeException e) { return null; } return null; } public boolean canWriteRasters() { return true; } public synchronized void abort() { super.abort(); } public void reset() { // reset local Java structures super.reset(); stream = null; } /** This method wraps the protected method abortRequested * to allow the abortions be monitored by J2KRenderedImage. */ public boolean getAbortRequest() { return abortRequested(); } private void checkSampleModel(SampleModel sm) { int type = sm.getDataType(); if (type < DataBuffer.TYPE_BYTE || type > DataBuffer.TYPE_INT) throw new IllegalArgumentException(I18N.getString("J2KImageWriter5")); if (sm.getNumBands() > 16384) throw new IllegalArgumentException(I18N.getString("J2KImageWriter6")); } private void writeMetadata(J2KMetadata metadata) throws IOException { if (metadata == null) return; IIOMetadataNode root = (IIOMetadataNode)metadata.getAsTree("com_sun_media_imageio_plugins_jpeg2000_image_1.0"); if (root == null) return; format = (J2KMetadataFormat)metadata.getMetadataFormat("com_sun_media_imageio_plugins_jpeg2000_image_1.0"); writeSuperBox(root); } private void writeSuperBox(IIOMetadataNode node) throws IOException { NodeList list = node.getChildNodes(); String name = node.getNodeName(); if (name.startsWith("JPEG2000")) { /* int length = computeLength(node); byte[] data = new byte[length]; generateSuperBoxContent(node, data, 0); com.sun.medialib.codec.jp2k.Box box = new com.sun.medialib.codec.jp2k.Box(); box.data = data; box.type = Box.getTypeInt((String)Box.getTypeByName(name)); encoder.encodeSuperBox(box.type, new com.sun.medialib.codec.jp2k.Box[]{box}); return; */ /* com.sun.medialib.codec.jp2k.Box box = new com.sun.medialib.codec.jp2k.Box(); box.type = Box.getTypeInt((String)Box.getTypeByName(name)); encoder.encodeSuperBox(box.type, null); */ } for (int i = 0; i < list.getLength(); i++) { IIOMetadataNode child = (IIOMetadataNode)list.item(i); name = child.getNodeName(); if (name.startsWith("JPEG2000") && format.isLeaf(name)) writeBox(child); else writeSuperBox(child); } } private void writeBox(IIOMetadataNode node) throws IOException { com.sun.medialib.codec.jp2k.Box mlibBox = new com.sun.medialib.codec.jp2k.Box(); mlibBox.type = Box.getTypeInt((String)Box.getAttribute(node, "Type")); Box box = Box.createBox(mlibBox.type, node); mlibBox.data = box.getContent(); encoder.encodeBox(mlibBox); } private int computeLength(IIOMetadataNode root) { NodeList list = root.getChildNodes(); int length = 0; for (int i = 0; i < list.getLength(); i++) { IIOMetadataNode node = (IIOMetadataNode)list.item(i); String name = node.getNodeName(); if (format.isLeaf(name)) { String s = (String)Box.getAttribute(node, "Length"); length += new Integer(s).intValue(); } else length += computeLength(node); } return length + (root.getNodeName().startsWith("JPEG2000") ? 8 : 0) ; } private int generateSuperBoxContent(IIOMetadataNode root, byte[] data, int pos) throws IOException { String name = root.getNodeName(); if (name.startsWith("JPEG2000")) { int length = computeLength(root); Box.copyInt(data, pos, length); pos += 4; int type = Box.getTypeInt((String)Box.getTypeByName(name)); Box.copyInt(data, pos, type); pos += 4; } NodeList list = root.getChildNodes(); for (int i = 0; i < list.getLength(); i++) { IIOMetadataNode node = (IIOMetadataNode)list.item(i); name = node.getNodeName(); if (format.isLeaf(name)) { int type = Box.getTypeInt((String)Box.getAttribute(node, "Type")); Box box = Box.createBox(type, node); byte[] data1 = box.getContent(); Box.copyInt(data, pos, data1.length + 8); pos += 4; Box.copyInt(data, pos, type); pos += 4; System.arraycopy(data1, 0, data, pos, data1.length); pos += data1.length; } else { pos = generateSuperBoxContent(node, data, pos); } } return pos; } private Raster getTile(int tileX, int tileY) { int sx = tileXOffset + tileX * tileWidth; int sy = tileYOffset + tileY * tileHeight; Rectangle bounds = new Rectangle(sx, sy, tileWidth, tileHeight); if (writeRaster) { bounds = bounds.intersection(destinationRegion); if (noTransform) { return inputRaster.createChild(bounds.x, bounds.y, bounds.width, bounds.height, bounds.x, bounds.y, sourceBands); } sx = bounds.x; sy = bounds.y; WritableRaster ras = Raster.createWritableRaster(sampleModel, new Point(sx, sy)); int x = mapToSourceX(sx); int y = mapToSourceY(sy); int minY = inputRaster.getMinY(); int maxY = inputRaster.getMinY() + inputRaster.getHeight(); int cTileWidth = bounds.width; int length = (cTileWidth - 1) * scaleX + 1; for (int j = 0; j < bounds.height; j++, sy++, y += scaleY) { if (y < minY || y >= maxY) continue; Raster source = inputRaster.createChild(x, y, length, 1, x, y, null); int tempX = sx; for (int i = 0, offset = x; i < cTileWidth; i++, tempX++, offset += scaleX) { for (int k = 0; k < numComp; k++) { int p = source.getSample(offset, y, sourceBands[k]); ras.setSample(tempX, sy, k, p); } } } return ras; } else { if (noTransform) { Raster ras = input.getTile(tileX, tileY); if (destinationRegion.contains(bounds) && noSubband) return ras; else { bounds = bounds.intersection(destinationRegion); return ras.createChild(bounds.x, bounds.y, bounds.width, bounds.height, bounds.x, bounds.y, sourceBands); } } bounds = bounds.intersection(destinationRegion); sx = bounds.x; sy = bounds.y; WritableRaster ras = Raster.createWritableRaster(sampleModel, new Point(sx, sy)); int x = mapToSourceX(sx); int y = mapToSourceY(sy); int minY = input.getMinY(); int maxY = input.getMinY() + input.getHeight(); int cTileWidth = bounds.width; int length = (cTileWidth -1) * scaleX + 1; for (int j = 0; j < bounds.height; j++, sy++, y += scaleY) { if (y < minY || y >= maxY) continue; Raster source = input.getData(new Rectangle(x, y, length, 1)); int tempX = sx; for (int i = 0, offset = x; i < cTileWidth; i++, tempX++, offset += scaleX) { for (int k = 0; k < numComp; k++) { int p = source.getSample(offset, y, sourceBands[k]); ras.setSample(tempX, sy, k, p); } } } return ras; } } private int mapToSourceX(int x) { return x * scaleX + xOffset; } private int mapToSourceY(int y) { return y * scaleY + yOffset; } private int getMinTileX() { return ToTile(destinationRegion.x, tileXOffset, tileWidth); } private int getMaxTileX() { return ToTile(destinationRegion.x + destinationRegion.width - 1, tileXOffset, tileWidth); } private int getMinTileY() { return ToTile(destinationRegion.y, tileYOffset, tileHeight); } private int getMaxTileY() { return ToTile(destinationRegion.y + destinationRegion.height - 1, tileYOffset, tileHeight); } private static int ToTile(int pos, int tileOffset, int tileSize) { pos -= tileOffset; if (pos < 0) { pos += 1 - tileSize; // force round to -infinity (ceiling) } return pos/tileSize; } private void setSize() { size = new Size(); size.csize = numComp; size.nxtiles = getMaxTileX() - getMinTileX() + 1; size.nytiles = getMaxTileY() - getMinTileY() + 1; size.xosize = destinationRegion.x; size.yosize = destinationRegion.y; size.xsize = destinationRegion.width + destinationRegion.x; size.ysize = destinationRegion.height + destinationRegion.y; size.xtosize = tileXOffset; size.ytosize = tileYOffset; size.xtsize = tileWidth; size.ytsize = tileHeight; encoder.setSize(size); } private void setCompParameters(ColorModel colorModel, SampleModel sampleModel, ImageWriteParam compParamArg) { // Check the parameters. if (colorModel == null && sampleModel == null && (compParamArg == null || !(compParamArg instanceof J2KImageWriteParam))) { return; } // Get the bit depths. int[] bitDepths = null; boolean isSigned = false; if(colorModel != null) { bitDepths = colorModel.getComponentSize(); isSigned = colorModel.getTransferType() == DataBuffer.TYPE_SHORT; } else if(sampleModel != null) { bitDepths = sampleModel.getSampleSize(); isSigned = sampleModel.getDataType() == DataBuffer.TYPE_SHORT; } // Get the number of decomposition levels. int numDecompositionLevels = -1; if(compParamArg != null) { // Cast is safe due to parameter check above. numDecompositionLevels = ((J2KImageWriteParam)compParamArg).getNumDecompositionLevels(); } // Return if nothing to set. if(bitDepths == null && numDecompositionLevels == -1) return; // Check for unequal bit depths. boolean bitDepthVaries = false; if(bitDepths != null) { for(int i = 1; i < bitDepths.length; i++) { if(bitDepths[i] != bitDepths[0]) { bitDepthVaries = true; break; } } } CompParams cp = encoder.getCompParams(null, -1); // Update the COD segment if needed. if((numDecompositionLevels != -1 && numDecompositionLevels != cp.maxlvls) || (bitDepths != null && ((isSigned ? 0x80 : 0x00) | (bitDepths[0] - 1)) != cp.depth)) { if(numDecompositionLevels != -1) { cp.maxlvls = numDecompositionLevels; } // Set the main COD bit depth to bitDepths[0]. if(bitDepths != null) { cp.depth = (isSigned ? 0x80 : 0x00) | (bitDepths[0] - 1); } encoder.setCompParams(cp, -1); } // Update COC segments if needed. if(bitDepthVaries) { // only true if bitDepths != null // Loop over component zero even though unnecessary. for(int i = 0; i < numComp; i++) { cp = encoder.getCompParams(null, i); if(numDecompositionLevels != -1) { cp.maxlvls = numDecompositionLevels; } cp.depth = (isSigned ? 0x80 : 0x00) | (bitDepths[i] - 1); encoder.setCompParams(cp, i); } } } private void setParameters(ImageWriteParam paramArg) { if (paramArg == null || !(paramArg instanceof J2KImageWriteParam)) { return; } J2KImageWriteParam param = (J2KImageWriteParam)paramArg; // set the rate double rate = param.getEncodingRate(); if (rate != Double.MAX_VALUE) { // convert the rate to the medialib definition rate /= ImageUtil.getElementSize(sampleModel); encoder.setRate(rate, 0); } else encoder.setRate(0.0, 0); Params params = new Params(); // set the component transformation flag params.enablemct = param.getComponentTransformation() ? Constants.JP2K_MCT_ENABLE : Constants.JP2K_MCT_DISABLE; // set coding style if (param.getEPH()) params.cstyle |= Constants.JP2K_COD_EPH; if (param.getSOP()) params.cstyle |= Constants.JP2K_COD_SOP; // set the wavelet filter type if (J2KImageWriteParam.FILTER_53.equals(param.getFilter())) params.wavemode = Constants.JP2K_WAVEMODE_53; else if (J2KImageWriteParam.FILTER_97.equals(param.getFilter())) params.wavemode = Constants.JP2K_WAVEMODE_97; //Set the progressive mode String progressiveType = param.getProgressionType(); if ("layer".equals(progressiveType)) params.prgorder = Constants.JP2K_COD_LRCPPRG; if ("res".equals(progressiveType)) params.prgorder = Constants.JP2K_COD_RLCPPRG; if ("res-pos".equals(progressiveType)) params.prgorder = Constants.JP2K_COD_RPCLPRG; if ("pos-comp".equals(progressiveType)) params.prgorder = Constants.JP2K_COD_PCRLPRG; if ("comp-pos".equals(progressiveType)) params.prgorder = Constants.JP2K_COD_CPRLPRG; encoder.setParams(params); } } ././@LongLink0000000000000000000000000000015500000000000011566 Lustar rootrootjai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/jpeg2000/ColorSpecificationBox.javajai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/jpeg2000/ColorSpecification0000664000175100017510000001674710203036165032376 0ustar tilletille/* * $RCSfile: ColorSpecificationBox.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.1 $ * $Date: 2005-02-11 05:01:32 $ * $State: Exp $ */ package com.sun.media.imageioimpl.plugins.jpeg2000; import java.awt.color.ICC_Profile; import javax.imageio.metadata.IIOInvalidTreeException; import javax.imageio.metadata.IIOMetadataNode; import org.w3c.dom.Node; import org.w3c.dom.NodeList; /** This class is defined to represent a Color Specification Box of JPEG JP2 * file format. A Channel Definition Box has a length, and a fixed type * of "colr". Its content contains the method to define the color space, * the precedence and approximation accuracy (0 for JP2 files), the * enumerated color space, and the ICC color profile if any. */ public class ColorSpecificationBox extends Box { /** The enumerated color space defined in JP2 file format. */ public static final int ECS_sRGB = 16; public static final int ECS_GRAY = 17; public static final int ECS_YCC = 18; /** Cache the element names for this box's xml definition */ private static String[] elementNames = {"Method", "Precedence", "ApproximationAccuracy", "EnumeratedColorSpace", "ICCProfile"}; /** This method will be called by the getNativeNodeForSimpleBox of the * class Box to get the element names. */ public static String[] getElementNames() { return elementNames; } /** The elements' values. */ private byte method; private byte precedence; private byte approximation; private int ecs; private ICC_Profile profile; /** Computes the length of this box when profile is present. */ private static int computeLength(byte m, ICC_Profile profile) { int ret = 15; if (m == 2 && profile != null) { ret += profile.getData().length; } return ret; } /** Creates a ColorSpecificationBox from the provided data * elements. */ public ColorSpecificationBox(byte m, byte p, byte a, int ecs, ICC_Profile profile) { super(computeLength(m, profile), 0x636F6C72, null); this.method = m; this.precedence = p; this.approximation = a; this.ecs = ecs; this.profile = profile; } /** Creates a ColorSpecificationBox from the provided byte * array. */ public ColorSpecificationBox(byte[] data) { super(8 + data.length, 0x636F6C72, data); } /** Constructs a ColorSpecificationBox based on the provided * org.w3c.dom.Node. */ public ColorSpecificationBox(Node node) throws IIOInvalidTreeException { super(node); NodeList children = node.getChildNodes(); for (int i = 0; i < children.getLength(); i++) { Node child = children.item(i); String name = child.getNodeName(); if ("Method".equals(name)) { method = Box.getByteElementValue(child); } if ("Precedence".equals(name)) { precedence = Box.getByteElementValue(child); } if ("ApproximationAccuracy".equals(name)) { approximation = Box.getByteElementValue(child); } if ("EnumeratedColorSpace".equals(name)) { ecs = Box.getIntElementValue(child); } if ("ICCProfile".equals(name)) { if (child instanceof IIOMetadataNode) profile = (ICC_Profile)((IIOMetadataNode)child).getUserObject(); else { String value = node.getNodeValue(); if (value != null) profile = ICC_Profile.getInstance(Box.parseByteArray(value)); } } } } /** Returns the method to define the color space. */ public byte getMethod() { return method; } /** Returns Precedence. */ public byte getPrecedence() { return precedence; } /** Returns ApproximationAccuracy. */ public byte getApproximationAccuracy() { return approximation; } /** Returns the enumerated color space. */ public int getEnumeratedColorSpace() { return ecs; } /** Returns the ICC color profile in this color specification box. */ public ICC_Profile getICCProfile() { return profile; } /** Creates an IIOMetadataNode from this color specification * box. The format of this node is defined in the XML dtd and xsd * for the JP2 image file. */ public IIOMetadataNode getNativeNode() { return getNativeNodeForSimpleBox(); } protected void parse(byte[] data) { method = data[0]; precedence = data[1]; approximation = data[2]; if (method == 2) { byte[] proData = new byte[data.length - 3]; System.arraycopy(data, 3, proData, 0, data.length - 3); profile = ICC_Profile.getInstance(proData); } else ecs = ((data[3] & 0xFF) << 24) | ((data[4] & 0xFF) << 16) | ((data[5] & 0xFF) << 8) | (data[6] & 0xFF); } protected void compose() { if (data != null) return; int len = 7; byte[] profileData = null; if (profile != null) { profileData = profile.getData(); len += profileData.length; } data = new byte[len]; data[0] = (byte)method; data[1] = (byte)precedence; data[2] = (byte)approximation; copyInt(data, 3, ecs); if (profile != null) System.arraycopy(profileData, 0, data, 7, len - 7); } } ././@LongLink0000000000000000000000000000016200000000000011564 Lustar rootrootjai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/jpeg2000/J2KMetadataFormatResources.javajai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/jpeg2000/J2KMetadataFormatR0000664000175100017510000003241410203036165032126 0ustar tilletille/* * $RCSfile: J2KMetadataFormatResources.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.1 $ * $Date: 2005-02-11 05:01:35 $ * $State: Exp $ */ package com.sun.media.imageioimpl.plugins.jpeg2000; import java.util.*; public class J2KMetadataFormatResources extends ListResourceBundle { static final Object[][] contents = { // Node name, followed by description {"JPEG2000SignatureBox", "The JPEG 2000 signature box."}, {"JPEG2000FileTypeBox", "The JPEG 2000 file type box."}, {"OtherBoxes", "All the boxes other than the signature or file type box."}, {"HeaderCStream", "The super box conatins the header and code stream box."}, {"JPEG2000IntellectualPropertyRightsBox", "The JPEG 2000 intellectual property rights box."}, {"JPEG2000XMLBox", "The JPEG 2000 XML box."}, {"JPEG2000UUIDBox", "The JPEG 2000 UUID box."}, {"JPEG2000UUIDInfoBox", "The JPEG 2000 UUID information box."}, {"JPEG2000HeaderSuperBox", "The JPEG 2000 header super box."}, {"JPEG2000CodeStreamBox", "The JPEG 2000 code stream box."}, {"JPEG2000HeaderBox", "The JPEG 2000 header box."}, {"OptionalBoxes", "The optional boxes in the header super box."}, {"JPEG2000BitsPerComponentBox", "The JPEG2000 bits per component box."}, {"JPEG2000ColorSpecificationBox", "The JPEG 2000 color specification box."}, {"JPEG2000PaletteBox", "The JPEG 2000 palette box."}, {"JPEG2000ComponentMappingBox", "The JPEG 2000 component mapping box."}, {"JPEG2000ChannelDefinitionBox", "The JPEG 2000 channel definition box."}, {"JPEG2000ResolutionBox", "The JPEG 2000 resolution box."}, {"JPEG2000CaptureResolutionBox", "The JPEG 2000 capture resolution box"}, {"JPEG2000DefaultDisplayResolutionBox", "The JPEG 2000 default display resolution box"}, {"JPEG2000UUIDListBox", "The JPEG 2000 UUID list box."}, {"JPEG2000DataEntryURLBox", "The JPEG 2000 data entry URL box."}, // Elements in JPEG2000FileTypeBox {"Brand", "The brand of JPEG 2000 file. For JP2 file, it is \"jp2 \""}, {"MinorVersion", "The minor version of JPEG 2000 file. For JP2 file, it is 0"}, {"CompatibilityList", "The compatibility list. For non-JP2 file, at least one is \"jp2 \""}, // Elements of JPEG2000HeaderBox {"Width", "The width of the image."}, {"Height", "The height of the image."}, {"NumComponents", "The number of image components in this image file."}, {"BitDepth", "Bit depths for all the image components or for each of the component if it is a array."}, {"CompressionType", "The compression type. Always be 7 for JP2 file."}, {"UnknownColorspace", "Whether the color space is known or not."}, {"IntellectualProperty", "Whether intellectual property in included in this image."}, {"Method", "The method to define the color space. 1 by ECS; 2 by profile."}, {"Precedence", "Precedence. Be 0 for JP2 file."}, {"ApproximationAccuracy", "Approximation accuracy. Be 0 for JP2 file"}, {"EnumeratedColorSpace", "Enumerated color space. 16: sRGB. 17: Gray"}, {"ICCProfile", "The ICC profile used to define the color space"}, {"NumberEntries", "The number of palette entries."}, {"NumberColors", "The number of color components."}, {"BitDepth", "The bit depths for the output components after LUT."}, {"LUT", "The LUT for the palette."}, {"LUTRow", " A row of the LUT."}, {"Component", "A component in the component mapping box."}, {"ComponentType", "The type of one component: itself or lut column."}, {"ComponentAssociation", "The LUT column used to define this component."}, {"NumberOfDefinition", "The number of definitions in channel definition box."}, {"Definitions", "Defines one channel."}, {"ChannelNumber", "The channel number."}, {"ChannelType", "The channel type: color, alpha, premultiplied alpha."}, {"ChannelAssociation", "The association of this channel to the color space."}, {"VerticalResolutionNumerator", "The vertical resolution numerator."}, {"VerticalResolutionDenominator", "The vertical resolution denominator."}, {"HorizontalResolutionNumerator", "The horizontal resolution numerator."}, {"HorizontalResolutionDenominator", "The horizontal resolution denominator."}, {"VerticalResolutionExponent", "The vertical resolution exponent."}, {"HorizontalResolutionExponent", "The horizontal resolution exponent."}, {"CodeStream", "The data of the code stream."}, {"Content", "The intellectual property rights or XML."}, {"UUID", "The UUID."}, {"Data", "The data of the UUID."}, {"NumberUUID", "The number of UUID in the UUID list box."}, {"Version", "The version. Always be 0 for JP2 file."}, {"Flags", "The flags. Always be 0 for JP2 file."}, {"URL", "The URL"}, // Node name + "/" + AttributeName, followed by description {"JPEG2000SignatureBox/Length", "The length of the signature box. Always be 12."}, {"JPEG2000SignatureBox/Type", "The type of the signature box. Always be \"jP \""}, {"JPEG2000SignatureBox/Signature", "The content of the signature box. Always be 0D0A870A."}, {"JPEG2000FileTypeBox/Length", "The length of the file type box."}, {"JPEG2000FileTypeBox/Type", "The type of the file type box. Always be \"ftpy\""}, {"JPEG2000FileTypeBox/ExtraLength", "The extra length of the file type box. Optional. Set when Length = 1"}, {"JPEG2000HeaderSuperBox/Length", "The length of the header super box."}, {"JPEG2000HeaderSuperBox/Type", "The type of the header super box. Always be \"jp2h\""}, {"JPEG2000HeaderSuperBox/ExtraLength", "The extra length of the header super box. Optional. Set when Length = 1"}, {"JPEG2000HeaderBox/Length", "The length of the header box."}, {"JPEG2000HeaderBox/Type", "The type of the header box. Always be \"ihdr\""}, {"JPEG2000HeaderBox/ExtraLength", "The extra length of the header box. Optional. Set when Length = 1"}, {"JPEG2000BitsPerComponentBox/Length", "The length of the bits per component box."}, {"JPEG2000BitsPerComponentBox/Type", "The type of the bits per component box. Always be \"bpcc\""}, {"JPEG2000BitsPerComponentBox/ExtraLength", "The extra length of the bits per component box. Optional. Set when Length = 1"}, {"JPEG2000ColorSpecificationBox/Length", "The length of the bits per component box."}, {"JPEG2000ColorSpecificationBox/Type", "The type of the bits per component box. Always be \"colr\""}, {"JPEG2000ColorSpecificationBox/ExtraLength", "The extra length of the bits per component box. Optional. Set when Length = 1"}, {"JPEG2000PaletteBox/Length", "The length of the palette box."}, {"JPEG2000PaletteBox/Type", "The type of the palette box. Always be \"pclr\""}, {"JPEG2000PaletteBox/ExtraLength", "The extra length of the palette box. Optional. Set when Length = 1"}, {"JPEG2000ComponentMappingBox/Length", "The length of the component mapping box."}, {"JPEG2000ComponentMappingBox/Type", "The type of the component mapping box. Always be \"cmap\""}, {"JPEG2000ComponentMappingBox/ExtraLength", "The extra length of the component mapping box. Optional. Set when Length = 1"}, {"JPEG2000ChannelDefinitionBox/Length", "The length of the channel definition box."}, {"JPEG2000ChannelDefinitionBox/Type", "The type of the channel definition box. Always be \"cdef\""}, {"JPEG2000ChannelDefinitionBox/ExtraLength", "The extra length of the channel definition box. Optional. Set when Length = 1"}, {"JPEG2000ResolutionBox/Length", "The length of the resolution box."}, {"JPEG2000ResolutionBox/Type", "The type of the resolution box. Always be \"res \""}, {"JPEG2000ResolutionBox/ExtraLength", "The extra length of the resolution box. Optional. Set when Length = 1"}, {"JPEG2000CaptureResolutionBox/Length", "The length of the capture resolution box."}, {"JPEG2000CaptureResolutionBox/Type", "The type of the capture resolution box. Always be \"resc\""}, {"JPEG2000CaptureResolutionBox/ExtraLength", "The extra length of the capture resolution box. Optional. Set when Length = 1"}, {"JPEG2000DefaultDisplayResolutionBox/Length", "The length of the default display resolution box."}, {"JPEG2000DefaultDisplayResolutionBox/Type", "The type of the default display resolution box. Always be \"resd\""}, {"JPEG2000DefaultDisplayResolutionBox/ExtraLength", "The extra length of the default display resolution box. Optional. Set when Length = 1"}, {"JPEG2000CodeStreamBox/Length", "The length of the code stream box."}, {"JPEG2000CodeStreamBox/Type", "The type of the code stream box. Always be \"jp2c\""}, {"JPEG2000CodeStreamBox/ExtraLength", "The extra length of the code stream box. Optional. Set when Length = 1"}, {"JPEG2000IntellectualPropertyRightsBox/Length", "The length of the intellectual property rights box."}, {"JPEG2000IntellectualPropertyRightsBox/Type", "The type of the intellectual property rights box. Always be \"jp2i\""}, {"JPEG2000IntellectualPropertyRightsBox/ExtraLength", "The extra length of the intellectual property rights box. Optional. Set when Length = 1"}, {"JPEG2000XMLBox/Length", "The length of the XML box."}, {"JPEG2000XMLBox/Type", "The type of the XML box. Always be \"xml \""}, {"JPEG2000XMLBox/ExtraLength", "The extra length of the XML box. Optional. Set when Length = 1"}, {"JPEG2000UUIDBox/Length", "The length of the UUID box."}, {"JPEG2000UUIDBox/Type", "The type of the UUID box. Always be \"uuid\""}, {"JPEG2000UUIDBox/ExtraLength", "The extra length of the UUID box. Optional. Set when Length = 1"}, {"JPEG2000UUIDInfoBox/Length", "The length of the UUID information box."}, {"JPEG2000UUIDInfoBox/Type", "The type of the UUID information box. Always be \"uinf\""}, {"JPEG2000UUIDInfoBox/ExtraLength", "The extra length of the UUID information box. Optional. Set when Length = 1"}, {"JPEG2000UUIDListBox/Length", "The length of the UUID list box."}, {"JPEG2000UUIDListBox/Type", "The type of the UUID list box. Always be \"ulst\""}, {"JPEG2000UUIDListBox/ExtraLength", "The extra length of the UUID list box. Optional. Set when Length = 1"}, {"JPEG2000DataEntryURLBox/Length", "The length of the data entry URL box."}, {"JPEG2000DataEntryURLBox/Type", "The type of the data entry URL box. Always be \"ulst\""}, {"JPEG2000DataEntryURLBox/ExtraLength", "The extra length of the data entry URL box. Optional. Set when Length = 1"}, }; public J2KMetadataFormatResources() { } protected Object[][] getContents() { return contents; } } ././@LongLink0000000000000000000000000000015300000000000011564 Lustar rootrootjai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/jpeg2000/BitsPerComponentBox.javajai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/jpeg2000/BitsPerComponentBo0000664000175100017510000000671110203036165032321 0ustar tilletille/* * $RCSfile: BitsPerComponentBox.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.1 $ * $Date: 2005-02-11 05:01:31 $ * $State: Exp $ */ package com.sun.media.imageioimpl.plugins.jpeg2000; import javax.imageio.metadata.IIOInvalidTreeException; import javax.imageio.metadata.IIOMetadataNode; import org.w3c.dom.Node; import org.w3c.dom.NodeList; /** This class is defined to represent a Bits Per Component Box of JPEG * JP2 file format. A Bits Per Component box has a length, and a fixed * type of "bpcc". Its content is a byte array containing the bit * depths of the color components. * * This box is necessary only when the bit depth are not identical for all * the components. */ public class BitsPerComponentBox extends Box { /** Counstructs a BitsPerComponentBox from the provided * byte array containing the bit depths of each color component. */ public BitsPerComponentBox(byte[] bitDepth) { super(8 + bitDepth.length, 0x62706363, null); data = bitDepth; } /** Constructs a BitsPerComponentBox based on the provide * org.w3c.dom.Node. */ public BitsPerComponentBox(Node node) throws IIOInvalidTreeException { super(node); NodeList children = node.getChildNodes(); for (int i = 0; i < children.getLength(); i++) { Node child = children.item(i); String name = child.getNodeName(); if ("BitDepth".equals(name)) { data = Box.getByteArrayElementValue(child); } } } /** Returns the bit depths for all the image components. */ public byte[] getBitDepth() { return data; } } ././@LongLink0000000000000000000000000000016100000000000011563 Lustar rootrootjai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/jpeg2000/J2KImageWriterCodecLibSpi.javajai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/jpeg2000/J2KImageWriterCode0000664000175100017510000001225710413303155032127 0ustar tilletille/* * $RCSfile: J2KImageWriterCodecLibSpi.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.2 $ * $Date: 2006-03-31 19:43:39 $ * $State: Exp $ */ package com.sun.media.imageioimpl.plugins.jpeg2000; import java.awt.image.DataBuffer; import java.awt.image.SampleModel; import javax.imageio.spi.ImageWriterSpi; import javax.imageio.spi.ServiceRegistry; import javax.imageio.spi.IIORegistry; import javax.imageio.ImageWriter; import javax.imageio.ImageTypeSpecifier; import javax.imageio.IIOException; import java.awt.image.ColorModel; import java.awt.image.IndexColorModel; import java.util.Locale; import com.sun.media.imageioimpl.common.PackageUtil; public class J2KImageWriterCodecLibSpi extends ImageWriterSpi { private static String [] readerSpiNames = {"com.sun.media.imageioimpl.plugins.jpeg2000.J2KImageReaderCodecLibSpi"}; private static String[] formatNames = {"jpeg 2000", "JPEG 2000", "jpeg2000", "JPEG2000"}; private static String[] extensions = {"jp2"}; // Should add jpx or jpm private static String[] mimeTypes = {"image/jp2", "image/jpeg2000"}; private boolean registered = false; public J2KImageWriterCodecLibSpi() { super(PackageUtil.getVendor(), PackageUtil.getVersion(), formatNames, extensions, mimeTypes, "com.sun.media.imageioimpl.plugins.jpeg2000.J2KImageWriterCodecLib", STANDARD_OUTPUT_TYPE, readerSpiNames, false, null, null, null, null, true, "com_sun_media_imageio_plugins_jpeg2000_image_1.0", "com.sun.media.imageioimpl.plugins.jpeg2000.J2KMetadataFormat", null, null); } public String getDescription(Locale locale) { String desc = PackageUtil.getSpecificationTitle() + " natively-accelerated JPEG 2000 Image Writer"; return desc; } public void onRegistration(ServiceRegistry registry, Class category) { if (registered) { return; } registered = true; // Branch based on codecLib availability. if(!PackageUtil.isCodecLibAvailable()) { // Deregister provider. registry.deregisterServiceProvider(this); } else { // Set pairwise ordering to give codecLib writer precedence. Class javaWriterSPIClass = null; try { javaWriterSPIClass = Class.forName("com.sun.media.imageioimpl.plugins.jpeg2000.J2KImageWriterSpi"); } catch(Throwable t) { // Ignore it. } if(javaWriterSPIClass != null) { Object javaWriterSPI = registry.getServiceProviderByClass(javaWriterSPIClass); if(javaWriterSPI != null) { registry.setOrdering(category, this, javaWriterSPI); } } } } public boolean canEncodeImage(ImageTypeSpecifier type) { SampleModel sm = type.getSampleModel(); if (sm.getNumBands() > 16384) return false; if (sm.getDataType() < DataBuffer.TYPE_BYTE || sm.getDataType() > DataBuffer.TYPE_INT) return false; return true; } public ImageWriter createWriterInstance(Object extension) throws IIOException { return new J2KImageWriterCodecLib(this); } } ././@LongLink0000000000000000000000000000015000000000000011561 Lustar rootrootjai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/jpeg2000/MediaLibAccessor.javajai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/jpeg2000/MediaLibAccessor.j0000664000175100017510000014011010203036165032156 0ustar tilletille/* * $RCSfile: MediaLibAccessor.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.1 $ * $Date: 2005-02-11 05:01:36 $ * $State: Exp $ */ package com.sun.media.imageioimpl.plugins.jpeg2000; import java.awt.Rectangle; import java.awt.image.ColorModel; import java.awt.image.ComponentSampleModel; import java.awt.image.ComponentColorModel; import java.awt.image.DataBuffer; import java.awt.image.DataBufferByte; import java.awt.image.DataBufferDouble; import java.awt.image.DataBufferFloat; import java.awt.image.DataBufferInt; import java.awt.image.DataBufferShort; import java.awt.image.DataBufferUShort; import java.awt.image.MultiPixelPackedSampleModel; import java.awt.image.Raster; import java.awt.image.SampleModel; import java.awt.image.WritableRaster; import java.awt.image.RenderedImage; import java.awt.image.renderable.ParameterBlock; import java.io.FileNotFoundException; import java.io.FilePermission; import java.io.InputStream; import java.io.IOException; import java.lang.NoClassDefFoundError; import java.security.AccessControlException; import java.security.AccessController; import java.security.PrivilegedAction; import com.sun.media.imageioimpl.common.ImageUtil; import com.sun.medialib.codec.jiio.Util; import com.sun.medialib.codec.jiio.Constants; import com.sun.medialib.codec.jiio.mediaLibImage; /** * An adapter class for presenting image data in a mediaLibImage * format, even if the data isn't stored that way. MediaLibAccessor * is meant to make the common case (ComponentRasters) and allow * them to be accelerated via medialib. Note that unlike RasterAccessor, * MediaLibAccessor does not work with all cases. In the event that * MediaLibAccessor can not deal with a give collection of Rasters, * findCompatibleTag will return the value MediaLibAccessor.TAG_INCOMPATIBLE. * OpImages that use MediaLibAccessor should be paired with RIF's * which check that findCompatibleTag returns a valid tag before * actually constructing the Mlib OpImage. */ public class MediaLibAccessor { /** * Value indicating how far COPY_MASK info is shifted to avoid * interfering with the data type info */ private static final int COPY_MASK_SHIFT = 7; /* Value indicating how many bits the COPY_MASK is */ private static final int COPY_MASK_SIZE = 1; /** The bits of a FormatTag associated with how dataArrays are obtained. */ public static final int COPY_MASK = 0x1 << COPY_MASK_SHIFT; /** Flag indicating data is raster's data. */ public static final int UNCOPIED = 0x0 << COPY_MASK_SHIFT; /** Flag indicating data is a copy of the raster's data. */ public static final int COPIED = 0x01 << COPY_MASK_SHIFT; /** The bits of a FormatTag associated with pixel datatype. */ public static final int DATATYPE_MASK = (0x1 << COPY_MASK_SHIFT) - 1; /** * Value indicating how far BINARY_MASK info is shifted to avoid * interfering with the data type and copying info. */ private static final int BINARY_MASK_SHIFT = COPY_MASK_SHIFT+COPY_MASK_SIZE; /** Value indicating how many bits the BINARY_MASK is */ private static final int BINARY_MASK_SIZE = 1; /** The bits of a FormatTag associated with binary data. */ public static final int BINARY_MASK = ((1 << BINARY_MASK_SIZE) - 1) << BINARY_MASK_SHIFT; /** Flag indicating data are not binary. */ public static final int NONBINARY = 0x0 << BINARY_MASK_SHIFT; /** Flag indicating data are binary. */ public static final int BINARY = 0x1 << BINARY_MASK_SHIFT; /** FormatTag indicating data in byte arrays and uncopied. */ public static final int TAG_BYTE_UNCOPIED = DataBuffer.TYPE_BYTE | UNCOPIED; /** FormatTag indicating data in unsigned short arrays and uncopied. */ public static final int TAG_USHORT_UNCOPIED = DataBuffer.TYPE_USHORT | UNCOPIED; /** FormatTag indicating data in short arrays and uncopied. */ public static final int TAG_SHORT_UNCOPIED = DataBuffer.TYPE_SHORT | UNCOPIED; /** FormatTag indicating data in integer arrays and uncopied. */ public static final int TAG_INT_UNCOPIED = DataBuffer.TYPE_INT | UNCOPIED; /** FormatTag indicating data in float arrays and uncopied. */ public static final int TAG_FLOAT_UNCOPIED = DataBuffer.TYPE_FLOAT | UNCOPIED; /** FormatTag indicating data in double arrays and uncopied. */ public static final int TAG_DOUBLE_UNCOPIED = DataBuffer.TYPE_DOUBLE | UNCOPIED; /** FormatTag indicating data in byte arrays and uncopied. */ public static final int TAG_BYTE_COPIED = DataBuffer.TYPE_BYTE | COPIED; /** FormatTag indicating data in unsigned short arrays and copied. */ public static final int TAG_USHORT_COPIED = DataBuffer.TYPE_USHORT | COPIED; /** FormatTag indicating data in short arrays and copied. */ public static final int TAG_SHORT_COPIED = DataBuffer.TYPE_SHORT | COPIED; /** FormatTag indicating data in short arrays and copied. */ public static final int TAG_INT_COPIED = DataBuffer.TYPE_INT | COPIED; /** FormatTag indicating data in float arrays and copied. */ public static final int TAG_FLOAT_COPIED = DataBuffer.TYPE_FLOAT | COPIED; /** FormatTag indicating data in double arrays and copied. */ public static final int TAG_DOUBLE_COPIED = DataBuffer.TYPE_DOUBLE | COPIED; /** The raster that is the source of pixel data. */ protected Raster raster; /** The rectangle of the raster that MediaLibAccessor addresses. */ protected Rectangle rect; /** The number of bands per pixel in the data array. */ protected int numBands; /** The offsets of each band in the src image */ protected int bandOffsets[]; /** Tag indicating the data type of the data and whether its copied */ protected int formatTag; /** Area of mediaLib images that represent image data */ protected mediaLibImage mlimages[] = null; /** * Whether packed data are preferred when processing binary images. * This tag is ignored if the data are not binary. */ private boolean areBinaryDataPacked = false; /** * Returns the most efficient FormatTag that is compatible with * the destination raster and all source rasters. * * @param srcs the source Raster; may be null. * @param dst the destination Raster. */ public static int findCompatibleTag(Raster src) { SampleModel dstSM = src.getSampleModel(); int dstDT = dstSM.getDataType(); int defaultDataType = dstSM.getDataType(); boolean allComponentSampleModel = dstSM instanceof ComponentSampleModel; boolean allBinary = ImageUtil.isBinary(dstSM); if(allBinary) { // The copy flag is not set until the mediaLibImage is // created as knowing this information requires too much // processing to determine here. return DataBuffer.TYPE_BYTE | BINARY; } if (!allComponentSampleModel) { if ((defaultDataType == DataBuffer.TYPE_BYTE) || (defaultDataType == DataBuffer.TYPE_USHORT) || (defaultDataType == DataBuffer.TYPE_SHORT)) { defaultDataType = DataBuffer.TYPE_INT; } } int tag = defaultDataType | COPIED; if (!allComponentSampleModel) { return tag; } if (isPixelSequential(dstSM)) return dstDT | UNCOPIED; return tag; } /** * Determines if the SampleModel stores data in a way that can * be represented by a mediaLibImage without copying */ public static boolean isPixelSequential(SampleModel sm) { ComponentSampleModel csm = null; if (sm instanceof ComponentSampleModel) { csm = (ComponentSampleModel)sm; } else { return false; } int pixelStride = csm.getPixelStride(); int bandOffsets[] = csm.getBandOffsets(); int bankIndices[] = csm.getBankIndices(); if (pixelStride != bandOffsets.length) { return false; } //XXX: for band-selection result if (pixelStride != sm.getNumBands()) return false; for (int i = 0; i < bandOffsets.length; i++) { if (bandOffsets[i] >= pixelStride || bankIndices[i] != bankIndices[0]) { return false; } for (int j = i+1; j < bandOffsets.length; j++) { if (bandOffsets[i] == bandOffsets[j]) { return false; } //XXX: for BGR images if (bandOffsets[i] != i) return false; } } return true; } public static int getMediaLibDataType(int formatTag) { int dataType = formatTag & DATATYPE_MASK; switch (dataType) { case DataBuffer.TYPE_BYTE: return Constants.MLIB_BYTE; case DataBuffer.TYPE_USHORT: return Constants.MLIB_USHORT; case DataBuffer.TYPE_SHORT: return Constants.MLIB_SHORT; case DataBuffer.TYPE_INT: return Constants.MLIB_INT; case DataBuffer.TYPE_DOUBLE: return Constants.MLIB_DOUBLE; case DataBuffer.TYPE_FLOAT: return Constants.MLIB_FLOAT; } return -1; } /** * Constructs a MediaLibAccessor object out of a Raster, Rectangle * and formatTag returned from MediaLibAccessor.findCompatibleTag(). * * In the case of binary data the copy mask bits of the formatTag * will be reset within the constructor according to whether the * data are in fact copied. This cannot be easily determined before * the data are actually copied. */ public MediaLibAccessor(Raster raster, Rectangle rect, int formatTag, boolean preferPacked) { areBinaryDataPacked = preferPacked; this.raster = raster; this.rect = new Rectangle(rect); this.formatTag = formatTag; if(isBinary()) { // Set binary-specific fields and return. numBands = 1; bandOffsets = new int[] {0}; int mlibType; int scanlineStride; byte[] bdata; mlimages = new mediaLibImage[1]; if(areBinaryDataPacked) { mlibType = Constants.MLIB_BIT; scanlineStride = (rect.width+7)/8; bdata = ImageUtil.getPackedBinaryData(raster, rect); // Update format tag depending on whether the data were copied. if(bdata == ((DataBufferByte)raster.getDataBuffer()).getData()) { this.formatTag |= UNCOPIED; } else { this.formatTag |= COPIED; } } else { // unpacked mlibType = Constants.MLIB_BYTE; scanlineStride = rect.width; bdata = ImageUtil.getUnpackedBinaryData(raster, rect); this.formatTag |= COPIED; } mlimages[0] = new mediaLibImage(mlibType, 1, rect.width, rect.height, scanlineStride, 0, bdata); return; } if ((formatTag & COPY_MASK) == UNCOPIED) { ComponentSampleModel csm = (ComponentSampleModel)raster.getSampleModel(); numBands = csm.getNumBands(); bandOffsets = csm.getBandOffsets(); int dataOffset = raster.getDataBuffer().getOffset(); dataOffset += (rect.y-raster.getSampleModelTranslateY())*csm.getScanlineStride()+ (rect.x-raster.getSampleModelTranslateX())*csm.getPixelStride(); // dataoffset should and is in terms of dataElements // scanline stride should be in terms of dataElements int scanlineStride = csm.getScanlineStride(); switch (formatTag & DATATYPE_MASK) { case DataBuffer.TYPE_BYTE: DataBufferByte dbb = (DataBufferByte)raster.getDataBuffer(); mlimages = new mediaLibImage[1]; mlimages[0] = new mediaLibImage(Constants.MLIB_BYTE, numBands, rect.width, rect.height, scanlineStride, dataOffset, dbb.getData()); break; case DataBuffer.TYPE_USHORT: DataBufferUShort dbus = (DataBufferUShort)raster.getDataBuffer(); mlimages = new mediaLibImage[1]; mlimages[0] = new mediaLibImage(Constants.MLIB_USHORT, numBands, rect.width, rect.height, scanlineStride, dataOffset, dbus.getData()); break; case DataBuffer.TYPE_SHORT: DataBufferShort dbs = (DataBufferShort)raster.getDataBuffer(); mlimages = new mediaLibImage[1]; mlimages[0] = new mediaLibImage(Constants.MLIB_SHORT, numBands, rect.width, rect.height, scanlineStride, dataOffset, dbs.getData()); break; case DataBuffer.TYPE_INT: DataBufferInt dbi = (DataBufferInt)raster.getDataBuffer(); mlimages = new mediaLibImage[1]; mlimages[0] = new mediaLibImage(Constants.MLIB_INT, numBands, rect.width, rect.height, scanlineStride, dataOffset, dbi.getData()); break; case DataBuffer.TYPE_FLOAT: DataBufferFloat dbf = (DataBufferFloat)raster.getDataBuffer(); mlimages = new mediaLibImage[1]; mlimages[0] = new mediaLibImage(Constants.MLIB_FLOAT, numBands, rect.width, rect.height, scanlineStride, dataOffset, dbf.getData()); break; case DataBuffer.TYPE_DOUBLE: DataBufferDouble dbd = (DataBufferDouble)raster.getDataBuffer(); mlimages = new mediaLibImage[1]; mlimages[0] = new mediaLibImage(Constants.MLIB_DOUBLE, numBands, rect.width, rect.height, scanlineStride, dataOffset, dbd.getData()); break; default: throw new IllegalArgumentException((formatTag & DATATYPE_MASK) + "MediaLibAccessor does not recognize this datatype."); } } else { // Copying the data because we can't deal with it numBands = raster.getNumBands(); bandOffsets = new int[numBands]; for (int i = 0; i < numBands; i++) { bandOffsets[i] = i; } int scanlineStride = rect.width*numBands; switch (formatTag & DATATYPE_MASK) { case DataBuffer.TYPE_BYTE: byte bdata[] = new byte[rect.width*rect.height*numBands]; mlimages = new mediaLibImage[1]; mlimages[0] = new mediaLibImage(Constants.MLIB_BYTE, numBands, rect.width, rect.height, scanlineStride, 0, bdata); break; case DataBuffer.TYPE_USHORT: short usdata[] = new short[rect.width*rect.height*numBands]; mlimages = new mediaLibImage[1]; mlimages[0] = new mediaLibImage(Constants.MLIB_USHORT, numBands, rect.width, rect.height, scanlineStride, 0, usdata); break; case DataBuffer.TYPE_SHORT: short sdata[] = new short[rect.width*rect.height*numBands]; mlimages = new mediaLibImage[1]; mlimages[0] = new mediaLibImage(Constants.MLIB_SHORT, numBands, rect.width, rect.height, scanlineStride, 0, sdata); break; case DataBuffer.TYPE_INT: int idata[] = new int[rect.width*rect.height*numBands]; mlimages = new mediaLibImage[1]; mlimages[0] = new mediaLibImage(Constants.MLIB_INT, numBands, rect.width, rect.height, scanlineStride, 0, idata); break; case DataBuffer.TYPE_FLOAT: float fdata[] = new float[rect.width*rect.height*numBands]; mlimages = new mediaLibImage[1]; mlimages[0] = new mediaLibImage(Constants.MLIB_FLOAT, numBands, rect.width, rect.height, scanlineStride, 0, fdata); break; case DataBuffer.TYPE_DOUBLE: double ddata[] = new double[rect.width*rect.height*numBands]; mlimages = new mediaLibImage[1]; mlimages[0] = new mediaLibImage(Constants.MLIB_DOUBLE, numBands, rect.width, rect.height, scanlineStride, 0, ddata); break; default: throw new IllegalArgumentException((formatTag & DATATYPE_MASK) + "MediaLibAccessor does not recognize this datatype."); } copyDataFromRaster(); } } /** * Returns true if the MediaLibAccessor * represents binary data. */ public boolean isBinary() { return ((formatTag & BINARY_MASK) == BINARY); } /** * Returns an array of mediaLibImages which represents the input raster. * An array is returned instead of a single mediaLibImage because * in some cases, an input Raster can't be represented by one * mediaLibImage (unless copying is done) but can be represented * by several mediaLibImages without copying. */ public mediaLibImage[] getMediaLibImages() { return mlimages; } /** * Returns the data type of the RasterAccessor object. Note that * this datatype is not necessarily the same data type as the * underlying raster. */ public int getDataType() { return formatTag & DATATYPE_MASK; } /** * Returns true if the MediaLibAccessors's data is copied from it's * raster. */ public boolean isDataCopy() { return ((formatTag & COPY_MASK) == COPIED); } /** Returns the bandOffsets. */ public int[] getBandOffsets() { return bandOffsets; } /** * Returns parameters in the appropriate order if MediaLibAccessor * has reordered the bands or is attempting to make a * BandSequential image look like multiple PixelSequentialImages */ public int[] getIntParameters(int band, int params[]) { int returnParams[] = new int[numBands]; for (int i = 0; i < numBands; i++) { returnParams[i] = params[bandOffsets[i+band]]; } return returnParams; } /** * Returns parameters in the appropriate order if MediaLibAccessor * has reordered the bands or is attempting to make a * BandSequential image look like multiple PixelSequentialImages */ public int[][] getIntArrayParameters(int band, int[][] params) { int returnParams[][] = new int[numBands][]; for (int i = 0; i < numBands; i++) { returnParams[i] = params[bandOffsets[i+band]]; } return returnParams; } /** * Returns parameters in the appropriate order if MediaLibAccessor * has reordered the bands or is attempting to make a * BandSequential image look like multiple PixelSequentialImages */ public double[] getDoubleParameters(int band, double params[]) { double returnParams[] = new double[numBands]; for (int i = 0; i < numBands; i++) { returnParams[i] = params[bandOffsets[i+band]]; } return returnParams; } /** * Copy data from Raster to MediaLib image */ private void copyDataFromRaster() { // Writeback should only be necessary on destRasters which // should be writable so this cast should succeed. if (raster.getSampleModel() instanceof ComponentSampleModel) { ComponentSampleModel csm = (ComponentSampleModel)raster.getSampleModel(); int rasScanlineStride = csm.getScanlineStride(); int rasPixelStride = csm.getPixelStride(); int subRasterOffset = (rect.y-raster.getSampleModelTranslateY())*rasScanlineStride+ (rect.x-raster.getSampleModelTranslateX())*rasPixelStride; int rasBankIndices[] = csm.getBankIndices(); int rasBandOffsets[] = csm.getBandOffsets(); int rasDataOffsets[] = raster.getDataBuffer().getOffsets(); if (rasDataOffsets.length == 1) { for (int i = 0; i < numBands; i++) { rasBandOffsets[i] += rasDataOffsets[0] + subRasterOffset; } } else if (rasDataOffsets.length == rasBandOffsets.length) { for (int i = 0; i < numBands; i++) { rasBandOffsets[i] += rasDataOffsets[i] + subRasterOffset; } } Object mlibDataArray = null; switch (getDataType()) { case DataBuffer.TYPE_BYTE: byte bArray[][] = new byte[numBands][]; for (int i = 0; i < numBands; i++) { bArray[i] = mlimages[0].getByteData(); } mlibDataArray = bArray; break; case DataBuffer.TYPE_USHORT: short usArray[][] = new short[numBands][]; for (int i = 0; i < numBands; i++) { usArray[i] = mlimages[0].getUShortData(); } mlibDataArray = usArray; break; case DataBuffer.TYPE_SHORT: short sArray[][] = new short[numBands][]; for (int i = 0; i < numBands; i++) { sArray[i] = mlimages[0].getShortData(); } mlibDataArray = sArray; break; case DataBuffer.TYPE_INT: int iArray[][] = new int[numBands][]; for (int i = 0; i < numBands; i++) { iArray[i] = mlimages[0].getIntData(); } mlibDataArray = iArray; break; case DataBuffer.TYPE_FLOAT: float fArray[][] = new float[numBands][]; for (int i = 0; i < numBands; i++) { fArray[i] = mlimages[0].getFloatData(); } mlibDataArray = fArray; break; case DataBuffer.TYPE_DOUBLE: double dArray[][] = new double[numBands][]; for (int i = 0; i < numBands; i++) { dArray[i] = mlimages[0].getDoubleData(); } mlibDataArray = dArray; break; } Object rasDataArray = null; switch (csm.getDataType()) { case DataBuffer.TYPE_BYTE: { DataBufferByte dbb = (DataBufferByte)raster.getDataBuffer(); byte rasByteDataArray[][] = new byte[numBands][]; for (int i = 0; i < numBands; i++) { rasByteDataArray[i] = dbb.getData(rasBankIndices[i]); } rasDataArray = rasByteDataArray; } break; case DataBuffer.TYPE_USHORT: { DataBufferUShort dbus = (DataBufferUShort)raster.getDataBuffer(); short rasUShortDataArray[][] = new short[numBands][]; for (int i = 0; i < numBands; i++) { rasUShortDataArray[i] = dbus.getData(rasBankIndices[i]); } rasDataArray = rasUShortDataArray; } break; case DataBuffer.TYPE_SHORT: { DataBufferShort dbs = (DataBufferShort)raster.getDataBuffer(); short rasShortDataArray[][] = new short[numBands][]; for (int i = 0; i < numBands; i++) { rasShortDataArray[i] = dbs.getData(rasBankIndices[i]); } rasDataArray = rasShortDataArray; } break; case DataBuffer.TYPE_INT: { DataBufferInt dbi = (DataBufferInt)raster.getDataBuffer(); int rasIntDataArray[][] = new int[numBands][]; for (int i = 0; i < numBands; i++) { rasIntDataArray[i] = dbi.getData(rasBankIndices[i]); } rasDataArray = rasIntDataArray; } break; case DataBuffer.TYPE_FLOAT: { DataBufferFloat dbf = (DataBufferFloat)raster.getDataBuffer(); float rasFloatDataArray[][] = new float[numBands][]; for (int i = 0; i < numBands; i++) { rasFloatDataArray[i] = dbf.getData(rasBankIndices[i]); } rasDataArray = rasFloatDataArray; } break; case DataBuffer.TYPE_DOUBLE: { DataBufferDouble dbd = (DataBufferDouble)raster.getDataBuffer(); double rasDoubleDataArray[][] = new double[numBands][]; for (int i = 0; i < numBands; i++) { rasDoubleDataArray[i] = dbd.getData(rasBankIndices[i]); } rasDataArray = rasDoubleDataArray; } break; } // dst = mlib && src = ras Util.Reformat( mlibDataArray, rasDataArray, numBands, rect.width,rect.height, getMediaLibDataType(this.getDataType()), bandOffsets, rect.width*numBands, numBands, getMediaLibDataType(csm.getDataType()), rasBandOffsets, rasScanlineStride, rasPixelStride); } else { // If COPIED and the raster doesn't have ComponentSampleModel // data is moved with getPixel/setPixel (even byte/short) switch (getDataType()) { case DataBuffer.TYPE_INT: raster.getPixels(rect.x,rect.y, rect.width,rect.height, mlimages[0].getIntData()); break; case DataBuffer.TYPE_FLOAT: raster.getPixels(rect.x,rect.y, rect.width,rect.height, mlimages[0].getFloatData()); break; case DataBuffer.TYPE_DOUBLE: raster.getPixels(rect.x,rect.y, rect.width,rect.height, mlimages[0].getDoubleData()); break; } } } /** * Copies data back into the MediaLibAccessor's raster. Note that * the data is casted from the intermediate data format to * the raster's format. If clamping is needed, the call * clampDataArrays() method needs to be called before * calling the copyDataToRaster() method. */ public void copyDataToRaster(int[] channelMap) { if (isDataCopy()) { if(isBinary()) { if(areBinaryDataPacked) { ImageUtil.setPackedBinaryData(mlimages[0].getBitData(), (WritableRaster)raster, rect); } else { // unpacked ImageUtil.setUnpackedBinaryData(mlimages[0].getByteData(), (WritableRaster)raster, rect); } return; } // Writeback should only be necessary on destRasters which // should be writable so this cast should succeed. WritableRaster wr = (WritableRaster)raster; if (wr.getSampleModel() instanceof ComponentSampleModel) { ComponentSampleModel csm = (ComponentSampleModel)wr.getSampleModel(); int rasScanlineStride = csm.getScanlineStride(); int rasPixelStride = csm.getPixelStride(); int subRasterOffset = (rect.y-raster.getSampleModelTranslateY())*rasScanlineStride+ (rect.x-raster.getSampleModelTranslateX())*rasPixelStride; int rasBankIndices[] = csm.getBankIndices(); int rasBandOffsets[] = csm.getBandOffsets(); int rasDataOffsets[] = raster.getDataBuffer().getOffsets(); if (rasDataOffsets.length == 1) { for (int i = 0; i < numBands; i++) { rasBandOffsets[i] += rasDataOffsets[0] + subRasterOffset; } } else if (rasDataOffsets.length == rasBandOffsets.length) { for (int i = 0; i < numBands; i++) { rasBandOffsets[i] += rasDataOffsets[i] + subRasterOffset; } } Object mlibDataArray = null; switch (getDataType()) { case DataBuffer.TYPE_BYTE: byte bArray[][] = new byte[numBands][]; for (int i = 0; i < numBands; i++) { bArray[i] = mlimages[0].getByteData(); } mlibDataArray = bArray; break; case DataBuffer.TYPE_USHORT: short usArray[][] = new short[numBands][]; for (int i = 0; i < numBands; i++) { usArray[i] = mlimages[0].getUShortData(); } mlibDataArray = usArray; break; case DataBuffer.TYPE_SHORT: short sArray[][] = new short[numBands][]; for (int i = 0; i < numBands; i++) { sArray[i] = mlimages[0].getShortData(); } mlibDataArray = sArray; break; case DataBuffer.TYPE_INT: int iArray[][] = new int[numBands][]; for (int i = 0; i < numBands; i++) { iArray[i] = mlimages[0].getIntData(); } mlibDataArray = iArray; break; case DataBuffer.TYPE_FLOAT: float fArray[][] = new float[numBands][]; for (int i = 0; i < numBands; i++) { fArray[i] = mlimages[0].getFloatData(); } mlibDataArray = fArray; break; case DataBuffer.TYPE_DOUBLE: double dArray[][] = new double[numBands][]; for (int i = 0; i < numBands; i++) { dArray[i] = mlimages[0].getDoubleData(); } mlibDataArray = dArray; break; } byte tmpDataArray[] = null; Object rasDataArray = null; switch (csm.getDataType()) { case DataBuffer.TYPE_BYTE: { DataBufferByte dbb = (DataBufferByte)raster.getDataBuffer(); byte rasByteDataArray[][] = new byte[numBands][]; for (int i = 0; i < numBands; i++) { rasByteDataArray[i] = dbb.getData(rasBankIndices[i]); } tmpDataArray = rasByteDataArray[0]; rasDataArray = rasByteDataArray; } break; case DataBuffer.TYPE_USHORT: { DataBufferUShort dbus = (DataBufferUShort)raster.getDataBuffer(); short rasUShortDataArray[][] = new short[numBands][]; for (int i = 0; i < numBands; i++) { rasUShortDataArray[i] = dbus.getData(rasBankIndices[i]); } rasDataArray = rasUShortDataArray; } break; case DataBuffer.TYPE_SHORT: { DataBufferShort dbs = (DataBufferShort)raster.getDataBuffer(); short rasShortDataArray[][] = new short[numBands][]; for (int i = 0; i < numBands; i++) { rasShortDataArray[i] = dbs.getData(rasBankIndices[i]); } rasDataArray = rasShortDataArray; } break; case DataBuffer.TYPE_INT: { DataBufferInt dbi = (DataBufferInt)raster.getDataBuffer(); int rasIntDataArray[][] = new int[numBands][]; for (int i = 0; i < numBands; i++) { rasIntDataArray[i] = dbi.getData(rasBankIndices[i]); } rasDataArray = rasIntDataArray; } break; case DataBuffer.TYPE_FLOAT: { DataBufferFloat dbf = (DataBufferFloat)raster.getDataBuffer(); float rasFloatDataArray[][] = new float[numBands][]; for (int i = 0; i < numBands; i++) { rasFloatDataArray[i] = dbf.getData(rasBankIndices[i]); } rasDataArray = rasFloatDataArray; } break; case DataBuffer.TYPE_DOUBLE: { DataBufferDouble dbd = (DataBufferDouble)raster.getDataBuffer(); double rasDoubleDataArray[][] = new double[numBands][]; for (int i = 0; i < numBands; i++) { rasDoubleDataArray[i] = dbd.getData(rasBankIndices[i]); } rasDataArray = rasDoubleDataArray; } break; } int[] bandOffsetCopy = (int[])bandOffsets.clone(); if (channelMap != null) { for (int i = 0; i < bandOffsetCopy.length; i++) bandOffsetCopy[i] = channelMap[bandOffsetCopy[i]]; } // src = mlib && dst = ras Util.Reformat( rasDataArray, mlibDataArray, numBands, rect.width,rect.height, getMediaLibDataType(csm.getDataType()), rasBandOffsets, rasScanlineStride, rasPixelStride, getMediaLibDataType(this.getDataType()), bandOffsetCopy, rect.width*numBands, numBands); } else { // If COPIED and the raster doesn't have ComponentSampleModel // data is moved with getPixel/setPixel (even byte/short) switch (getDataType()) { case DataBuffer.TYPE_INT: wr.setPixels(rect.x,rect.y, rect.width,rect.height, mlimages[0].getIntData()); break; case DataBuffer.TYPE_FLOAT: wr.setPixels(rect.x,rect.y, rect.width,rect.height, mlimages[0].getFloatData()); break; case DataBuffer.TYPE_DOUBLE: wr.setPixels(rect.x,rect.y, rect.width,rect.height, mlimages[0].getDoubleData()); break; } } } } /** * Clamps data array values to a range that the underlying raster * can deal with. For example, if the underlying raster stores * data as bytes, but the samples ares unpacked into integer arrays by * the RasterAccessor object for an operation, the operation will * need to call clampDataArrays() so that the data in the int * arrays is restricted to the range 0..255 before a setPixels() * call is made on the underlying raster. Note that some * operations (for example, lookup) can guarantee that their * results don't need clamping so they can call * RasterAccessor.copyDataToRaster() without first calling this * function. */ public void clampDataArrays () { if (!isDataCopy()) { return; } // additonal medialib check: If it's a componentSampleModel // we get a free cast when we call medialibWrapper.Reformat // to copy the data to the source. So we don't need to cast // here. if (raster.getSampleModel() instanceof ComponentSampleModel) { return; } int bits[] = raster.getSampleModel().getSampleSize(); // Do we even need a clamp? We do if there's any band // of the source image stored in that's less than 32 bits // and is stored in a byte, short or int format. (The automatic // cast's between floats/doubles and 32-bit ints in setPixel() // generall do what we want.) boolean needClamp = false; boolean uniformBitSize = true; for (int i = 0; i < bits.length; i++) { int bitSize = bits[0]; if (bits[i] < 32) { needClamp = true; } if (bits[i] != bitSize) { uniformBitSize = false; } } if (!needClamp) { return; } int dataType = raster.getDataBuffer().getDataType(); double hiVals[] = new double[bits.length]; double loVals[] = new double[bits.length]; if (dataType == DataBuffer.TYPE_USHORT && uniformBitSize && bits[0] == 16) { for (int i = 0; i < bits.length; i++) { hiVals[i] = (double)0xFFFF; loVals[i] = (double)0; } } else if (dataType == DataBuffer.TYPE_SHORT && uniformBitSize && bits[0] == 16) { for (int i = 0; i < bits.length; i++) { hiVals[i] = (double)Short.MAX_VALUE; loVals[i] = (double)Short.MIN_VALUE; } } else if (dataType == DataBuffer.TYPE_INT && uniformBitSize && bits[0] == 32) { for (int i = 0; i < bits.length; i++) { hiVals[i] = (double)Integer.MAX_VALUE; loVals[i] = (double)Integer.MIN_VALUE; } } else { for (int i = 0; i < bits.length; i++) { hiVals[i] = (double)((1 << bits[i]) - 1); loVals[i] = (double)0; } } clampDataArray(hiVals,loVals); } private void clampDataArray(double hiVals[], double loVals[]) { switch (getDataType()) { case DataBuffer.TYPE_INT: clampIntArrays(toIntArray(hiVals),toIntArray(loVals)); break; case DataBuffer.TYPE_FLOAT: clampFloatArrays(toFloatArray(hiVals),toFloatArray(loVals)); break; case DataBuffer.TYPE_DOUBLE: clampDoubleArrays(hiVals,loVals); break; } } private int[] toIntArray(double vals[]) { int returnVals[] = new int[vals.length]; for (int i = 0; i < vals.length; i++) { returnVals[i] = (int)vals[i]; } return returnVals; } private float[] toFloatArray(double vals[]) { float returnVals[] = new float[vals.length]; for (int i = 0; i < vals.length; i++) { returnVals[i] = (float)vals[i]; } return returnVals; } private void clampIntArrays(int hiVals[], int loVals[]) { int width = rect.width; int height = rect.height; int scanlineStride = numBands*width; for (int k = 0; k < numBands; k++) { int data[] = mlimages[0].getIntData(); int scanlineOffset = k; int hiVal = hiVals[k]; int loVal = loVals[k]; for (int j = 0; j < height; j++) { int pixelOffset = scanlineOffset; for (int i = 0; i < width; i++) { int tmp = data[pixelOffset]; if (tmp < loVal) { data[pixelOffset] = loVal; } else if (tmp > hiVal) { data[pixelOffset] = hiVal; } pixelOffset += numBands; } scanlineOffset += scanlineStride; } } } private void clampFloatArrays(float hiVals[], float loVals[]) { int width = rect.width; int height = rect.height; int scanlineStride = numBands*width; for (int k = 0; k < numBands; k++) { float data[] = mlimages[0].getFloatData(); int scanlineOffset = k; float hiVal = hiVals[k]; float loVal = loVals[k]; for (int j = 0; j < height; j++) { int pixelOffset = scanlineOffset; for (int i = 0; i < width; i++) { float tmp = data[pixelOffset]; if (tmp < loVal) { data[pixelOffset] = loVal; } else if (tmp > hiVal) { data[pixelOffset] = hiVal; } pixelOffset += numBands; } scanlineOffset += scanlineStride; } } } private void clampDoubleArrays(double hiVals[], double loVals[]) { int width = rect.width; int height = rect.height; int scanlineStride = numBands*width; for (int k = 0; k < numBands; k++) { double data[] = mlimages[0].getDoubleData(); int scanlineOffset = k; double hiVal = hiVals[k]; double loVal = loVals[k]; for (int j = 0; j < height; j++) { int pixelOffset = scanlineOffset; for (int i = 0; i < width; i++) { double tmp = data[pixelOffset]; if (tmp < loVal) { data[pixelOffset] = loVal; } else if (tmp > hiVal) { data[pixelOffset] = hiVal; } pixelOffset += numBands; } scanlineOffset += scanlineStride; } } } } ././@LongLink0000000000000000000000000000015600000000000011567 Lustar rootrootjai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/jpeg2000/J2KImageReaderCodecLib.javajai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/jpeg2000/J2KImageReaderCode0000664000175100017510000004123010507277753032070 0ustar tilletille/* * $RCSfile: J2KImageReaderCodecLib.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.4 $ * $Date: 2006-09-29 20:19:55 $ * $State: Exp $ */ package com.sun.media.imageioimpl.plugins.jpeg2000; import com.sun.media.imageio.plugins.jpeg2000.J2KImageReadParam; import java.awt.Point; import java.awt.image.ColorModel; import java.awt.image.Raster; import java.awt.image.RenderedImage; import java.awt.image.SampleModel; import java.awt.image.WritableRaster; import java.io.IOException; import java.util.Hashtable; import javax.imageio.IIOException; import javax.imageio.ImageReader; import javax.imageio.ImageReadParam; import javax.imageio.ImageTypeSpecifier; import javax.imageio.metadata.IIOMetadata; import javax.imageio.spi.ImageReaderSpi; import javax.imageio.stream.ImageInputStream; import java.util.ArrayList; import java.util.Iterator; import javax.imageio.metadata.IIOMetadata; import java.awt.image.BufferedImage; import com.sun.media.imageioimpl.common.SimpleRenderedImage; import com.sun.medialib.codec.jp2k.Decoder; import com.sun.medialib.codec.jp2k.Size; import com.sun.medialib.codec.jiio.*; public class J2KImageReaderCodecLib extends ImageReader { /** Wrapper for the protected method processImageUpdate * So it can be access from the classes which are not in * ImageReader hierachy. */ public void processImageUpdateWrapper(BufferedImage theImage, int minX, int minY, int width, int height, int periodX, int periodY, int[] bands) { processImageUpdate(theImage, minX, minY, width, height, periodX, periodY, bands); } /** Wrapper for the protected method processImageProgress * So it can be access from the classes which are not in * ImageReader hierachy. */ public void processImageProgressWrapper(float percentageDone) { processImageProgress(percentageDone); } /** The input stream where reads from */ private ImageInputStream iis = null; /** Stream position when setInput() was called. */ private long streamPosition0; /** Indicates whether the header is read. */ private boolean gotHeader = false; /** The image width. */ private int width = -1; /** The image height. */ private int height = -1; /** The image tile width. */ private int tileWidth = -1; /** The image tile height. */ private int tileHeight = -1; /** The image tile grid X offset. */ private int tileGridXOffset = 0; /** The image tile grid Y offset. */ private int tileGridYOffset = 0; /** Image metadata, valid for the imageMetadataIndex only. */ private J2KMetadata imageMetadata = null; /** The RenderedImage decoded from the stream. */ SimpleRenderedImage image = null; public J2KImageReaderCodecLib(ImageReaderSpi originator) { super(originator); } /** Overrides the method defined in the superclass. */ public void setInput(Object input, boolean seekForwardOnly, boolean ignoreMetadata) { super.setInput(input, seekForwardOnly, ignoreMetadata); this.ignoreMetadata = ignoreMetadata; iis = (ImageInputStream) input; // Always works iis.mark(); // Mark the initial position. imageMetadata = null; try { this.streamPosition0 = iis.getStreamPosition(); } catch(IOException e) { // XXX ignore } } public ImageReadParam getDefaultReadParam() { return new J2KImageReadParam(); } public int getNumImages(boolean allowSearch) throws java.io.IOException { if(input == null) { throw new IllegalStateException(I18N.getString("J2KImageReader6")); } else if(seekForwardOnly) { throw new IllegalStateException(I18N.getString("J2KImageReader7")); } return 1; } public Iterator getImageTypes(int imageIndex) throws java.io.IOException { checkIndex(imageIndex); readHeader(); if (image != null) { ArrayList list = new ArrayList(); list.add(new ImageTypeSpecifier(image.getColorModel(), image.getSampleModel())); return list.iterator(); } return null; } public int getWidth(int imageIndex) throws java.io.IOException { checkIndex(imageIndex); readHeader(); return width; } public int getHeight(int imageIndex) throws java.io.IOException { checkIndex(imageIndex); readHeader(); return height; } public int getTileGridXOffset(int imageIndex) throws IOException { checkIndex(imageIndex); readHeader(); return tileGridXOffset; } public int getTileGridYOffset(int imageIndex) throws IOException { checkIndex(imageIndex); readHeader(); return tileGridYOffset; } public int getTileWidth(int imageIndex) throws IOException { checkIndex(imageIndex); readHeader(); return tileWidth; } public int getTileHeight(int imageIndex) throws IOException { checkIndex(imageIndex); readHeader(); return tileHeight; } /** * Returns true if the image is organized into * tiles, that is, equal-sized non-overlapping rectangles. * *

A reader plug-in may choose whether or not to expose tiling * that is present in the image as it is stored. It may even * choose to advertise tiling when none is explicitly present. In * general, tiling should only be advertised if there is some * advantage (in speed or space) to accessing individual tiles. * Regardless of whether the reader advertises tiling, it must be * capable of reading an arbitrary rectangular region specified in * an ImageReadParam. * *

A reader for which all images are guaranteed to be tiled, * or are guaranteed not to be tiled, may return true * or false respectively without accessing any image * data. In such cases, it is not necessary to throw an exception * even if no input source has been set or the image index is out * of bounds. * *

The default implementation just returns false. * * @param imageIndex the index of the image to be queried. * * @return true if the image is tiled. * * @exception IllegalStateException if an input source is required * to determine the return value, but none has been set. * @exception IndexOutOfBoundsException if an image must be * accessed to determine the return value, but the supplied index * is out of bounds. * @exception IOException if an error occurs during reading. */ public boolean isImageTiled(int imageIndex) throws IOException { int w = getWidth(imageIndex); int tw = getTileWidth(imageIndex); if(tw > 0 && ((w + tw - 1)/tw) > 1) { return true; } int h = getHeight(imageIndex); int th = getTileHeight(imageIndex); if(th > 0 && ((h + th - 1)/th) > 1) { return true; } return false; } public IIOMetadata getStreamMetadata() throws java.io.IOException { return null; } public IIOMetadata getImageMetadata(int imageIndex) throws java.io.IOException { if (ignoreMetadata) return null; checkIndex(imageIndex); if (imageMetadata == null) { try { iis.reset(); // Reset to initial position. iis.mark(); // Re-mark initial position. if (image == null || !(image instanceof J2KRenderedImageCodecLib)) image = new J2KRenderedImageCodecLib(iis, this, null); imageMetadata = ((J2KRenderedImageCodecLib)image).readImageMetadata(); } catch(IOException ioe) { throw ioe; } catch(RuntimeException re) { throw re; } finally { iis.reset(); // Reset to initial position. iis.mark(); // Re-mark initial position. } } return imageMetadata; } public boolean isRandomAccessEasy(int imageIndex) throws IOException { // No check done because neither input source nor image is // required to determine the return value. return true; } public RenderedImage readAsRenderedImage(int imageIndex, ImageReadParam param) throws java.io.IOException { checkIndex(imageIndex); if (param == null) param = getDefaultReadParam(); clearAbortRequest(); processImageStarted(0); if(param instanceof J2KImageReadParam && ((J2KImageReadParam)param).getResolution() >= 0) { // XXX Workaround for java.sun.com change request 5089981: // fall back to Java reader for lower resolution levels. // This code should be removed when this problem is fixed // in the codecLib JPEG2000 decoder. ImageReader jreader = new J2KImageReader(null); iis.seek(streamPosition0); jreader.setInput(iis); image = (SimpleRenderedImage)jreader.readAsRenderedImage(imageIndex, param); } else { image = new J2KRenderedImageCodecLib(iis, this, param); } if (abortRequested()) processReadAborted(); else processImageComplete(); return image; } public BufferedImage read(int imageIndex, ImageReadParam param) throws java.io.IOException { checkIndex(imageIndex); clearAbortRequest(); if (param == null) param = getDefaultReadParam(); processImageStarted(imageIndex); if(param instanceof J2KImageReadParam && ((J2KImageReadParam)param).getResolution() >= 0) { // XXX Workaround for java.sun.com change request 5089981: // fall back to Java reader for lower resolution levels. // This code should be removed when this problem is fixed // in the codecLib JPEG2000 decoder. ImageReader jreader = new J2KImageReader(null); iis.seek(streamPosition0); jreader.setInput(iis); if (abortRequested()) processReadAborted(); else processImageComplete(); return jreader.read(imageIndex, param); } BufferedImage bi = param.getDestination(); iis.reset(); // Reset to initial position. iis.mark(); // Re-mark initial position. // XXX Need to add a try-catch IOException block and reset/mark iis. image = new J2KRenderedImageCodecLib(iis, this, param); J2KRenderedImageCodecLib jclibImage = (J2KRenderedImageCodecLib)image; Point offset = param.getDestinationOffset(); WritableRaster raster; if (bi == null) { ColorModel colorModel = jclibImage.getColorModel(); SampleModel sampleModel = jclibImage.getSampleModel(); // If the destination type is specified, use the color model of it. ImageTypeSpecifier type = param.getDestinationType(); if (type != null) colorModel = type.getColorModel(); raster = Raster.createWritableRaster( sampleModel.createCompatibleSampleModel(jclibImage.getMinX()+ jclibImage.getWidth(), jclibImage.getMinY() + jclibImage.getHeight()), new Point(0, 0)); bi = new BufferedImage(colorModel, raster, colorModel != null ? colorModel.isAlphaPremultiplied() : false, new Hashtable()); } else { raster = bi.getWritableTile(0, 0); } jclibImage.setDestImage(bi); jclibImage.readAsRaster(raster); jclibImage.clearDestImage(); if (abortRequested()) processReadAborted(); else processImageComplete(); return bi; } public Raster readRaster(int imageIndex, ImageReadParam param) throws IOException { BufferedImage bi = read(imageIndex, param); return bi.getWritableTile(0, 0); } public void readHeader() throws java.io.IOException { if (gotHeader) return; try { iis.reset(); // Reset to initial position. iis.mark(); // Re-mark initial position. if (image == null) image = new J2KRenderedImageCodecLib(iis, this, null); this.width = image.getWidth(); this.height = image.getHeight(); this.tileWidth = image.getTileWidth(); this.tileHeight = image.getTileHeight(); this.tileGridXOffset = image.getTileGridXOffset(); this.tileGridYOffset = image.getTileGridYOffset(); } catch(IOException ioe) { throw ioe; } catch(RuntimeException re) { throw re; } finally { iis.reset(); // Reset to initial position. iis.mark(); // Re-mark initial position. } this.gotHeader = true; } private void checkIndex(int imageIndex) { if(input == null) { throw new IllegalStateException(I18N.getString("J2KImageReader6")); } if (imageIndex != 0) { throw new IndexOutOfBoundsException(I18N.getString("J2KImageReader4")); } } /** This method wraps the protected method abortRequested * to allow the abortions be monitored by J2KReadState. */ public boolean getAbortRequest() { return abortRequested(); } public void reset() { super.reset(); iis = null; gotHeader = false; width = -1; height = -1; tileWidth = -1; tileHeight = -1; tileGridXOffset = 0; tileGridYOffset = 0; imageMetadata = null; image = null; } } ././@LongLink0000000000000000000000000000015700000000000011570 Lustar rootrootjai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/jpeg2000/J2KImageWriterResources.javajai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/jpeg2000/J2KImageWriterReso0000664000175100017510000000422010203036165032155 0ustar tilletille/* * $RCSfile: J2KImageWriterResources.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.1 $ * $Date: 2005-02-11 05:01:35 $ * $State: Exp $ */ package com.sun.media.imageioimpl.plugins.jpeg2000; public class J2KImageWriterResources { static final Object[][] contents = { }; public J2KImageWriterResources() {} public Object[][] getContents() { return contents; } } ././@LongLink0000000000000000000000000000014700000000000011567 Lustar rootrootjai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/jpeg2000/DataEntryURLBox.javajai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/jpeg2000/DataEntryURLBox.ja0000664000175100017510000001235210203036165032123 0ustar tilletille/* * $RCSfile: DataEntryURLBox.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.1 $ * $Date: 2005-02-11 05:01:32 $ * $State: Exp $ */ package com.sun.media.imageioimpl.plugins.jpeg2000; import javax.imageio.metadata.IIOInvalidTreeException; import javax.imageio.metadata.IIOMetadataNode; import org.w3c.dom.Node; import org.w3c.dom.NodeList; /** This class is defined to represent a Data Entry URL Box of JPEG JP2 * file format. A Data Entry URL Box has a length, and a fixed type * of "url ". Its content are a one-byte version, a three-byte flags and * a URL pertains to the UUID List box within its UUID Info superbox. */ public class DataEntryURLBox extends Box { /** Cache the element names for this box's xml definition */ private static String[] elementNames = {"Version", "Flags", "URL"}; /** This method will be called by the getNativeNodeForSimpleBox of the * class Box to get the element names. */ public static String[] getElementNames() { return elementNames; } /** The element values. */ private byte version; private byte[] flags; private String url; /** Constructs a DataEntryURLBox from its content data. */ public DataEntryURLBox(byte[] data) { super(8 + data.length, 0x75726C20, data); } /** Constructs a DataEntryURLBox from its data elements. */ public DataEntryURLBox(byte version, byte[] flags, String url) { super(12 + url.length(), 0x75726C20, null); this.version = version; this.flags = flags; this.url = url; } /** Constructs a DataEntryURLBox from a Node. */ public DataEntryURLBox(Node node) throws IIOInvalidTreeException { super(node); NodeList children = node.getChildNodes(); for (int i = 0; i < children.getLength(); i++) { Node child = children.item(i); String name = child.getNodeName(); if ("Version".equals(name)) { version = Box.getByteElementValue(child); } if ("Flags".equals(name)) { flags = Box.getByteArrayElementValue(child); } if ("URL".equals(name)) { url = Box.getStringElementValue(child); } } } /** Parses the content of this box from its content byte array. */ protected void parse(byte[] data) { version = data[0]; flags = new byte[3]; flags[0] = data[1]; flags[1] = data[2]; flags[2] = data[3]; url = new String(data, 4, data.length - 4); } /** Creates an IIOMetadataNode from this data entry URL * box. The format of this node is defined in the XML dtd and xsd * for the JP2 image file. */ public IIOMetadataNode getNativeNode() { return getNativeNodeForSimpleBox(); } /** Returns the Version data element. */ public byte getVersion() { return version; } /** Returns the Flags data element. */ public byte[] getFlags() { return flags; } /** Returns the URL data element. */ public String getURL() { return url; } protected void compose() { if (data != null) return; data = new byte[4 + url.length()]; data[0] = version; data[1] = flags[0]; data[2] = flags[1]; data[3] = flags[2]; System.arraycopy(url.getBytes(), 0, data, 4, url.length()); } } ././@LongLink0000000000000000000000000000014500000000000011565 Lustar rootrootjai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/jpeg2000/ResolutionBox.javajai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/jpeg2000/ResolutionBox.java0000664000175100017510000001735610203036165032350 0ustar tilletille/* * $RCSfile: ResolutionBox.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.1 $ * $Date: 2005-02-11 05:01:37 $ * $State: Exp $ */ package com.sun.media.imageioimpl.plugins.jpeg2000; import javax.imageio.metadata.IIOInvalidTreeException; import javax.imageio.metadata.IIOMetadataNode; import org.w3c.dom.Node; import org.w3c.dom.NodeList; /** This class is defined to represent a Resolution Box of JPEG JP2 * file format. A Data Entry URL Box has a length, and a fixed type * of "resc" (capture resolution) or "resd" (default display resolution). * * Its contens includes the resolution numerators, denominator, and the * exponents for both horizontal and vertical directions. */ public class ResolutionBox extends Box { /** The data elements in this box. */ private short numV; private short numH; private short denomV; private short denomH; private byte expV; private byte expH; /** The cached horizontal/vertical resolutions. */ private float hRes; private float vRes; /** Constructs a ResolutionBox from the provided type and * content data array. */ public ResolutionBox(int type, byte[] data) { super(18, type, data); } /** Constructs a ResolutionBox from the provided type and * horizontal/vertical resolutions. */ public ResolutionBox(int type, float hRes, float vRes) { super(18, type, null); this.hRes = hRes; this.vRes = vRes; denomH = denomV = 1; expV = 0; if (vRes >= 32768) { int temp = (int)vRes; while (temp >= 32768) { expV++; temp /= 10; } numV = (short)(temp & 0xFFFF); } else { numV = (short)vRes; } expH = 0; if (hRes >= 32768) { int temp = (int)hRes; while (temp >= 32768) { expH++; temp /= 10; } numH = (short)(temp & 0xFFFF); } else { numH = (short)hRes; } } /** Constructs a ResolutionBox based on the provided * org.w3c.dom.Node. */ public ResolutionBox(Node node) throws IIOInvalidTreeException { super(node); NodeList children = node.getChildNodes(); for (int i = 0; i < children.getLength(); i++) { Node child = children.item(i); String name = child.getNodeName(); if ("VerticalResolutionNumerator".equals(name)) { numV = Box.getShortElementValue(child); } if ("VerticalResolutionDenominator".equals(name)) { denomV = Box.getShortElementValue(child); } if ("HorizontalResolutionNumerator".equals(name)) { numH = Box.getShortElementValue(child); } if ("HorizontalResolutionDenominator".equals(name)) { denomH = Box.getShortElementValue(child); } if ("VerticalResolutionExponent".equals(name)) { expV = Box.getByteElementValue(child); } if ("HorizontalResolutionExponent".equals(name)) { expH = Box.getByteElementValue(child); } } } /** Return the horizontal resolution. */ public float getHorizontalResolution() { return hRes; } /** Return the vertical resolution. */ public float getVerticalResolution() { return vRes; } /** Parse the data elements from the provided content data array. */ protected void parse(byte[] data) { numV = (short)(((data[0] & 0xFF) << 8) | (data[1] & 0xFF)); denomV = (short)(((data[2] & 0xFF) << 8) | (data[3] & 0xFF)); numH = (short)(((data[4] & 0xFF) << 8) | (data[5] & 0xFF)); denomH = (short)(((data[6] & 0xFF) << 8) | (data[7] & 0xFF)); expV = data[8]; expH = data[9]; vRes = (float)((numV & 0xFFFF) * Math.pow(10, expV) / (denomV & 0xFFFF)); hRes = (float)((numH & 0xFFFF)* Math.pow(10, expH) / (denomH & 0xFFFF)); } /** Creates an IIOMetadataNode from this resolution * box. The format of this node is defined in the XML dtd and xsd * for the JP2 image file. */ public IIOMetadataNode getNativeNode() { IIOMetadataNode node = new IIOMetadataNode(Box.getName(getType())); setDefaultAttributes(node); IIOMetadataNode child = new IIOMetadataNode("VerticalResolutionNumerator"); child.setUserObject(new Short(numV)); child.setNodeValue("" + numV); node.appendChild(child); child = new IIOMetadataNode("VerticalResolutionDenominator"); child.setUserObject(new Short(denomV)); child.setNodeValue("" + denomV); node.appendChild(child); child = new IIOMetadataNode("HorizontalResolutionNumerator"); child.setUserObject(new Short(numH)); child.setNodeValue("" + numH); node.appendChild(child); child = new IIOMetadataNode("HorizontalResolutionDenominator"); child.setUserObject(new Short(denomH)); child.setNodeValue("" + denomH); node.appendChild(child); child = new IIOMetadataNode("VerticalResolutionExponent"); child.setUserObject(new Byte(expV)); child.setNodeValue("" + expV); node.appendChild(child); child = new IIOMetadataNode("HorizontalResolutionExponent"); child.setUserObject(new Byte(expH)); child.setNodeValue("" + expH); node.appendChild(child); return node; } protected void compose() { if (data != null) return; data = new byte[10]; data[0] = (byte)(numV >> 8); data[1] = (byte)(numV & 0xFF); data[2] = (byte)(denomV >> 8); data[3] = (byte)(denomV & 0xFF); data[4] = (byte)(numH >> 8); data[5] = (byte)(numH & 0xFF); data[6] = (byte)(denomH >> 8); data[7] = (byte)(denomH & 0xFF); data[8] = expV; data[9] = expH; } } jai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/jpeg2000/HeaderBox.java0000664000175100017510000001674410203036165031375 0ustar tilletille/* * $RCSfile: HeaderBox.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.1 $ * $Date: 2005-02-11 05:01:32 $ * $State: Exp $ */ package com.sun.media.imageioimpl.plugins.jpeg2000; import javax.imageio.metadata.IIOInvalidTreeException; import javax.imageio.metadata.IIOMetadataNode; import org.w3c.dom.Node; import org.w3c.dom.NodeList; /** This class is defined to represent an Image Header Box of JPEG JP2 file * format. An Image Header Box has a length, and a fixed type of "ihdr". * * The content of an image header box contains the width/height, number of * image components, the bit depth (coded with sign/unsign information), * the compression type (7 for JP2 file), the flag to indicate the color * space is known or not, and a flag to indicate whether the intellectual * property information included in this file. */ public class HeaderBox extends Box { /** Cache the element names for this box's xml definition */ private static String[] elementNames = {"Height", "Width", "NumComponents", "BitDepth", "CompressionType", "UnknownColorspace", "IntellectualProperty"}; /** This method will be called by the getNativeNodeForSimpleBox of the * class Box to get the element names. */ public static String[] getElementNames() { return elementNames; } /** The element values. */ private int width; private int height; private short numComp; private byte bitDepth; private byte compressionType; private byte unknownColor; private byte intelProp; /** Create an Image Header Box from the element values. */ public HeaderBox(int height, int width, int numComp, int bitDepth, int compressionType, int unknownColor, int intelProp) { super(22, 0x69686472, null); this.height = height; this.width = width; this.numComp = (short)numComp; this.bitDepth = (byte)bitDepth; this.compressionType = (byte)compressionType; this.unknownColor = (byte)unknownColor; this.intelProp = (byte)intelProp; } /** Create an Image Header Box using the content data. */ public HeaderBox(byte[] data) { super(8 + data.length, 0x69686472, data); } /** Constructs an Image Header Box from a Node. */ public HeaderBox(Node node) throws IIOInvalidTreeException { super(node); NodeList children = node.getChildNodes(); for (int i = 0; i < children.getLength(); i++) { Node child = children.item(i); String name = child.getNodeName(); if ("Height".equals(name)) { height = Box.getIntElementValue(child); } if ("Width".equals(name)) { width = Box.getIntElementValue(child); } if ("NumComponents".equals(name)) { numComp = Box.getShortElementValue(child); } if ("BitDepth".equals(name)) { bitDepth = Box.getByteElementValue(child); } if ("CompressionType".equals(name)) { compressionType = Box.getByteElementValue(child); } if ("UnknownColorspace".equals(name)) { unknownColor = Box.getByteElementValue(child); } if ("IntellectualProperty".equals(name)) { intelProp = Box.getByteElementValue(child); } } } /** Parse the data elements from the byte array of the content. */ protected void parse(byte[] data) { height = ((data[0] & 0xFF) << 24) | ((data[1] & 0xFF) << 16) | ((data[2] & 0xFF) << 8) | (data[3]& 0xFF); width = ((data[4] & 0xFF) << 24) | ((data[5] & 0xFF) << 16) | ((data[6] & 0xFF) << 8) | (data[7] & 0xFF); numComp = (short)(((data[8] & 0xFF) << 8) | (data[9] & 0xFF)); bitDepth = data[10]; compressionType = data[11]; unknownColor = data[12]; intelProp = data[13]; } /** Returns the height of the image. */ public int getHeight() { return height; } /** Returns the width of the image. */ public int getWidth() { return width; } /** Returns the number of image components. */ public short getNumComponents() { return numComp; } /** Returns the compression type. */ public byte getCompressionType() { return compressionType; } /** Returns the bit depth for all the image components. */ public byte getBitDepth() { return bitDepth; } /** Returns the UnknowColorspace flag. */ public byte getUnknownColorspace() { return unknownColor; } /** Returns the IntellectualProperty flag. */ public byte getIntellectualProperty() { return intelProp; } /** Creates an IIOMetadataNode from this image header box. * The format of this node is defined in the XML dtd and xsd * for the JP2 image file. */ public IIOMetadataNode getNativeNode() { return getNativeNodeForSimpleBox(); } protected void compose() { if (data != null) return; data = new byte[14]; copyInt(data, 0, height); copyInt(data, 4, width); data[8] = (byte)(numComp >> 8); data[9] = (byte)(numComp & 0xFF); data[10] = bitDepth; data[11] = compressionType; data[12] = unknownColor; data[13] = intelProp; } } ././@LongLink0000000000000000000000000000015100000000000011562 Lustar rootrootjai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/jpeg2000/IISRandomAccessIO.javajai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/jpeg2000/IISRandomAccessIO.0000664000175100017510000001641010465755563032043 0ustar tilletille/* * $RCSfile: IISRandomAccessIO.java,v $ * * * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.1 $ * $Date: 2006-08-08 00:31:47 $ * $State: Exp $ */ package com.sun.media.imageioimpl.plugins.jpeg2000; import java.io.IOException; import java.nio.ByteOrder; import javax.imageio.stream.ImageInputStream; import jj2000.j2k.io.EndianType; import jj2000.j2k.io.RandomAccessIO; /** * A wrapper for converting an ImageInputStream into a * RandomAccessIO. The resulting class is read-only. */ public class IISRandomAccessIO implements RandomAccessIO { /** The ImageInputStream that is wrapped */ private ImageInputStream iis; /** * Creates a RandomAccessIO instance from the supplied * ImageInputStream. * * @param iis The source ImageInputStream. */ public IISRandomAccessIO(ImageInputStream iis) { if (iis == null) { throw new IllegalArgumentException("iis == null!"); } this.iis = iis; } public void close() throws IOException { iis.close(); } /** * Returns the stream position clamped to a maximum of * Integer.MAX_VALUE. */ public int getPos() throws IOException { long pos = iis.getStreamPosition(); return pos > Integer.MAX_VALUE ? Integer.MAX_VALUE : (int)pos; } public void seek(int off) throws IOException { iis.seek(off); } /** * Returns the length of the data stream. * *

If the length of the ImageInputStream is not * -1, then it is returned after being clamped to * a maximum value of Integer.MAX_VALUE. If the * ImageInputStream is -1, the stream * is read to a maximum position of Integer.MAX_VALUE * and its final position is returned. The position of the stream * is unchanged from the value it had prior to the call.

*/ public int length() throws IOException { long len = iis.length(); // If the length is non-negative, use it. if(len != -1L) { return len > Integer.MAX_VALUE ? Integer.MAX_VALUE : (int)len; } // If the length is negative, read until the stream ends. iis.mark(); int bufLen = 1024; byte[] buf = new byte[bufLen]; long pos = iis.getStreamPosition(); while(pos < Integer.MAX_VALUE) { int numRead = iis.read(buf, 0, bufLen); if(numRead == -1) break; // EOF pos += numRead; } iis.reset(); // Return the last position. return pos > Integer.MAX_VALUE ? Integer.MAX_VALUE : (int)pos; } public int read() throws IOException { return iis.read(); } public void readFully(byte b[], int off, int n) throws IOException { iis.readFully(b, off, n); } public int getByteOrdering() { return iis.getByteOrder() == ByteOrder.BIG_ENDIAN ? EndianType.BIG_ENDIAN : EndianType.LITTLE_ENDIAN; } public byte readByte() throws IOException { return iis.readByte(); } public int readUnsignedByte() throws IOException { return iis.readUnsignedByte(); } public short readShort() throws IOException { return iis.readShort(); } public int readUnsignedShort() throws IOException { return iis.readUnsignedShort(); } public int readInt() throws IOException { return iis.readInt(); } public long readUnsignedInt() throws IOException { return iis.readUnsignedInt(); } public long readLong() throws IOException { return iis.readLong(); } public float readFloat() throws IOException { return iis.readFloat(); } public double readDouble() throws IOException { return iis.readDouble(); } public int skipBytes(int n) throws IOException { return iis.skipBytes(n); } /** * A null operation as writing is not supported. */ public void flush() { // Intentionally empty. } /** * Throws an IOException as writing is not supported. */ public void write(int b) throws IOException { throw new IOException("Writing is not supported!"); } /** * Throws an IOException as writing is not supported. */ public void writeByte(int v) throws IOException { throw new IOException("Writing is not supported!"); } /** * Throws an IOException as writing is not supported. */ public void writeShort(int v) throws IOException { throw new IOException("Writing is not supported!"); } /** * Throws an IOException as writing is not supported. */ public void writeInt(int v) throws IOException { throw new IOException("Writing is not supported!"); } /** * Throws an IOException as writing is not supported. */ public void writeLong(long v) throws IOException { throw new IOException("Writing is not supported!"); } /** * Throws an IOException as writing is not supported. */ public void writeFloat(float v) throws IOException { throw new IOException("Writing is not supported!"); } /** * Throws an IOException as writing is not supported. */ public void writeDouble(double v) throws IOException { throw new IOException("Writing is not supported!"); } } ././@LongLink0000000000000000000000000000016100000000000011563 Lustar rootrootjai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/jpeg2000/J2KImageReaderCodecLibSpi.javajai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/jpeg2000/J2KImageReaderCode0000664000175100017510000001347410413303155032057 0ustar tilletille/* * $RCSfile: J2KImageReaderCodecLibSpi.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.2 $ * $Date: 2006-03-31 19:43:39 $ * $State: Exp $ */ package com.sun.media.imageioimpl.plugins.jpeg2000; import java.util.Locale; import javax.imageio.spi.ImageReaderSpi; import javax.imageio.stream.ImageInputStream; import javax.imageio.spi.IIORegistry; import javax.imageio.spi.ServiceRegistry; import java.io.IOException; import javax.imageio.ImageReader; import javax.imageio.IIOException; import com.sun.media.imageioimpl.common.PackageUtil; public class J2KImageReaderCodecLibSpi extends ImageReaderSpi { private static String [] writerSpiNames = {"com.sun.media.imageioimpl.plugins.jpeg2000.J2KImageWriterCodecLibSpi"}; private static String[] formatNames = {"jpeg 2000", "JPEG 2000", "jpeg2000", "JPEG2000"}; private static String[] extensions = {"jp2"}; // Should add jpx or jpm private static String[] mimeTypes = {"image/jp2", "image/jpeg2000"}; private boolean registered = false; public J2KImageReaderCodecLibSpi() { super(PackageUtil.getVendor(), PackageUtil.getVersion(), formatNames, extensions, mimeTypes, "com.sun.media.imageioimpl.plugins.jpeg2000.J2KImageReaderCodecLib", STANDARD_INPUT_TYPE, writerSpiNames, false, null, null, null, null, true, "com_sun_media_imageio_plugins_jpeg2000_image_1.0", "com.sun.media.imageioimpl.plugins.jpeg2000.J2KMetadataFormat", null, null); } public void onRegistration(ServiceRegistry registry, Class category) { if (registered) { return; } registered = true; // Branch based on codecLib availability. if(!PackageUtil.isCodecLibAvailable()) { // Deregister provider. registry.deregisterServiceProvider(this); } else { // Set pairwise ordering to give codecLib reader precedence. Class javaReaderSPIClass = null; try { javaReaderSPIClass = Class.forName("com.sun.media.imageioimpl.plugins.jpeg2000.J2KImageReaderSpi"); } catch(Throwable t) { // Ignore it. } if(javaReaderSPIClass != null) { Object javaReaderSPI = registry.getServiceProviderByClass(javaReaderSPIClass); if(javaReaderSPI != null) { registry.setOrdering(category, this, javaReaderSPI); } } } } public String getDescription(Locale locale) { String desc = PackageUtil.getSpecificationTitle() + " natively-accelerated JPEG 2000 Image Reader"; return desc; } public boolean canDecodeInput(Object source) throws IOException { if (!(source instanceof ImageInputStream)) { return false; } ImageInputStream stream = (ImageInputStream)source; //fix of 4938421 stream.mark(); int marker = (stream.read() << 8) | stream.read(); if (marker == 0xFF4F) { stream.reset(); return true; } stream.reset(); stream.mark(); byte[] b = new byte[12]; stream.readFully(b); stream.reset(); //Verify the signature box // The length of the signature box is 12 if (b[0] !=0 || b[1]!=0 || b[2] != 0 || b[3] != 12) return false; // The signature box type is "jP " if ((b[4] & 0xff) != 0x6A || (b[5] & 0xFF) != 0x50 || (b[6] & 0xFF) !=0x20 || (b[7] & 0xFF) != 0x20) return false; // The signture content is 0x0D0A870A if ((b[8] & 0xFF) != 0x0D || (b[9] & 0xFF) != 0x0A || (b[10] & 0xFF) != 0x87 || (b[11] &0xFF) != 0x0A) return false; return true; } public ImageReader createReaderInstance(Object extension) throws IIOException { return new J2KImageReaderCodecLib(this); } } ././@LongLink0000000000000000000000000000015000000000000011561 Lustar rootrootjai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/jpeg2000/RenderedImageSrc.javajai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/jpeg2000/RenderedImageSrc.j0000664000175100017510000010463010505066255032207 0ustar tilletille/* * $RCSfile: RenderedImageSrc.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.2 $ * $Date: 2006-09-22 23:07:25 $ * $State: Exp $ */ package com.sun.media.imageioimpl.plugins.jpeg2000; import java.awt.Point; import java.awt.Rectangle; import java.awt.RenderingHints; import java.awt.image.ColorModel; import java.awt.image.ComponentSampleModel; import java.awt.image.DataBuffer; import java.awt.image.DataBufferByte; import java.awt.image.RenderedImage; import java.awt.image.Raster; import java.awt.image.MultiPixelPackedSampleModel; import java.awt.image.SampleModel; import java.awt.image.WritableRaster; import java.awt.image.renderable.ParameterBlock; import jj2000.j2k.image.*; import jj2000.j2k.*; import java.io.*; import com.sun.media.imageioimpl.common.ImageUtil; public class RenderedImageSrc implements BlkImgDataSrc { /** The width of the image */ private int w; /** The height of the image */ private int h; /** The tile width for encoding */ int tileWidth; /** The tile height for encoding */ int tileHeight; /** The tile grid offset for encoding */ int tileXOffset, tileYOffset; /** The source -> destination transformation */ int scaleX, scaleY, xOffset, yOffset; /** The source bands to be encoded. */ int[] sourceBands = null; /** The destination upper-left corner */ int minX, minY; /** The number of components in the image */ private int nc; /** The number of bits that determine the nominal dynamic range */ // XXX: Should be an int[] of length 'nc'. private int rb; /** Buffer for the 3 components of each pixel(in the current block) */ private int[][] barr = null; /** Data block used only to store coordinates of the buffered blocks */ private DataBlkInt dbi = new DataBlkInt(); /** The line buffer. */ private byte buf[]; /** Temporary DataBlkInt object (needed when encoder uses floating-point filters). This avoid allocating new DataBlk at each time */ private DataBlkInt intBlk; private RenderedImage src; private J2KImageWriteParamJava param; /** The input source raster. */ private Raster raster; /** The raster for a destination tile */ private Raster aTile; private Point co = new Point(); private int dcOffset = 0; private boolean isBinary = false; private Rectangle destinationRegion; private Rectangle sourceRegion; private ColorModel cm; private SampleModel sm; private boolean noTransform = true; private boolean noSubband = true; /** Used to process abortion. */ private J2KImageWriter writer; /** Indicates a raster rather than a RenderedImage * to be encoded. */ private boolean inputIsRaster = false; /** * Creates RenderedImageSrc for encoding a Raster. * * @param raster The Raster to be encoded. * @param param The J2KImageWriteParamJava used in encoding. * @param writer The J2KImageWriter performs the encoding. * * @param IOException If an error occurs while opening the file. */ public RenderedImageSrc(Raster raster, J2KImageWriteParamJava param, J2KImageWriter writer) { this.raster = raster; this.param = param; this.writer = writer; this.inputIsRaster = true; sourceRegion = param.getSourceRegion(); if (sourceRegion == null) sourceRegion = new Rectangle(raster.getMinX(), raster.getMinY(), raster.getWidth(), raster.getHeight()); else sourceRegion = sourceRegion.intersection(raster.getBounds()); if (sourceRegion.isEmpty()) throw new RuntimeException(I18N.getString("J2KImageWriterCodecLib0")); sm = raster.getSampleModel(); getFromParam(); setSampleModelAndMore(); setTile(0, 0); } /** * Creates RenderedImageSrc for encoding a * RenderedImage. * * @param src The RenderedImage to be encoded. * @param param The J2KImageWriteParamJava used in encoding. * @param writer The J2KImageWriter performs the encoding. * * @param IOException If an error occurs while opening the file. * */ public RenderedImageSrc(RenderedImage src, J2KImageWriteParamJava param, J2KImageWriter writer) { this.src = src; this.param = param; this.writer = writer; sourceRegion = param.getSourceRegion(); if (sourceRegion == null) sourceRegion = new Rectangle(src.getMinX(), src.getMinY(), src.getWidth(), src.getHeight()); else sourceRegion = sourceRegion.intersection(new Rectangle(src.getMinX(), src.getMinY(), src.getWidth(), src.getHeight())); if (sourceRegion.isEmpty()) throw new RuntimeException(I18N.getString("J2KImageWriterCodecLib0")); sm = src.getSampleModel(); cm = src.getColorModel(); getFromParam(); setSampleModelAndMore(); } private void getFromParam() { try { tileWidth = param.getTileWidth(); tileHeight = param.getTileHeight(); tileXOffset = param.getTileGridXOffset(); tileYOffset = param.getTileGridYOffset(); } catch(IllegalStateException e) { param.setTilingMode(param.MODE_EXPLICIT); if (inputIsRaster) { param.setTiling(raster.getWidth(), raster.getHeight(), raster.getMinX(), raster.getMinY()); } else { param.setTiling(src.getWidth(), src.getHeight(), src.getMinX(), src.getMinY()); } tileWidth = param.getTileWidth(); tileHeight = param.getTileHeight(); tileXOffset = param.getTileGridXOffset(); tileYOffset = param.getTileGridYOffset(); } scaleX = param.getSourceXSubsampling(); scaleY = param.getSourceYSubsampling(); xOffset = param.getSubsamplingXOffset(); yOffset = param.getSubsamplingYOffset(); sourceRegion.translate(xOffset, yOffset); sourceRegion.width -= xOffset; sourceRegion.height -= yOffset; xOffset = sourceRegion.x % scaleX; yOffset = sourceRegion.y % scaleY; minX = sourceRegion.x / scaleX; minY = sourceRegion.y / scaleY; w = (sourceRegion.width + scaleX - 1) / scaleX; h = (sourceRegion.height + scaleY - 1) / scaleY; tileXOffset += (minX - tileXOffset)/tileWidth * tileWidth; tileYOffset += (minY - tileYOffset)/tileHeight * tileHeight; destinationRegion = new Rectangle(minX, minY, w, h); if (!destinationRegion.equals(sourceRegion) || tileWidth != sm.getWidth() || tileHeight != sm.getHeight() || (!inputIsRaster && (tileXOffset != src.getTileGridXOffset() || tileYOffset != src.getTileGridYOffset())) || (inputIsRaster && (tileXOffset != raster.getMinX() || tileYOffset != raster.getMinY()))) noTransform = false; } private void setSampleModelAndMore() { nc = sm.getNumBands(); sourceBands = param.getSourceBands(); if (sourceBands != null) { sm = sm.createSubsetSampleModel(sourceBands); noSubband = false; } else { sourceBands = new int[nc]; for (int i = 0; i < nc; i++) sourceBands[i] = i; } sm = sm.createCompatibleSampleModel(tileWidth, tileHeight); nc = sm.getNumBands(); isBinary = ImageUtil.isBinary(sm); if(cm != null) { // XXX: rb should be set to getComponentSize(); rb = cm.getComponentSize(0); for (int i = 1; i < cm.getNumComponents(); i++) if (rb < cm.getComponentSize(i)) rb = cm.getComponentSize(i); } else { // XXX: rb should be set to getSampleSize(); rb = sm.getSampleSize(0); for (int i = 1; i < sm.getNumBands(); i++) if (rb < sm.getSampleSize(i)) rb = sm.getSampleSize(i); } if (!isOrigSigned(0) && rb > 1) // XXX: if rb is an int[] this will have to change. dcOffset = 1 << rb - 1; } public int getTilePartULX() { return tileXOffset; } public int getTilePartULY() { return tileYOffset; } /** * Returns the width of the current tile in pixels. * * @return The total image width in pixels. * */ public int getTileWidth() { int width = tileWidth; int maxX = getImgULX() + getImgWidth(); int x = co.x * tileWidth + tileXOffset; if (x + tileWidth >= maxX) width = maxX - x; return width; } /** * Returns the overall height of the current tile in pixels. * * @return The total image height in pixels. */ public int getTileHeight() { int height = tileHeight; int maxY = getImgULY() + getImgHeight(); int y = co.y * tileHeight + tileYOffset; if (y + tileHeight >= maxY) height = maxY - y; return height; } public int getNomTileWidth() { return tileWidth; } public int getNomTileHeight() { return tileHeight; } /** * Returns the overall width of the image in pixels. This is the image's * width without accounting for any component subsampling or tiling. The * value of w is returned. * * @return The total image's width in pixels. * */ public int getImgWidth() { return w; } /** * Returns the overall height of the image in pixels. This is the image's * height without accounting for any component subsampling or tiling. The * value of h is returned. * * @return The total image's height in pixels. * */ public int getImgHeight() { return h; } /** * Returns the number of components in the image. The value of nc * is returned. * * @return The number of components in the image. * */ public int getNumComps() { return nc; } public int getTileGridXOffset() { return param.getTileGridXOffset(); } public int getTileGridYOffset() { return param.getTileGridYOffset(); } public int getTileCompHeight(int t, int c) { return tileHeight; } public int getTileCompWidth(int t, int c) { return tileWidth; } /** * Returns the component subsampling factor in the horizontal direction, * for the specified component. This is, approximately, the ratio of * dimensions between the reference grid and the component itself, see the * 'ImgData' interface desription for details. * * @param c The index of the component (between 0 and C-1) * * @return The horizontal subsampling factor of component 'c' * * @see ImgData * */ public int getCompSubsX(int c) { return 1; } /** * Returns the component subsampling factor in the vertical direction, for * the specified component. This is, approximately, the ratio of * dimensions between the reference grid and the component itself, see the * 'ImgData' interface desription for details. * * @param c The index of the component (between 0 and C-1) * * @return The vertical subsampling factor of component 'c' * * @see ImgData * */ public int getCompSubsY(int c) { return 1; } /** * Returns the width in pixels of the specified component in the current * tile. This default implementation assumes no tiling and no component * subsampling (i.e., all components, or components, have the same * dimensions in pixels). * * @param c The index of the component, from 0 to C-1. * * @return The width in pixels of component n in the current * tile. * */ public int getCompWidth(int n) { return w; } /** * Returns the height in pixels of the specified component in the current * tile. This default implementation assumes no tiling and no component * subsampling (i.e., all components, or components, have the same * dimensions in pixels). * * @param c The index of the component, from 0 to C-1. * * @return The height in pixels of component c in the current * tile. * */ public int getCompHeight(int c) { return h; } /** * Returns the width in pixels of the specified component in the overall * image. This default implementation assumes no component, or component, * subsampling (i.e. all components have the same dimensions in pixels). * * @param c The index of the component, from 0 to C-1. * * @return The width in pixels of component c in the overall * image. * */ public int getCompImgWidth(int c) { return w; } /** * Returns the height in pixels of the specified component in the overall * image. This default implementation assumes no component, or component, * subsampling (i.e. all components have the same dimensions in pixels). * * @param c The index of the component, from 0 to C-1. * * @return The height in pixels of component c in the overall * image. * */ public int getCompImgHeight(int c) { return h; } /** * Changes the current tile, given the new coordinates. * * @param x The horizontal coordinate of the tile. * * @param y The vertical coordinate of the new tile. * */ public void setTile(int x, int y) { if (x >= getNumXTiles()) { y += x/ getNumXTiles(); x = x % getNumXTiles(); } co.x = x; co.y = y; aTile = null; } /** * Advances to the next tile, in standard scan-line order (by rows then * columns). * */ public void nextTile() { co.x++; if (co.x >= getNumXTiles()) { co.x = 0; co.y++; } setTile(co.x, co.y); } /** * Returns the coordinates of the current tile. This default * implementation assumes no-tiling, so (0,0) is returned. * * @param co If not null this object is used to return the information. If * null a new one is created and returned. * * @return The current tile's coordinates. * */ public Point getTile(Point co) { if (co != null) return co; else return new Point(0, 0); } /** * Returns the index of the current tile, relative to a standard scan-line * order. * * @return The current tile's index (starts at 0). * */ public int getTileIdx() { return getNumXTiles() * co.y + co.x; } /** * Returns the horizontal and vertical offset of the upper-left corner of * the current tile, in the specified component, relative to the canvas * origin, in the component coordinates (not in the reference grid * coordinates). These are the coordinates of the current tile's (not * active tile) upper-left corner relative to the canvas. * * @param co If not null the object is used to return the values, if null * a new one is created and returned. * * @param c The index of the component (between 0 and C-1) * * @return The horizontal and vertical offsets of the upper-left corner of * the current tile, for the specified component, relative to the canvas * origin, in the component coordinates. * */ public Point getTileOff(Point p, int c) { if (p != null) { p.x = co.x * tileWidth + tileXOffset; p.y = co.y * tileHeight + tileYOffset; return co; } else return new Point(co.x * tileWidth + tileXOffset, co.y * tileHeight + tileYOffset); } /** * Returns the horizontal coordinate of the upper-left corner of the * active tile, with respect to the canvas origin, in the component * coordinates, for the specified component. * * @param c The index of the component (between 0 and C-1) * * @return The horizontal coordinate of the upper-left corner of the * active tile, with respect to the canvas origin, for component 'c', in * the component coordinates. * */ public int getCompULX(int c) { return raster.getMinX(); } /** * Returns the vertical coordinate of the upper-left corner of the active * tile, with respect to the canvas origin, in the component coordinates, * for the specified component. * * @param c The index of the component (between 0 and C-1) * * @return The vertical coordinate of the upper-left corner of the active * tile, with respect to the canvas origin, for component 'c', in the * component coordinates. * */ public int getCompULY(int c) { return raster.getMinY(); } /** * Returns the horizontal coordinate of the image origin, the top-left * corner, in the canvas system, on the reference grid. * * @return The horizontal coordinate of the image origin in the canvas * system, on the reference grid. * */ public int getImgULX() { return destinationRegion.x; } /** * Returns the vertical coordinate of the image origin, the top-left * corner, in the canvas system, on the reference grid. * * @return The vertical coordinate of the image origin in the canvas * system, on the reference grid. * */ public int getImgULY() { return destinationRegion.y; } /** * Returns the number of tiles in the horizontal and vertical * directions. * * @param co If not null this object is used to return the information. If * null a new one is created and returned. * * @return The number of tiles in the horizontal (Point.x) and vertical * (Point.y) directions. * */ public Point getNumTiles(Point co) { if (co != null) { co.x = getNumXTiles(); co.y = getNumYTiles(); return co; } else { return new Point(getNumXTiles(), getNumYTiles()); } } /** * Returns the total number of tiles in the image. This default * implementation assumes no tiling, so 1 is always returned. * * @return The total number of tiles in the image. * */ public int getNumTiles() { return getNumXTiles() * getNumYTiles(); } /** * Returns the number of bits corresponding to the nominal range of the * data in the specified component. This is the value rb (range bits) that * was specified in the constructor, which normally is 8 for non bilevel * data, and 1 for bilevel data. * *

If this number is b then the nominal range is between * -2^(b-1) and 2^(b-1)-1, since unsigned data is level shifted to have a * nominal avergae of 0. * * @param c The index of the component. * * @return The number of bits corresponding to the nominal range of the * data. For floating-point data this value is not applicable and the * return value is undefined. * */ public int getNomRangeBits(int c) { // Check component index // XXX: Should be component-dependent. return rb; } /** * Returns the position of the fixed point in the specified component * (i.e. the number of fractional bits), which is always 0 for this * ImgReader. * * @param c The index of the component. * * @return The position of the fixed-point (i.e. the number of fractional * bits). Always 0 for this ImgReader. * */ public int getFixedPoint(int c) { // Check component index return 0; } /** * Returns, in the blk argument, the block of image data containing the * specifed rectangular area, in the specified component. The data is * returned, as a reference to the internal data, if any, instead of as a * copy, therefore the returned data should not be modified. * *

After being read the coefficients are level shifted by subtracting * 2^(nominal bit range - 1) * *

The rectangular area to return is specified by the 'ulx', 'uly', 'w' * and 'h' members of the 'blk' argument, relative to the current * tile. These members are not modified by this method. The 'offset' and * 'scanw' of the returned data can be arbitrary. See the 'DataBlk' class. * *

If the data array in blk is null, then a new one * is created if necessary. The implementation of this interface may * choose to return the same array or a new one, depending on what is more * efficient. Therefore, the data array in blk prior to the * method call should not be considered to contain the returned data, a * new array may have been created. Instead, get the array from * blk after the method has returned. * *

The returned data always has its 'progressive' attribute unset * (i.e. false). * *

When an I/O exception is encountered the JJ2KExceptionHandler is * used. The exception is passed to its handleException method. The action * that is taken depends on the action that has been registered in * JJ2KExceptionHandler. See JJ2KExceptionHandler for details. * *

This method implements buffering for the 3 components: When the * first one is asked, all the 3 components are read and stored until they * are needed. * * @param blk Its coordinates and dimensions specify the area to * return. Some fields in this object are modified to return the data. * * @param c The index of the component from which to get the data. Only 0, * 1 and 3 are valid. * * @return The requested DataBlk * * @see #getCompData * * @see JJ2KExceptionHandler */ public final DataBlk getInternCompData(DataBlk blk, int c) { if (writer != null && writer.getAbortRequest()) throw new RuntimeException(J2KImageWriter.WRITE_ABORTED); if (barr == null) barr = new int[nc][]; // Check type of block provided as an argument if(blk.getDataType()!=DataBlk.TYPE_INT){ if(intBlk==null) intBlk = new DataBlkInt(blk.ulx,blk.uly,blk.w,blk.h); else{ intBlk.ulx = blk.ulx; intBlk.uly = blk.uly; intBlk.w = blk.w; intBlk.h = blk.h; } blk = intBlk; } float percentage = (getTileIdx() + (blk.uly + 1.0F) / blk.h) / getNumTiles(); writer.processImageProgressWrapper(percentage * 100.0F); // If asking a component for the first time for this block, read the 3 // components if ((barr[c] == null) || (dbi.ulx > blk.ulx) || (dbi.uly > blk.uly) || (dbi.ulx+dbi.w < blk.ulx+blk.w) || (dbi.uly+dbi.h < blk.uly+blk.h)) { int k,j,i,mi; // Reset data arrays if needed if (barr[c] == null || barr[c].length < blk.w*blk.h) { barr[c] = new int[blk.w*blk.h]; } blk.setData(barr[c]); for (i = (c + 1) % nc; i != c; i = (i + 1) % nc) if (barr[i] == null || barr[i].length < blk.w*blk.h) { barr[i] = new int[blk.w*blk.h]; } // set attributes of the DataBlk used for buffering dbi.ulx = blk.ulx; dbi.uly = blk.uly; dbi.w = blk.w; dbi.h = blk.h; // get data from the image if (aTile == null) { aTile = getTile(co.x, co.y); Rectangle temp = aTile.getBounds(); aTile = aTile.createTranslatedChild(temp.x-minX, temp.y-minY); } for (i = 0; i < nc ; i++) { aTile.getSamples(blk.ulx, blk.uly, blk.w, blk.h, i, barr[i]); for (k = 0; k < barr[i].length; k++) barr[i][k] -= dcOffset; } //getByteData(raster, new Rectangle(blk.ulx, blk.uly, blk.w, blk.h), barr); // Set buffer attributes blk.setData(barr[c]); blk.offset = 0; blk.scanw = blk.w; } else { //Asking for the 2nd or 3rd block component blk.setData(barr[c]); blk.offset = (blk.ulx-dbi.ulx)*dbi.w+blk.ulx-dbi.ulx; blk.scanw = dbi.scanw; } // Turn off the progressive attribute blk.progressive = false; return blk; } /** * Returns, in the blk argument, a block of image data containing the * specifed rectangular area, in the specified component. The data is * returned, as a copy of the internal data, therefore the returned data * can be modified "in place". * *

After being read the coefficients are level shifted by subtracting * 2^(nominal bit range - 1) * *

The rectangular area to return is specified by the 'ulx', 'uly', 'w' * and 'h' members of the 'blk' argument, relative to the current * tile. These members are not modified by this method. The 'offset' of * the returned data is 0, and the 'scanw' is the same as the block's * width. See the 'DataBlk' class. * *

If the data array in 'blk' is 'null', then a new one is created. If * the data array is not 'null' then it is reused, and it must be large * enough to contain the block's data. Otherwise an 'ArrayStoreException' * or an 'IndexOutOfBoundsException' is thrown by the Java system. * *

The returned data has its 'progressive' attribute unset * (i.e. false). * *

When an I/O exception is encountered the JJ2KExceptionHandler is * used. The exception is passed to its handleException method. The action * that is taken depends on the action that has been registered in * JJ2KExceptionHandler. See JJ2KExceptionHandler for details. * * @param blk Its coordinates and dimensions specify the area to * return. If it contains a non-null data array, then it must have the * correct dimensions. If it contains a null data array a new one is * created. The fields in this object are modified to return the data. * * @param c The index of the component from which to get the data. Only * 0,1 and 2 are valid. * * @return The requested DataBlk * * @see #getInternCompData * * @see JJ2KExceptionHandler * */ public final DataBlk getCompData(DataBlk blk, int c) { // NOTE: can not directly call getInterCompData since that returns // internally buffered data. int ulx,uly,w,h; // Check type of block provided as an argument if(blk.getDataType()!=DataBlk.TYPE_INT){ DataBlkInt tmp = new DataBlkInt(blk.ulx,blk.uly,blk.w,blk.h); blk = tmp; } int bakarr[] = (int[])blk.getData(); // Save requested block size ulx = blk.ulx; uly = blk.uly; w = blk.w; h = blk.h; // Force internal data buffer to be different from external blk.setData(null); getInternCompData(blk,c); // Copy the data if (bakarr == null) { bakarr = new int[w*h]; } if (blk.offset == 0 && blk.scanw == w) { // Requested and returned block buffer are the same size System.arraycopy(blk.getData(),0,bakarr,0,w*h); } else { // Requested and returned block are different for (int i=h-1; i>=0; i--) { // copy line by line System.arraycopy(blk.getData(),blk.offset+i*blk.scanw, bakarr,i*w,w); } } blk.setData(bakarr); blk.offset = 0; blk.scanw = blk.w; return blk; } /** * Returns true if the data read was originally signed in the specified * component, false if not. This method always returns false since PPM * data is always unsigned. * * @param c The index of the component, from 0 to N-1. * * @return always false, since PPM data is always unsigned. * */ public boolean isOrigSigned(int c) { if (isBinary) return true; // Check component index SampleModel sm = null; if (inputIsRaster) sm = raster.getSampleModel(); else sm = src.getSampleModel(); if (sm.getDataType() == DataBuffer.TYPE_USHORT || sm.getDataType() == DataBuffer.TYPE_BYTE) return false; return true; } private int getNumXTiles() { int x = destinationRegion.x; int tx = tileXOffset; int tw = tileWidth; return ToTile(x + destinationRegion.width - 1, tx, tw) - ToTile(x, tx, tw) + 1; } private int getNumYTiles() { int y = destinationRegion.y; int ty = tileYOffset; int th = tileHeight; return ToTile(y + destinationRegion.height - 1, ty, th) - ToTile(y, ty, th) + 1; } private static int ToTile(int pos, int tileOffset, int tileSize) { pos -= tileOffset; if (pos < 0) { pos += 1 - tileSize; // force round to -infinity (ceiling) } return pos/tileSize; } private Raster getTile(int tileX, int tileY) { int sx = tileXOffset + tileX * tileWidth; int sy = tileYOffset + tileY * tileHeight; tileX += tileXOffset / tileWidth; tileY += tileYOffset / tileHeight; if (inputIsRaster) { if (noTransform) { return raster.createChild(sx, sy, getTileWidth(), getTileHeight(), sx, sy, sourceBands); } WritableRaster ras = Raster.createWritableRaster(sm, new Point(sx, sy)); int x = mapToSourceX(sx); int y = mapToSourceY(sy); int minY = raster.getMinY(); int maxY = raster.getMinY() + raster.getHeight(); int cTileWidth = getTileWidth(); for (int j = 0; j < getTileHeight(); j++, sy++, y += scaleY) { if (y < minY || y >= maxY) continue; Raster source = raster.createChild(x, y, (cTileWidth - 1) * scaleX + 1, 1, x, y, null); int tempX = sx; for (int i = 0, offset = x; i < cTileWidth; i++, tempX++, offset += scaleX) { for (int k = 0; k < nc; k++) { int p = source.getSample(offset, y, sourceBands[k]); ras.setSample(tempX, sy, k, p); } } } return ras; } else { if (noTransform) { Raster ras = src.getTile(tileX, tileY); if (noSubband) return ras; else { return ras.createChild(sx, sy, tileWidth, tileHeight, sx, sy, sourceBands); } } WritableRaster ras = Raster.createWritableRaster(sm, new Point(sx, sy)); int x = mapToSourceX(sx); int y = mapToSourceY(sy); int minY = src.getMinY(); int maxY = src.getMinY() + src.getHeight(); int length = tileWidth * scaleX; if (x + length >= src.getWidth()) length = src.getWidth() - x; int dLength = (length + scaleX -1 ) / scaleX; for (int j = 0; j < tileHeight; j++, sy++, y += scaleY) { if (y < minY || y >= maxY) continue; Raster source = src.getData(new Rectangle(x, y, length, 1)); int tempX = sx; for (int i = 0, offset = x; i < dLength; i++, tempX++, offset += scaleX) { for (int k = 0; k < nc; k++) { int p = source.getSample(offset, y, sourceBands[k]); ras.setSample(tempX, sy, k, p); } } } return ras; } } private int mapToSourceX(int x) { return x * scaleX + xOffset; } private int mapToSourceY(int y) { return y * scaleY + yOffset; } } ././@LongLink0000000000000000000000000000016000000000000011562 Lustar rootrootjai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/jpeg2000/J2KRenderedImageCodecLib.javajai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/jpeg2000/J2KRenderedImageCo0000664000175100017510000011740410510572336032101 0ustar tilletille/* * $RCSfile: J2KRenderedImageCodecLib.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.4 $ * $Date: 2006-10-03 23:40:14 $ * $State: Exp $ */ package com.sun.media.imageioimpl.plugins.jpeg2000; import javax.imageio.IIOException; import javax.imageio.ImageReadParam; import javax.imageio.stream.ImageInputStream; import java.awt.Point; import java.awt.Rectangle; import java.awt.Transparency; import java.awt.color.ColorSpace; import java.awt.color.ICC_ColorSpace; import java.awt.color.ICC_Profile; import java.awt.image.BufferedImage; import java.awt.image.ColorModel; import java.awt.image.ComponentColorModel; import java.awt.image.ComponentSampleModel; import java.awt.image.DataBuffer; import java.awt.image.DirectColorModel; import java.awt.image.IndexColorModel; import java.awt.image.MultiPixelPackedSampleModel; import java.awt.image.PixelInterleavedSampleModel; import java.awt.image.SinglePixelPackedSampleModel; import java.awt.image.Raster; import java.awt.image.RenderedImage; import java.awt.image.SampleModel; import java.awt.image.WritableRaster; import java.io.IOException; import java.lang.reflect.Constructor; import java.lang.reflect.Method; import java.lang.reflect.InvocationTargetException; import com.sun.medialib.codec.jp2k.CompParams; import com.sun.medialib.codec.jp2k.Constants; import com.sun.medialib.codec.jp2k.Decoder; import com.sun.medialib.codec.jp2k.Size; import com.sun.medialib.codec.jiio.mediaLibImage; import com.sun.media.imageio.plugins.jpeg2000.J2KImageReadParam; import com.sun.media.imageioimpl.common.SimpleRenderedImage; import com.sun.media.imageioimpl.common.ImageUtil; // XXX Overall documentation public class J2KRenderedImageCodecLib extends SimpleRenderedImage { /** The sample model for the original image. */ private SampleModel originalSampleModel; private Raster currentTile; private Point currentTileGrid; private J2KMetadata metadata; /** The input stream we read from */ private ImageInputStream iis = null; /** Caches the J2KImageReader which creates this object. This * variable is used to monitor the abortion. */ private J2KImageReaderCodecLib reader; /** The J2KImageReadParam to create this * renderedImage. */ private J2KImageReadParam param = null; /** Caches the medialib decoder. */ private Decoder decoder; private Size size; private CompParams compParam; private int xStep, yStep; // JPEG 2000 internal subsampling parameters /** The destination bounds. */ Rectangle destinationRegion; Rectangle originalRegion; Point sourceOrigin; /** The subsampling parameters. */ private int scaleX, scaleY, xOffset, yOffset; private int[] destinationBands = null; private int[] sourceBands = null; private int nComp; private int[] channelMap; /** Coordinate transform is not needed from the source (image stream) * to the destination. */ private boolean noTransform = true; /** The raster for medialib tiles to share. */ private WritableRaster rasForATile; private BufferedImage destImage; public J2KRenderedImageCodecLib(ImageInputStream iis, J2KImageReaderCodecLib reader, ImageReadParam param) throws IOException { this.iis = iis; this.reader = reader; // Ensure the ImageReadParam is a J2KImageReadParam boolean allowZeroDestOffset = true; if(param == null) { // Use the default param = (J2KImageReadParam)reader.getDefaultReadParam(); allowZeroDestOffset = false; } else if(!(param instanceof J2KImageReadParam)) { // Create a new one param = new J2KImageReadParamJava(param); allowZeroDestOffset = false; } this.param = (J2KImageReadParam)param; decoder = new Decoder(iis); decoder.setMode(Constants.JP2K_COMPOSITE_TILE); //set resolution before any calling of any calling for decode/decodeSize int resolution = ((J2KImageReadParam)param).getResolution(); if (resolution != -1) decoder.setMaxLevels(resolution); size = decoder.decodeSize(null); compParam = new CompParams(); for (int i = 0; i < size.csize; i++) { decoder.decodeCompParams(compParam, i); if(i == 0) { xStep = compParam.xstep; yStep = compParam.ystep; } else if(compParam.xstep != xStep || compParam.ystep != yStep) { // All components must have same subsampling along each axis. throw new IIOException ("All components must have the same subsampling factors!"); } } // Set source sub-banding. sourceBands = param.getSourceBands(); if (sourceBands == null) { nComp = size.csize; sourceBands = new int[nComp]; for (int i = 0; i < nComp; i++) sourceBands[i] = i; } else { for(int i = 0; i < sourceBands.length; i++) { if(sourceBands[i] < 0 || sourceBands[i] >= size.csize) { throw new IIOException ("Source band out of range!"); } } } // Cache number of components. nComp = sourceBands.length; // Set destination sub-banding. destinationBands = param.getDestinationBands(); if (destinationBands == null) { destinationBands = new int[nComp]; for (int i = 0; i < nComp; i++) destinationBands[i] = i; } else { for(int i = 0; i < destinationBands.length; i++) { if(destinationBands[i] < 0 || destinationBands[i] >= size.csize) { throw new IIOException ("Destination band out of range!"); } } } // Check number of source and dest bands. if(destinationBands.length != sourceBands.length) { throw new IIOException ("Number of source and destination bands must be equal!"); } this.width = (size.xosize + size.xsize + xStep - 1)/xStep; this.height = (size.yosize + size.ysize + yStep - 1)/yStep; Rectangle sourceRegion = new Rectangle(0, 0, this.width, this.height); originalRegion = (Rectangle)sourceRegion.clone(); destinationRegion = (Rectangle)sourceRegion.clone(); J2KImageReader.computeRegionsWrapper(param, allowZeroDestOffset, this.width, this.height, param.getDestination(), sourceRegion, destinationRegion); scaleX = param.getSourceXSubsampling(); scaleY = param.getSourceYSubsampling(); xOffset = param.getSubsamplingXOffset(); yOffset = param.getSubsamplingYOffset(); sourceOrigin = new Point(sourceRegion.x, sourceRegion.y); if (!destinationRegion.equals(originalRegion)) noTransform = false; this.tileWidth = (size.xtsize + xStep - 1)/xStep; this.tileHeight = (size.ytsize + yStep - 1)/yStep; this.tileGridXOffset = (size.xtosize + xStep - 1)/xStep - (size.xosize + xStep - 1)/xStep; this.tileGridYOffset = (size.ytosize + yStep - 1)/yStep - (size.yosize + yStep - 1)/yStep; this.width = destinationRegion.width; this.height = destinationRegion.height; this.minX = destinationRegion.x; this.minY = destinationRegion.y; originalSampleModel = createOriginalSampleModel(); sampleModel = createSampleModel(); colorModel = createColorModel(); tileGridXOffset += (XToTileX(minX) - XToTileX(tileGridXOffset)) * tileWidth; tileGridYOffset += (YToTileY(minY) - YToTileY(tileGridYOffset)) * tileHeight; // sets the resolution and decoding rate to the medialib decoder // Java decoding rate is in bit-per-pixel; the medialib rate is in // percentage; so convert first. double rate = ((J2KImageReadParam)param).getDecodingRate(); if (rate != Double.MAX_VALUE) { // XXX Obtain bits per sample from elsewhere, e.g., ColorModel. rate /= ImageUtil.getElementSize(sampleModel); decoder.setRate(rate, 0); } } public synchronized Raster getTile(int tileX, int tileY) { if (currentTile != null && currentTileGrid.x == tileX && currentTileGrid.y == tileY) return currentTile; if (tileX < getMinTileX() || tileY < getMinTileY() || tileX > getMaxTileX() || tileY > getMaxTileY()) throw new IllegalArgumentException(I18N.getString("J2KReadState1")); int x = tileXToX(tileX); int y = tileYToY(tileY); currentTile = Raster.createWritableRaster(sampleModel, new Point(x, y)); try { readAsRaster((WritableRaster)currentTile); } catch(IOException ioe) { throw new RuntimeException(ioe); } if (currentTileGrid == null) currentTileGrid = new Point(tileX, tileY); else { currentTileGrid.x = tileX; currentTileGrid.y = tileY; } return currentTile; } synchronized WritableRaster readAsRaster(WritableRaster raster) throws IOException { int x = raster.getMinX(); int y = raster.getMinY(); try { if (noTransform) { int E2c = (size.xosize + xStep - 1)/xStep; int E1c = (size.yosize + yStep - 1)/yStep; int tXStart = ((x + E2c)*xStep - size.xtosize)/size.xtsize; int tXEnd = ((x + raster.getWidth() - 1 + E2c)*xStep - size.xtosize)/ size.xtsize; int tYStart = ((y + E2c)*yStep - size.ytosize)/size.ytsize; int tYEnd = ((y + raster.getHeight() - 1 + E2c)*yStep - size.ytosize)/ size.ytsize; int sourceFormatTag = MediaLibAccessor.findCompatibleTag(raster); if(tXStart == tXEnd && tYStart == tYEnd) { MediaLibAccessor accessor = new MediaLibAccessor(raster, raster.getBounds().intersection(originalRegion), sourceFormatTag, true); mediaLibImage[] mlImage = accessor.getMediaLibImages(); //this image may be a subregion of the image in the stream // So use the original tile number. int tileNo = tXStart + tYStart*size.nxtiles; decoder.decode(mlImage, tileNo); accessor.copyDataToRaster(channelMap); } else { for(int ty = tYStart; ty <= tYEnd; ty++) { for(int tx = tXStart; tx <= tXEnd; tx++) { int sx = (size.xtosize + tx*size.xtsize + xStep - 1)/xStep - E2c; int sy = (size.ytosize + ty*size.ytsize + yStep - 1)/yStep - E1c; int ex = (size.xtosize + (tx + 1)*size.xtsize + xStep - 1)/xStep - E2c; int ey = (size.ytosize + (ty + 1)*size.ytsize + yStep - 1)/yStep - E1c; Rectangle subRect = new Rectangle(sx, sy, ex - sx, ey - sy); if(subRect.isEmpty()) { continue; } if (rasForATile == null) { rasForATile = Raster.createWritableRaster (originalSampleModel, null); } WritableRaster subRaster = rasForATile.createWritableChild (rasForATile.getMinX(), rasForATile.getMinY(), subRect.width, subRect.height, subRect.x, subRect.y, null); MediaLibAccessor accessor = new MediaLibAccessor(subRaster, subRect, sourceFormatTag, true); mediaLibImage[] mlImage = accessor.getMediaLibImages(); int tileNo = tx + ty*size.nxtiles; decoder.decode(mlImage, tileNo); accessor.copyDataToRaster(channelMap); Rectangle rasBounds = raster.getBounds(); Rectangle childRect = rasBounds.intersection(subRect); if(childRect.isEmpty()) { continue; } Raster childRaster = subRaster.createChild(childRect.x, childRect.y, childRect.width, childRect.height, childRect.x, childRect.y, null); ((WritableRaster)raster).setRect(childRaster); } } } } else { readSubsampledRaster(raster); } } catch (IOException e) { throw new RuntimeException(e); } return raster; } private void readSubsampledRaster(WritableRaster raster) throws IOException { int numBands = sourceBands.length; Rectangle destRect = raster.getBounds().intersection(destinationRegion); int offx = destinationRegion.x; int offy = destinationRegion.y; int sourceSX = (destRect.x - offx) * scaleX + sourceOrigin.x; int sourceSY = (destRect.y - offy) * scaleY + sourceOrigin.y; int sourceEX = (destRect.width - 1) * scaleX + sourceSX; int sourceEY = (destRect.height - 1)* scaleY + sourceSY; int E2c = (size.xosize + xStep - 1)/xStep; int E1c = (size.yosize + yStep - 1)/yStep; int startXTile = ((sourceSX + E2c)*xStep - size.xtosize)/size.xtsize; int endXTile = ((sourceEX + E2c)*xStep - size.xtosize)/size.xtsize; int startYTile = ((sourceSY + E1c)*yStep - size.ytosize)/size.ytsize; int endYTile = ((sourceEY + E1c)*yStep - size.ytosize)/size.ytsize; startXTile = clip(startXTile, 0, size.nxtiles - 1); startYTile = clip(startYTile, 0, size.nytiles - 1); endXTile = clip(endXTile, 0, size.nxtiles - 1); endYTile = clip(endYTile, 0, size.nytiles - 1); int totalXTiles = endXTile - startXTile + 1; int totalYTiles = endYTile - startYTile + 1; int totalTiles = totalXTiles * totalYTiles; int[] pixbuf = null; // integer buffer for the decoded pixels. // Start the data delivery to the cached consumers tile by tile for(int y=startYTile; y <= endYTile; y++){ if (reader.getAbortRequest()) break; // Loop on horizontal tiles for(int x=startXTile; x <= endXTile; x++){ if (reader.getAbortRequest()) break; float percentage = // XXX Incorrect? (x - startXTile + 1.0F + y * totalXTiles) / totalTiles; int startX = (x * size.xtsize + size.xtosize + xStep - 1)/xStep - E2c; int startY = (y * size.ytsize + size.ytosize + yStep - 1)/yStep - E1c; int endX = ((x + 1)*size.xtsize + size.xtosize + xStep - 1)/ xStep - E2c; int endY = ((y + 1)*size.ytsize + size.ytosize + yStep - 1)/ yStep - E1c; if (rasForATile == null) { rasForATile = Raster.createWritableRaster(originalSampleModel, new Point(startX, startY)); } else { rasForATile = rasForATile.createWritableTranslatedChild(startX, startY); } int tw = endX - startX; int th = endY - startY; WritableRaster targetRas; if(tw != tileWidth || th != tileHeight) { targetRas = rasForATile.createWritableChild (startX, startY, tw, th, startX, startY, null); } else { targetRas = rasForATile; } int sourceFormatTag = MediaLibAccessor.findCompatibleTag(targetRas); MediaLibAccessor accessor = new MediaLibAccessor(targetRas, // targetRas.getBounds(), targetRas.getBounds().intersection(originalRegion), sourceFormatTag, true); mediaLibImage[] mlImage = accessor.getMediaLibImages(); decoder.decode(mlImage, x + y * size.nxtiles); accessor.copyDataToRaster(channelMap); int cTileHeight = th; int cTileWidth = tw; if (startY + cTileHeight >= originalRegion.height) cTileHeight = originalRegion.height - startY; if (startX + cTileWidth >= originalRegion.width) cTileWidth = originalRegion.width - startX; int tx = startX; int ty = startY; if (sourceSX > startX) { cTileWidth += startX - sourceSX; tx = sourceSX; startX = sourceSX; } if (sourceSY > startY) { cTileHeight += startY - sourceSY; ty = sourceSY; startY = sourceSY; } if (sourceEX < startX + cTileWidth - 1) { cTileWidth += sourceEX - startX - cTileWidth + 1; } if (sourceEY < startY + cTileHeight - 1) { cTileHeight += sourceEY - startY - cTileHeight + 1; } // The start X in the destination int x1 = (startX + scaleX - 1 - sourceOrigin.x) / scaleX; int x2 = (startX + scaleX -1 + cTileWidth - sourceOrigin.x) / scaleX; int lineLength = x2 - x1; // Suppress further processing if lineLength is non-positive // XXX (which it should never be). if(lineLength <= 0) continue; x2 = (x2 - 1) * scaleX + sourceOrigin.x; int y1 = (startY + scaleY -1 - sourceOrigin.y) /scaleY; startY = y1 * scaleY + sourceOrigin.y; startX = x1 * scaleX + sourceOrigin.x; x1 += offx; y1 += offy; if (pixbuf == null || pixbuf.length < lineLength) pixbuf = new int[lineLength]; // line buffer for pixel data // Deliver in lines to reduce memory usage for (int l = startY, m = y1; l < ty + cTileHeight; l += scaleY, m++) { if (reader.getAbortRequest()) break; // Request line data for (int i = 0; i < numBands; i++) { for (int j = lineLength - 1, k1 = x2; j >= 0; j--, k1-=scaleX) { pixbuf[j] = targetRas.getSample(k1, l, i); } // Send the line data to the BufferedImage raster.setSamples(x1, m, lineLength, 1, destinationBands[i], pixbuf); } if (destImage != null) reader.processImageUpdateWrapper(destImage, x1, m, cTileWidth, 1, 1, 1, destinationBands); reader.processImageProgressWrapper(percentage + (l - startY + 1.0F) / cTileHeight / totalTiles); } } // End loop on horizontal tiles } // End loop on vertical tiles } public void setDestImage(BufferedImage image) { destImage = image; } public void clearDestImage() { destImage = null; } private int getTileNum(int x, int y) { int num = (y - getMinTileY()) * getNumXTiles() + x - getMinTileX(); if (num < 0 || num >= getNumXTiles() * getNumYTiles()) throw new IllegalArgumentException(I18N.getString("J2KReadState1")); return num; } private int clip(int value, int min, int max) { if (value < min) value = min; if (value > max) value = max; return value; } private SampleModel createSampleModel() throws IOException { if (sampleModel != null) return sampleModel; if (metadata == null) readImageMetadata(); HeaderBox header = (HeaderBox)metadata.getElement("JPEG2000HeaderBox"); int maxDepth = 0; boolean isSigned = false; if (header != null) { maxDepth = header.getBitDepth(); isSigned = (maxDepth & 0x80) > 0; maxDepth = (maxDepth & 0x7F) + 1; } else { CompParams compParam = new CompParams(); for (int i = 0; i < size.csize; i++) { decoder.decodeCompParams(compParam, i); maxDepth = (compParam.depth & 0x7F) + 1; isSigned = (compParam.depth & 0x80) > 0 ? true : false; } } BitsPerComponentBox bits = (BitsPerComponentBox)metadata.getElement("JPEG2000BitsPerComponentBox"); if (bits != null) { byte[] depths = bits.getBitDepth(); maxDepth = (depths[0] & 0x7F) + 1; isSigned = (depths[0] & 0x80) > 0; for (int i = 1; i < nComp; i++) if (maxDepth > depths[sourceBands[i]]) maxDepth = (depths[sourceBands[i]] & 0x7F) + 1; } int[] bandOffsets = new int[nComp]; for (int i = 0; i < nComp; i++) bandOffsets[i] = i; ChannelDefinitionBox cdb= (ChannelDefinitionBox)metadata.getElement("JPEG2000ChannelDefinitionBox"); if (cdb != null && metadata.getElement("JPEG2000PaletteBox") == null) { short[] assoc = cdb.getAssociation(); short[] types = cdb.getTypes(); short[] channels = cdb.getChannel(); for (int i = 0; i < types.length; i++) if (types[i] == 0) bandOffsets[sourceBands[channels[i]]] = assoc[i] - 1; else if (types[i] == 1 || types[i] == 2) bandOffsets[sourceBands[channels[i]]] = channels[i]; } return createSampleModel(nComp, maxDepth, bandOffsets, isSigned, tileWidth, tileHeight); } private SampleModel createOriginalSampleModel() throws IOException { if (metadata == null) readImageMetadata(); HeaderBox header = (HeaderBox)metadata.getElement("JPEG2000HeaderBox"); int maxDepth = 0; boolean isSigned = false; int nc = size.csize; if (header != null) { maxDepth = header.getBitDepth(); isSigned = (maxDepth & 0x80) > 0; maxDepth = (maxDepth & 0x7F) + 1; } else { CompParams compParam = new CompParams(); for (int i = 0; i < size.csize; i++) { decoder.decodeCompParams(compParam, i); maxDepth = (compParam.depth & 0x7F) + 1; isSigned = (compParam.depth & 0x80) > 0 ? true : false; } } BitsPerComponentBox bits = (BitsPerComponentBox)metadata.getElement("JPEG2000BitsPerComponentBox"); if (bits != null) { byte[] depths = bits.getBitDepth(); maxDepth = (depths[0] & 0x7F) + 1; isSigned = (depths[0] & 0x80) > 0; for (int i = 1; i < nc; i++) if (maxDepth > depths[i]) maxDepth = (depths[i] & 0x7F) + 1; } int[] bandOffsets = new int[nc]; for (int i = 0; i < nc; i++) bandOffsets[i] = i; ChannelDefinitionBox cdb= (ChannelDefinitionBox)metadata.getElement("JPEG2000ChannelDefinitionBox"); if (cdb != null && metadata.getElement("JPEG2000PaletteBox") == null) { short[] assoc = cdb.getAssociation(); short[] types = cdb.getTypes(); short[] channels = cdb.getChannel(); channelMap = new int[nc]; for (int i = 0; i < types.length; i++) if (types[i] == 0) { bandOffsets[channels[i]] = assoc[i] - 1; channelMap[assoc[i] - 1] = channels[i]; } else if (types[i] == 1 || types[i] == 2) { bandOffsets[channels[i]] = channels[i]; channelMap[channels[i]] = channels[i]; } } return createSampleModel(nc, maxDepth, bandOffsets, isSigned, tileWidth, tileHeight); } private SampleModel createSampleModel(int nc, int maxDepth, int[] bandOffsets, boolean isSigned, int tw, int th) { SampleModel sm = null; if (nc == 1 && (maxDepth == 1 || maxDepth == 2 || maxDepth == 4)) sm = new MultiPixelPackedSampleModel(DataBuffer.TYPE_BYTE, tw, th, maxDepth); else if (maxDepth <= 8) sm = new PixelInterleavedSampleModel(DataBuffer.TYPE_BYTE, tw, th, nc, tw * nc, bandOffsets); else if (maxDepth <=16) sm = new PixelInterleavedSampleModel(isSigned ? DataBuffer.TYPE_SHORT : DataBuffer.TYPE_USHORT, tw, th, nc, tw * nc, bandOffsets); else if (maxDepth <= 32) sm = new PixelInterleavedSampleModel(DataBuffer.TYPE_INT, tw, th, nComp, tw * nComp, bandOffsets); else throw new IllegalArgumentException(I18N.getString("J2KReadState11") + " " + + maxDepth); return sm; } private ColorModel createColorModel() throws IOException { if (colorModel != null) return colorModel; PaletteBox pBox = (PaletteBox)metadata.getElement("JPEG2000PaletteBox"); ChannelDefinitionBox cdef = (ChannelDefinitionBox)metadata.getElement("JPEG2000ChannelDefinitionBox"); // Check 'nComp' instance variable here in case there is an // embedded palette such as in the pngsuite images pp0n2c16.png // and pp0n6a08.png. if (pBox != null && nComp == 1) { byte[][] lut = pBox.getLUT(); int numComp = pBox.getNumComp(); int[] mapping = new int[numComp]; for (int i = 0; i < numComp; i++) mapping[i] = i; ComponentMappingBox cmap = (ComponentMappingBox)metadata.getElement("JPEG2000ComponentMappingBox"); short[] comps = null; byte[] type = null; byte[] maps = null; if (cmap != null) { comps = cmap.getComponent(); type = cmap.getComponentType(); maps = cmap.getComponentAssociation(); } if (comps != null) for (int i = 0; i < numComp; i++) if (type[i] == 1) mapping[i] = maps[i]; if (numComp == 3) colorModel = new IndexColorModel(sampleModel.getSampleSize(0), lut[0].length, lut[mapping[0]], lut[mapping[1]], lut[mapping[2]]); else if (numComp == 4) colorModel = new IndexColorModel(sampleModel.getSampleSize(0), lut[0].length, lut[mapping[0]], lut[mapping[1]], lut[mapping[2]], lut[mapping[3]]); } else if (cdef != null){ HeaderBox header = (HeaderBox)metadata.getElement("JPEG2000HeaderBox"); int numComp = header.getNumComponents(); int bitDepth = header.getBitDepth(); boolean hasAlpha = false; int alphaChannel = numComp - 1; short[] channels = cdef.getChannel(); short[] cType = cdef.getTypes(); short[] associations = cdef.getAssociation(); for (int i = 0; i < channels.length; i++) { if (cType[i] == 1 && channels[i] == alphaChannel) hasAlpha = true; } boolean[] isPremultiplied = new boolean[] {false}; if (hasAlpha) { isPremultiplied = new boolean[alphaChannel]; for (int i = 0; i < alphaChannel; i++) isPremultiplied[i] = false; for (int i = 0; i < channels.length; i++) { if (cType[i] == 2) isPremultiplied[associations[i] - 1] = true; } for (int i = 1; i < alphaChannel; i++) isPremultiplied[0] &= isPremultiplied[i]; } ColorSpecificationBox cBox = (ColorSpecificationBox)metadata.getElement("JPEG2000ColorSpecificationBox"); ICC_Profile profile = null; int colorSpaceType = 0; if (cBox != null) { profile = cBox.getICCProfile(); colorSpaceType = cBox.getEnumeratedColorSpace(); } ColorSpace cs = null; if (profile != null) cs = new ICC_ColorSpace(profile); else if (colorSpaceType == ColorSpecificationBox.ECS_sRGB) cs = ColorSpace.getInstance(ColorSpace.CS_sRGB); else if (colorSpaceType == ColorSpecificationBox.ECS_GRAY) cs = ColorSpace.getInstance(ColorSpace.CS_GRAY); else if (colorSpaceType == ColorSpecificationBox.ECS_YCC) cs = ColorSpace.getInstance(ColorSpace.CS_PYCC); byte[] bitDepths = null; boolean isSigned = ((bitDepth & 0x80) == 0x80) ? true : false; BitsPerComponentBox bitBox = (BitsPerComponentBox)metadata.getElement("JPEG2000BitsPerComponentBox"); if (bitBox != null) bitDepths = bitBox.getBitDepth(); int[] bits = new int[numComp]; for (int i = 0; i < numComp; i++) if (bitDepths != null) bits[i] = (bitDepths[i] & 0x7F) + 1; else bits[i] = (bitDepth &0x7F) + 1; int maxBitDepth = 1 + (bitDepth & 0x7F); if (bitDepths != null) for (int i = 0; i < numComp; i++) if (bits[i] > maxBitDepth) maxBitDepth = bits[i]; int type = -1; if (maxBitDepth <= 8) type = DataBuffer.TYPE_BYTE; else if (maxBitDepth <= 16) type = isSigned ? DataBuffer.TYPE_SHORT : DataBuffer.TYPE_USHORT; else if (maxBitDepth <= 32) type = DataBuffer.TYPE_INT; if (type == -1) return null; if (cs != null) { colorModel = new ComponentColorModel(cs, bits, hasAlpha, isPremultiplied[0], hasAlpha ? Transparency.TRANSLUCENT : Transparency.OPAQUE , type); } } if (colorModel != null) return colorModel; if(nComp <= 4) { // XXX: Code essentially duplicated from FileFormatReader.getColorModel(). // Create the ColorModel from the SIZ marker segment parameters. ColorSpace cs; if(nComp > 2) { cs = ColorSpace.getInstance(ColorSpace.CS_sRGB); } else { cs = ColorSpace.getInstance(ColorSpace.CS_GRAY); } int[] bitsPerComponent = new int[nComp]; boolean isSigned = false; int maxBitDepth = -1; for(int i = 0; i < nComp; i++) { bitsPerComponent[i] = (compParam.depth & 0x7f) + 1; if(maxBitDepth < bitsPerComponent[i]) { maxBitDepth = bitsPerComponent[i]; } isSigned |= (compParam.depth & 0x80) != 0; } boolean hasAlpha = nComp % 2 == 0; int type = -1; if (maxBitDepth <= 8) { type = DataBuffer.TYPE_BYTE; } else if (maxBitDepth <= 16) { type = isSigned ? DataBuffer.TYPE_SHORT : DataBuffer.TYPE_USHORT; } else if (maxBitDepth <= 32) { type = DataBuffer.TYPE_INT; } if (type != -1) { if (nComp == 1 && (maxBitDepth == 1 || maxBitDepth == 2 || maxBitDepth == 4)) { colorModel = ImageUtil.createColorModel(getSampleModel()); } else { colorModel = new ComponentColorModel(cs, bitsPerComponent, hasAlpha, false, hasAlpha ? Transparency.TRANSLUCENT : Transparency.OPAQUE , type); } return colorModel; } } return ImageUtil.createColorModel(null, getSampleModel()); } public J2KMetadata readImageMetadata() throws IOException { if (metadata == null) { metadata = new J2KMetadata(); com.sun.medialib.codec.jp2k.Box mlibBox = null; com.sun.media.imageioimpl.plugins.jpeg2000.Box box = null; while ((mlibBox = decoder.decodeBox()) != null) { box = null; Class c = com.sun.media.imageioimpl.plugins.jpeg2000.Box.getBoxClass(mlibBox.type); if (c != null) { try { Constructor cons = c.getConstructor(new Class[]{byte[].class}); if (cons != null) { box = (Box)cons.newInstance(new Object[]{mlibBox.data}); } } catch(NoSuchMethodException e) { try { Constructor cons = c.getConstructor(new Class[]{int.class, byte[].class}); if (cons != null) { box = (com.sun.media.imageioimpl.plugins.jpeg2000.Box) cons.newInstance(new Object[]{new Integer(mlibBox.type), mlibBox.data}); } } catch (NoSuchMethodException e1) { box = createUnknowBox(mlibBox); } catch(InvocationTargetException e1) { box = createUnknowBox(mlibBox); } catch (IllegalAccessException e1) { box = createUnknowBox(mlibBox); } catch (InstantiationException e1) { box = createUnknowBox(mlibBox); } } catch(InvocationTargetException e) { box = createUnknowBox(mlibBox); } catch (IllegalAccessException e) { box = createUnknowBox(mlibBox); } catch (InstantiationException e) { box = createUnknowBox(mlibBox); } } else { if (mlibBox.data != null) box = createUnknowBox(mlibBox); } if (box != null) metadata.addNode(box); } } return metadata; } private com.sun.media.imageioimpl.plugins.jpeg2000.Box createUnknowBox(com.sun.medialib.codec.jp2k.Box mlibBox) { return new com.sun.media.imageioimpl.plugins.jpeg2000.Box(8 + mlibBox.data.length, mlibBox.type, mlibBox.data); } } jai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/jpeg2000/properties0000664000175100017510000000530710203036165031001 0ustar tilletille# # $RCSfile: properties,v $ # # Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved. # # Use is subject to license terms. # # $Revision: 1.1 $ # $Date: 2005-02-11 05:01:38 $ # $State: Exp $ # # Internationalization file for com.sun.media.imageioimpl.plugins.jpeg2000 Box0=A simple box should have a static methos getElementNames. Box1=Length should be 1 when set extra length. Box2=Content length should be length - 8 or extraLength - 16. J2KImageReader0=The source region is null. J2KImageReader1=The destination region is null. J2KImageReader2=The destination region is empty. J2KImageReader3=The destination or source region is empty. J2KImageReader4=Only support to decode the first image in JP2 stream. J2KImageReader5=The provided ImageReadParam isn't a J2KImageReadParam. J2KImageReader6=The input source has not been set. J2KImageReader7=seekForwardOnly == true! J2KImageWriteParamJava0=Packet per tile part cannot be negative. J2KImageWriter0=The provided output is not an ImageOutputStream. J2KImageWriter1=Packet headers cannot be in both main and tile headers. J2KImageWriter2=Cannot set lossless and encoding rate at the same time. J2KImageWriter3=The image origin coordinates should not be negative. J2KImageWriter4=Invalid tile grid settings. J2KImageWriter5=Only byte/short/ushort/int types are supported. J2KImageWriter6=Only up to 16384 bands are supported. J2KImageWriter7=output == null! J2KImageWriter8=image == null! J2KImageWriterMedialib0=The source region is empty. J2KImageWriterMedialib1=output == null! J2KImageWriterMedialib2=image == null! J2KMetadata0=The provided metadata format is null. J2KMetadata1=The provided metadata format isn't recognized. J2KMetadata2=The tree to be merged is null. J2KMetadata3=Invalid node J2KMetadata4=Input node should be ColorSpaceType. J2KMetadata5=Input node should be Palette. J2KMetadata6=Input node should be Data. J2KMetadata7=Input node should be Dimension. J2KMetadata8=Input node should be Transparency. J2KReadState0=Null ImageInputStream/ImageReadParam/Metadata is provided. J2KReadState1=The provided tile grid position is out of range. J2KReadState2=Codestream too short or bad header. J2KReadState3=Error while reading bit stream header or parsing packets J2KReadState4=Could not instantiate bit stream reader J2KReadState5=Could not instantiate entropy decoder J2KReadState6=Could not instantiate roi de-scaler J2KReadState7=Could not instantiate dequantizer J2KReadState8=Could not instantiate inverse wavelet transform J2KReadState9=An error has occured during decoding. J2KReadState10=An uncaught runtime exception has occurred J2KReadState11=Cannot supported for this depth : J2KReadState12=Cannot decode a code stream with different component subsample rates. ././@LongLink0000000000000000000000000000015000000000000011561 Lustar rootrootjai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/jpeg2000/J2KRenderedImage.javajai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/jpeg2000/J2KRenderedImage.j0000664000175100017510000001125510506617025032044 0ustar tilletille/* * $RCSfile: J2KRenderedImage.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.2 $ * $Date: 2006-09-28 00:57:57 $ * $State: Exp $ */ package com.sun.media.imageioimpl.plugins.jpeg2000; import java.awt.Point; import java.awt.Rectangle; import java.awt.image.Raster; import java.awt.image.WritableRaster; import java.io.*; import javax.imageio.stream.ImageInputStream; import jj2000.j2k.codestream.reader.*; import com.sun.media.imageioimpl.common.SimpleRenderedImage; public class J2KRenderedImage extends SimpleRenderedImage { private Raster currentTile; private Point currentTileGrid; private J2KReadState readState; public J2KRenderedImage(ImageInputStream iis, J2KImageReadParamJava param, J2KMetadata metadata, J2KImageReader reader) throws IOException { this(new J2KReadState(iis, param, metadata, reader)); } public J2KRenderedImage(ImageInputStream iis, J2KImageReadParamJava param, J2KImageReader reader) throws IOException { this(new J2KReadState(iis, param, reader)); } public J2KRenderedImage(J2KReadState readState) { this.readState = readState; HeaderDecoder hd = readState.getHeader(); //determnined by destination Rectangle destinationRegion = readState.getDestinationRegion(); width = destinationRegion.width; height = destinationRegion.height; minX = destinationRegion.x; minY = destinationRegion.y; Rectangle tile0Rect = readState.getTile0Rect(); tileWidth = tile0Rect.width; tileHeight = tile0Rect.height; tileGridXOffset = tile0Rect.x; tileGridYOffset = tile0Rect.y; sampleModel = readState.getSampleModel(); colorModel = readState.getColorModel(); } public synchronized Raster getTile(int tileX, int tileY) { if (currentTile != null && currentTileGrid.x == tileX && currentTileGrid.y == tileY) return currentTile; if (tileX >= getNumXTiles() || tileY >= getNumYTiles()) throw new IllegalArgumentException(I18N.getString("J2KReadState1")); try { int x = tileXToX(tileX); int y = tileYToY(tileY); currentTile = Raster.createWritableRaster(sampleModel, new Point(x, y)); currentTile = readState.getTile(tileX, tileY, (WritableRaster)currentTile); } catch (IOException e) { throw new RuntimeException(e); } if (currentTileGrid == null) currentTileGrid = new Point(tileX, tileY); else { currentTileGrid.x = tileX; currentTileGrid.y = tileY; } return currentTile; } } jai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/jpeg2000/FileTypeBox.java0000664000175100017510000001424510203036165031720 0ustar tilletille/* * $RCSfile: FileTypeBox.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.1 $ * $Date: 2005-02-11 05:01:32 $ * $State: Exp $ */ package com.sun.media.imageioimpl.plugins.jpeg2000; import javax.imageio.metadata.IIOInvalidTreeException; import javax.imageio.metadata.IIOMetadataNode; import org.w3c.dom.Node; import org.w3c.dom.NodeList; /** This class is defined to represent a File Type Box of JPEG JP2 file * format. A File Type Box has a length, and a fixed type of "ftyp". * * The content of a file type box contains the brand ("jp2 " for JP2 file", * the minor version (0 for JP2 file format), and a compatibility list (one of * which should be "jp2 " if brand is not "jp2 ".) */ public class FileTypeBox extends Box { /** Cache the element names for this box's xml definition */ private static String[] elementNames = {"Brand", "MinorVersion", "CompatibilityList"}; /** This method will be called by the getNativeNodeForSimpleBox of the * class Box to get the element names. */ public static String[] getElementNames() { return elementNames; } /** The element values. */ private int brand; private int minorVersion; private int[] compatibility; /** Constructs a FileTypeBox from the provided brand, minor * version and compatibility list. */ public FileTypeBox(int br, int minorVersion, int[] comp) { super(16 + (comp == null ? 0 : (comp.length << 2)), 0x66747970, null); this.brand = br; this.minorVersion = minorVersion; this.compatibility = comp; } /** Constructs a FileTypeBox from the provided byte array. */ public FileTypeBox(byte[] data) { super(8 + data.length, 0x66747970, data); } /** Constructs a FileTypeBox from * org.w3c.dom.Node. */ public FileTypeBox(Node node) throws IIOInvalidTreeException { super(node); NodeList children = node.getChildNodes(); for (int i = 0; i < children.getLength(); i++) { Node child = children.item(i); String name = child.getNodeName(); if ("Brand".equals(name)) { brand = Box.getIntElementValue(child); } if ("MinorVersion".equals(name)) { minorVersion = Box.getIntElementValue(child); } if ("CompatibilityList".equals(name)) { compatibility = Box.getIntArrayElementValue(child); } } } /** Returns the brand of this file type box. */ public int getBrand() { return brand; } /** Returns the minor version of this file type box. */ public int getMinorVersion() { return minorVersion; } /** Returns the compatibilty list of this file type box. */ public int[] getCompatibilityList() { return compatibility; } /** Creates an IIOMetadataNode from this file type box. * The format of this node is defined in the XML dtd and xsd * for the JP2 image file. */ public IIOMetadataNode getNativeNode() { return getNativeNodeForSimpleBox(); } protected void parse(byte[] data) { if (data == null) return; brand = ((data[0] & 0xFF) << 24) | ((data[1] & 0xFF) << 16) | ((data[2] & 0xFF) << 8) | (data[3] & 0xFF); minorVersion = ((data[4] & 0xFF) << 24) | ((data[5] & 0xFF) << 16) | ((data[6] & 0xFF) << 8) | (data[7] & 0xFF); int len = (data.length - 8) / 4; if (len > 0) { compatibility = new int[len]; for (int i = 0, j = 8; i < len; i++, j += 4) compatibility[i] = ((data[j] & 0xFF) << 24) | ((data[j+1] & 0xFF) << 16) | ((data[j+2] & 0xFF) << 8) | (data[j+3] & 0xFF); } } protected void compose() { if (data != null) return; data = new byte[8 + (compatibility != null ? (compatibility.length << 2) : 0)]; copyInt(data, 0, brand); copyInt(data, 4, minorVersion); if (compatibility != null) for (int i = 0, j = 8; i < compatibility.length; i++, j += 4) copyInt(data, j, compatibility[i]); } } jai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/jpeg2000/J2KReadState.java0000664000175100017510000012162010510572336031713 0ustar tilletille/* * $RCSfile: J2KReadState.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.8 $ * $Date: 2006-10-03 23:40:14 $ * $State: Exp $ */ package com.sun.media.imageioimpl.plugins.jpeg2000; import javax.imageio.IIOException; import javax.imageio.ImageReader; import javax.imageio.ImageReadParam; import javax.imageio.ImageTypeSpecifier; import javax.imageio.metadata.IIOMetadata; import javax.imageio.spi.ImageReaderSpi; import javax.imageio.stream.ImageInputStream; import java.awt.Point; import java.awt.Rectangle; import java.awt.Transparency; import java.awt.color.ColorSpace; import java.awt.image.BufferedImage; import java.awt.image.DataBuffer; import java.awt.image.DataBufferByte; import java.awt.image.ColorModel; import java.awt.image.ComponentColorModel; import java.awt.image.ComponentSampleModel; import java.awt.image.DirectColorModel; import java.awt.image.IndexColorModel; import java.awt.image.MultiPixelPackedSampleModel; import java.awt.image.PixelInterleavedSampleModel; import java.awt.image.Raster; import java.awt.image.RenderedImage; import java.awt.image.SampleModel; import java.awt.image.SinglePixelPackedSampleModel; import java.awt.image.WritableRaster; import java.io.*; import java.util.ArrayList; import java.util.List; import java.util.Hashtable; import java.util.Iterator; import jj2000.j2k.quantization.dequantizer.*; import jj2000.j2k.wavelet.synthesis.*; import jj2000.j2k.image.invcomptransf.*; import jj2000.j2k.fileformat.reader.*; import jj2000.j2k.codestream.reader.*; import jj2000.j2k.entropy.decoder.*; import jj2000.j2k.codestream.*; import jj2000.j2k.decoder.*; import jj2000.j2k.image.*; import jj2000.j2k.util.*; import jj2000.j2k.roi.*; import jj2000.j2k.io.*; import jj2000.j2k.*; import com.sun.media.imageioimpl.common.ImageUtil; public class J2KReadState { /** The input stream we read from */ private ImageInputStream iis = null; private FileFormatReader ff; private HeaderInfo hi; private HeaderDecoder hd; private RandomAccessIO in; private BitstreamReaderAgent breader; private EntropyDecoder entdec; private ROIDeScaler roids; private Dequantizer deq; private InverseWT invWT; private InvCompTransf ictransf; private ImgDataConverter converter,converter2; private DecoderSpecs decSpec = null; private J2KImageReadParamJava j2krparam = null; private int[] destinationBands = null; private int[] sourceBands = null; private int[] levelShift = null; // level shift for each component private int[] minValues = null; // The min values private int[] maxValues = null; // The max values private int[] fracBits = null; // fractional bits for each component private DataBlkInt[] dataBlocks = null; // data-blocks to request data from src private int[] bandOffsets = null; private int maxDepth = 0; private boolean isSigned = false; private ColorModel colorModel = null; private SampleModel sampleModel = null; private int nComp = 0; private int tileWidth = 0; private int tileHeight = 0; /** Source to destination transform */ private int scaleX, scaleY, xOffset, yOffset; private Rectangle destinationRegion = null; private Point sourceOrigin; /** Tile grid offsets of the source, also used for destination. */ private int tileXOffset, tileYOffset; private int width; private int height; private int[] pixbuf = null; private byte[] bytebuf = null; private int[] channelMap = null; private boolean noTransform = true; /** The resolution level requested. */ private int resolution; /** The subsampling step sizes. */ private int stepX, stepY; /** Tile step sizes. */ private int tileStepX, tileStepY; private J2KMetadata metadata; private BufferedImage destImage; /** Cache the J2KImageReader which creates this object. This * variable is used to monitor the abortion. */ private J2KImageReader reader; /** Constructs J2KReadState. * @param iis The input stream. * @param param The reading parameters. * @param metadata The J2KMetadata to cache the metadata read * from the input stream. * @param reader The J2KImageReader which holds this state. * It is necessary for processing abortion. * @throw IllegalArgumentException If the provided iis, * param or metadata is null. */ public J2KReadState(ImageInputStream iis, J2KImageReadParamJava param, J2KMetadata metadata, J2KImageReader reader) { if (iis == null || param == null || metadata == null) throw new IllegalArgumentException(I18N.getString("J2KReadState0")); this.iis = iis; this.j2krparam = param; this.metadata = metadata; this.reader = reader; initializeRead(0, param, metadata); } /** Constructs J2KReadState. * @param iis The input stream. * @param param The reading parameters. * @param reader The J2KImageReader which holds this state. * It is necessary for processing abortion. * @throw IllegalArgumentException If the provided iis, * or param is null. */ public J2KReadState(ImageInputStream iis, J2KImageReadParamJava param, J2KImageReader reader) { if (iis == null || param == null) throw new IllegalArgumentException(I18N.getString("J2KReadState0")); this.iis = iis; this.j2krparam = param; this.reader = reader; initializeRead(0, param, null); } public int getWidth() throws IOException { return width; } public int getHeight() throws IOException { return height; } public HeaderDecoder getHeader() { return hd; } public Raster getTile(int tileX, int tileY, WritableRaster raster) throws IOException { Point nT = ictransf.getNumTiles(null); if (noTransform) { if (tileX >= nT.x || tileY >= nT.y) throw new IllegalArgumentException(I18N.getString("J2KImageReader0")); ictransf.setTile(tileX*tileStepX, tileY*tileStepY); // The offset of the active tiles is the same for all components, // since we don't support different component dimensions. int tOffx; int tOffy; int cTileWidth; int cTileHeight; if(raster != null && (this.resolution < hd.getDecoderSpecs().dls.getMin()) || stepX != 1 || stepY != 1) { tOffx = raster.getMinX(); tOffy = raster.getMinY(); cTileWidth = Math.min(raster.getWidth(), ictransf.getTileWidth()); cTileHeight = Math.min(raster.getHeight(), ictransf.getTileHeight()); } else { tOffx = ictransf.getCompULX(0) - (ictransf.getImgULX() + ictransf.getCompSubsX(0) - 1) / ictransf.getCompSubsX(0) + destinationRegion.x; tOffy = ictransf.getCompULY(0)- (ictransf.getImgULY() + ictransf.getCompSubsY(0) - 1) / ictransf.getCompSubsY(0) + destinationRegion.y; cTileWidth = ictransf.getTileWidth(); cTileHeight = ictransf.getTileHeight(); } if (raster == null) raster = Raster.createWritableRaster(sampleModel, new Point(tOffx, tOffy)); int numBands = sampleModel.getNumBands(); if (tOffx + cTileWidth >= destinationRegion.width + destinationRegion.x) cTileWidth = destinationRegion.width + destinationRegion.x - tOffx; if (tOffy + cTileHeight >= destinationRegion.height + destinationRegion.y) cTileHeight = destinationRegion.height + destinationRegion.y - tOffy; //create the line buffer for pixel data if it is not large enough // or null if (pixbuf == null || pixbuf.length < cTileWidth * numBands) pixbuf = new int[cTileWidth * numBands]; boolean prog = false; // Deliver in lines to reduce memory usage for (int l=0; l < cTileHeight;l++) { if (reader.getAbortRequest()) break; // Request line data for (int i = 0; i < numBands; i++) { if (reader.getAbortRequest()) break; DataBlkInt db = dataBlocks[i]; db.ulx = 0; db.uly = l; db.w = cTileWidth; db.h = 1; ictransf.getInternCompData(db, channelMap[sourceBands[i]]); prog = prog || db.progressive; int[] data = db.data; int k1 = db.offset + cTileWidth - 1; int fracBit = fracBits[i]; int lS = levelShift[i]; int min = minValues[i]; int max = maxValues[i]; if (ImageUtil.isBinary(sampleModel)) { // Force min max to 0 and 1. min = 0; max = 1; if (bytebuf == null || bytebuf.length < cTileWidth * numBands) bytebuf = new byte[cTileWidth * numBands]; for (int j = cTileWidth - 1; j >= 0; j--) { int tmp = (data[k1--] >> fracBit) + lS; bytebuf[j] = (byte)((tmp < min) ? min : ((tmp > max) ? max : tmp)); } ImageUtil.setUnpackedBinaryData(bytebuf, raster, new Rectangle(tOffx, tOffy + l, cTileWidth, 1)); } else { for (int j = cTileWidth - 1; j >= 0; j--) { int tmp = (data[k1--] >> fracBit) + lS; pixbuf[j] = (tmp < min) ? min : ((tmp > max) ? max : tmp); } raster.setSamples(tOffx, tOffy + l, cTileWidth, 1, destinationBands[i], pixbuf); } } } } else { readSubsampledRaster(raster); } return raster; } public Rectangle getDestinationRegion() { return destinationRegion; } public BufferedImage readBufferedImage() throws IOException { colorModel = getColorModel(); sampleModel = getSampleModel(); WritableRaster raster = null; BufferedImage image = j2krparam.getDestination(); int x = destinationRegion.x; int y = destinationRegion.y; destinationRegion.setLocation(j2krparam.getDestinationOffset()); if (image == null) { // If the destination type is specified, use the color model of it. ImageTypeSpecifier type = j2krparam.getDestinationType(); if (type != null) colorModel = type.getColorModel(); raster = Raster.createWritableRaster( sampleModel.createCompatibleSampleModel(destinationRegion.x + destinationRegion.width, destinationRegion.y + destinationRegion.height), new Point(0, 0)); image = new BufferedImage(colorModel, raster, colorModel.isAlphaPremultiplied(), new Hashtable()); } else raster = image.getWritableTile(0, 0); destImage = image; readSubsampledRaster(raster); destinationRegion.setLocation(x, y); destImage = null; return image; } public Raster readAsRaster() throws IOException { BufferedImage image = j2krparam.getDestination(); WritableRaster raster = null; if (image == null) { raster = Raster.createWritableRaster( sampleModel.createCompatibleSampleModel(destinationRegion.x + destinationRegion.width, destinationRegion.y + destinationRegion.height), new Point(0, 0)); } else raster = image.getWritableTile(0, 0); readSubsampledRaster(raster); return raster; } private void initializeRead(int imageIndex, J2KImageReadParamJava param, J2KMetadata metadata) { try { iis.mark(); in = new IISRandomAccessIO(iis); // **** File Format **** // If the codestream is wrapped in the jp2 fileformat, Read the // file format wrapper ff = new FileFormatReader(in, metadata); ff.readFileFormat(); in.seek(ff.getFirstCodeStreamPos()); hi = new HeaderInfo(); try{ hd = new HeaderDecoder(in, j2krparam, hi); } catch(EOFException e){ throw new RuntimeException(I18N.getString("J2KReadState2")); } catch (IOException ioe) { throw new RuntimeException(ioe); } this.width = hd.getImgWidth(); this.height = hd.getImgHeight(); Rectangle sourceRegion = param.getSourceRegion(); sourceOrigin = new Point(); sourceRegion = new Rectangle(hd.getImgULX(), hd.getImgULY(), this.width, this.height); // if the subsample rate for components are not consistent boolean compConsistent = true; stepX = hd.getCompSubsX(0); stepY = hd.getCompSubsY(0); for (int i = 1; i < nComp; i++) { if (stepX != hd.getCompSubsX(i) || stepY != hd.getCompSubsY(i)) throw new RuntimeException(I18N.getString("J2KReadState12")); } // Get minimum number of resolution levels available across // all tile-components. int minResLevels = hd.getDecoderSpecs().dls.getMin(); // Set current resolution level. this.resolution = param != null ? param.getResolution() : minResLevels; if(resolution < 0 || resolution > minResLevels) { resolution = minResLevels; } // Convert source region to lower resolution level. if(resolution != minResLevels || stepX != 1 || stepY != 1) { sourceRegion = J2KImageReader.getReducedRect(sourceRegion, minResLevels, resolution, stepX, stepY); } destinationRegion = (Rectangle)sourceRegion.clone(); J2KImageReader.computeRegionsWrapper(param, false, this.width, this.height, param.getDestination(), sourceRegion, destinationRegion); sourceOrigin = new Point(sourceRegion.x, sourceRegion.y); scaleX = param.getSourceXSubsampling(); scaleY = param.getSourceYSubsampling(); xOffset = param.getSubsamplingXOffset(); yOffset = param.getSubsamplingYOffset(); this.width = destinationRegion.width; this.height = destinationRegion.height; Point tileOffset = hd.getTilingOrigin(null); this.tileWidth = hd.getNomTileWidth(); this.tileHeight = hd.getNomTileHeight(); // Convert tile 0 to lower resolution level. if(resolution != minResLevels || stepX != 1 || stepY != 1) { Rectangle tileRect = new Rectangle(tileOffset); tileRect.width = tileWidth; tileRect.height = tileHeight; tileRect = J2KImageReader.getReducedRect(tileRect, minResLevels, resolution, stepX, stepY); tileOffset = tileRect.getLocation(); tileWidth = tileRect.width; tileHeight = tileRect.height; } tileXOffset = tileOffset.x; tileYOffset = tileOffset.y; // Set the tile step sizes. These values are used because it // is possible that tiles will be empty. In particular at lower // resolution levels when subsampling is used this may be the // case. This method of calculation will work at least for // Profile-0 images. if(tileWidth*(1 << (minResLevels - resolution))*stepX > hd.getNomTileWidth()) { tileStepX = (tileWidth*(1 << (minResLevels - resolution))*stepX + hd.getNomTileWidth() - 1)/hd.getNomTileWidth(); } else { tileStepX = 1; } if(tileHeight*(1 << (minResLevels - resolution))*stepY > hd.getNomTileHeight()) { tileStepY = (tileHeight*(1 << (minResLevels - resolution))*stepY + hd.getNomTileHeight() - 1)/hd.getNomTileHeight(); } else { tileStepY = 1; } if (!destinationRegion.equals(sourceRegion)) noTransform = false; // **** Header decoder **** // Instantiate header decoder and read main header decSpec = hd.getDecoderSpecs(); // **** Instantiate decoding chain **** // Get demixed bitdepths nComp = hd.getNumComps(); int[] depth = new int[nComp]; for (int i=0; i maxDepth) maxDepth = depth[i]; dataBlocks[i] = new DataBlkInt(); //XXX: may need to change if ChannelDefinition is used to // define the color channels, such as BGR order bandOffsets[i] = i; if (hd.isOriginalSigned(sourceBands[i])) isSigned = true; else { levelShift[i] = 1<<(ictransf.getNomRangeBits(sourceBands[i])-1); } // Get the number of bits in the image, and decide what the max // value should be, depending on whether it is signed or not int nomRangeBits = ictransf.getNomRangeBits(sourceBands[i]); maxValues[i] = (1 << (isSigned == true ? (nomRangeBits-1) : nomRangeBits)) - 1; minValues[i] = isSigned ? -(maxValues[i]+1) : 0; fracBits[i] = ictransf.getFixedPoint(sourceBands[i]); } iis.reset(); } catch (IllegalArgumentException e){ throw new RuntimeException(e.getMessage(), e); } catch (Error e) { if(e.getMessage()!=null) throw new RuntimeException(e.getMessage(), e); else { throw new RuntimeException(I18N.getString("J2KReadState9"), e); } } catch (RuntimeException e) { if(e.getMessage()!=null) throw new RuntimeException(I18N.getString("J2KReadState10") + " " + e.getMessage(), e); else { throw new RuntimeException(I18N.getString("J2KReadState10"), e); } } catch (Throwable e) { throw new RuntimeException(I18N.getString("J2KReadState10"), e); } } private Raster readSubsampledRaster(WritableRaster raster) throws IOException { if (raster == null) raster = Raster.createWritableRaster( sampleModel.createCompatibleSampleModel(destinationRegion.x + destinationRegion.width, destinationRegion.y + destinationRegion.height), new Point(destinationRegion.x, destinationRegion.y)); int pixbuf[] = null; // line buffer for pixel data boolean prog = false; // Flag for progressive data Point nT = ictransf.getNumTiles(null); int numBands = sourceBands.length; Rectangle destRect = raster.getBounds().intersection(destinationRegion); int offx = destinationRegion.x; int offy = destinationRegion.y; int sourceSX = (destRect.x - offx) * scaleX + sourceOrigin.x; int sourceSY = (destRect.y - offy) * scaleY + sourceOrigin.y; int sourceEX = (destRect.width - 1)* scaleX + sourceSX; int sourceEY = (destRect.height - 1) * scaleY + sourceSY; int startXTile = (sourceSX - tileXOffset) / tileWidth; int startYTile = (sourceSY - tileYOffset) / tileHeight; int endXTile = (sourceEX - tileXOffset) / tileWidth; int endYTile = (sourceEY - tileYOffset) / tileHeight; startXTile = clip(startXTile, 0, nT.x - 1); startYTile = clip(startYTile, 0, nT.y - 1); endXTile = clip(endXTile, 0, nT.x - 1); endYTile = clip(endYTile, 0, nT.y - 1); int totalXTiles = endXTile - startXTile + 1; int totalYTiles = endYTile - startYTile + 1; int totalTiles = totalXTiles * totalYTiles; // Start the data delivery to the cached consumers tile by tile for(int y=startYTile; y <= endYTile; y++){ if (reader.getAbortRequest()) break; // Loop on horizontal tiles for(int x=startXTile; x <= endXTile; x++){ if (reader.getAbortRequest()) break; float initialFraction = (x - startXTile + (y - startYTile)*totalXTiles)/totalTiles; ictransf.setTile(x*tileStepX,y*tileStepY); int sx = hd.getCompSubsX(0); int cTileWidth = (ictransf.getTileWidth() + sx - 1)/sx; int sy = hd.getCompSubsY(0); int cTileHeight = (ictransf.getTileHeight() + sy - 1)/sy; // Offsets within the tile. int tx = 0; int ty = 0; // The region for this tile int startX = tileXOffset + x * tileWidth; int startY = tileYOffset + y * tileHeight; // sourceSX is guaranteed to be >= startX if (sourceSX > startX) { if(startX >= hd.getImgULX()) { tx = sourceSX - startX; // Intra-tile offset. cTileWidth -= tx; // Reduce effective width. } startX = sourceSX; // Absolute position. } // sourceSY is guaranteed to be >= startY if (sourceSY > startY) { if(startY >= hd.getImgULY()) { ty = sourceSY - startY; // Intra-tile offset. cTileHeight -= ty; // Reduce effective width. } startY = sourceSY; // Absolute position. } // Decrement dimensions if end position is within tile. if (sourceEX < startX + cTileWidth - 1) { cTileWidth += sourceEX - startX - cTileWidth + 1; } if (sourceEY < startY + cTileHeight - 1) { cTileHeight += sourceEY - startY - cTileHeight + 1; } // The start X in the destination int x1 = (startX + scaleX - 1 - sourceOrigin.x) / scaleX; int x2 = (startX + scaleX -1 + cTileWidth - sourceOrigin.x) / scaleX; int lineLength = x2 - x1; if (pixbuf == null || pixbuf.length < lineLength) pixbuf = new int[lineLength]; // line buffer for pixel data x2 = (x2 - 1) * scaleX + sourceOrigin.x - startX; int y1 = (startY + scaleY -1 - sourceOrigin.y) /scaleY; x1 += offx; y1 += offy; // Deliver in lines to reduce memory usage for (int l = ty, m = y1; l < ty + cTileHeight; l += scaleY, m++) { if (reader.getAbortRequest()) break; // Request line data for (int i = 0; i < numBands; i++) { DataBlkInt db = dataBlocks[i]; db.ulx = tx; db.uly = l; db.w = cTileWidth; db.h = 1; ictransf.getInternCompData(db, channelMap[sourceBands[i]]); prog = prog || db.progressive; int[] data = db.data; int k1 = db.offset + x2; int fracBit = fracBits[i]; int lS = levelShift[i]; int min = minValues[i]; int max = maxValues[i]; if (ImageUtil.isBinary(sampleModel)) { // Force min max to 0 and 1. min = 0; max = 1; if (bytebuf == null || bytebuf.length < cTileWidth * numBands) bytebuf = new byte[cTileWidth * numBands]; for (int j = lineLength - 1; j >= 0; j--, k1-=scaleX) { int tmp = (data[k1] >> fracBit) + lS; bytebuf[j] = (byte)((tmp < min) ? min : ((tmp > max) ? max : tmp)); } ImageUtil.setUnpackedBinaryData(bytebuf, raster, new Rectangle(x1, m, lineLength, 1)); } else { for (int j = lineLength - 1; j >= 0; j--, k1-=scaleX) { int tmp = (data[k1] >> fracBit) + lS; pixbuf[j] = (tmp < min) ? min : ((tmp > max) ? max : tmp); } // Send the line data to the BufferedImage raster.setSamples(x1, m, lineLength, 1, destinationBands[i], pixbuf); } } if (destImage != null) reader.processImageUpdateWrapper(destImage, x1, m, cTileWidth, 1, 1, 1, destinationBands); float fraction = initialFraction + (l - ty + 1.0F)/cTileHeight/totalTiles; reader.processImageProgressWrapper(100.0f*fraction); } } // End loop on horizontal tiles } // End loop on vertical tiles return raster; } public ImageTypeSpecifier getImageType() throws IOException { getSampleModel(); getColorModel(); return new ImageTypeSpecifier(colorModel, sampleModel); } public SampleModel getSampleModel() { if (sampleModel != null) return sampleModel; if (nComp == 1 && (maxDepth == 1 || maxDepth == 2 || maxDepth == 4)) sampleModel = new MultiPixelPackedSampleModel(DataBuffer.TYPE_BYTE, tileWidth, tileHeight, maxDepth); else if (maxDepth <= 8) sampleModel = new PixelInterleavedSampleModel(DataBuffer.TYPE_BYTE, tileWidth, tileHeight, nComp, tileWidth * nComp, bandOffsets); else if (maxDepth <=16) sampleModel = new PixelInterleavedSampleModel(isSigned ? DataBuffer.TYPE_SHORT : DataBuffer.TYPE_USHORT, tileWidth, tileHeight, nComp, tileWidth * nComp, bandOffsets); else if (maxDepth <= 32) sampleModel = new PixelInterleavedSampleModel(DataBuffer.TYPE_INT, tileWidth, tileHeight, nComp, tileWidth * nComp, bandOffsets); else throw new IllegalArgumentException(I18N.getString("J2KReadState11") + " " + + maxDepth); return sampleModel; } public ColorModel getColorModel() { if (colorModel != null) return colorModel; // Attempt to get the ColorModel from the JP2 boxes. colorModel = ff.getColorModel(); if (colorModel != null) return colorModel; if(hi.siz.csiz <= 4) { // XXX: Code essentially duplicated from FileFormatReader.getColorModel(). // Create the ColorModel from the SIZ marker segment parameters. ColorSpace cs; if(hi.siz.csiz > 2) { cs = ColorSpace.getInstance(ColorSpace.CS_sRGB); } else { cs = ColorSpace.getInstance(ColorSpace.CS_GRAY); } int[] bitsPerComponent = new int[hi.siz.csiz]; boolean isSigned = false; int maxBitDepth = -1; for(int i = 0; i < hi.siz.csiz; i++) { bitsPerComponent[i] = hi.siz.getOrigBitDepth(i); if(maxBitDepth < bitsPerComponent[i]) { maxBitDepth = bitsPerComponent[i]; } isSigned |= hi.siz.isOrigSigned(i); } boolean hasAlpha = hi.siz.csiz % 2 == 0; int type = -1; if (maxBitDepth <= 8) { type = DataBuffer.TYPE_BYTE; } else if (maxBitDepth <= 16) { type = isSigned ? DataBuffer.TYPE_SHORT : DataBuffer.TYPE_USHORT; } else if (maxBitDepth <= 32) { type = DataBuffer.TYPE_INT; } if (type != -1) { if(hi.siz.csiz == 1 && (maxBitDepth == 1 || maxBitDepth == 2 || maxBitDepth == 4)) { colorModel = ImageUtil.createColorModel(getSampleModel()); } else { colorModel = new ComponentColorModel(cs, bitsPerComponent, hasAlpha, false, hasAlpha ? Transparency.TRANSLUCENT : Transparency.OPAQUE , type); } return colorModel; } } if(sampleModel == null) { sampleModel = getSampleModel(); } if (sampleModel == null) return null; return ImageUtil.createColorModel(null, sampleModel); } /** * Returns the bounding rectangle of the upper left tile at * the current resolution level. */ Rectangle getTile0Rect() { return new Rectangle(tileXOffset, tileYOffset, tileWidth, tileHeight); } private int clip(int value, int min, int max) { if (value < min) value = min; if (value > max) value = max; return value; } private void clipDestination(Rectangle dest) { Point offset = j2krparam.getDestinationOffset(); if (dest.x < offset.x) { dest.width += dest.x - offset.x; dest.x = offset.x ; } if (dest.y < offset.y) { dest.height += dest.y - offset.y; dest.y = offset.y ; } } } ././@LongLink0000000000000000000000000000015500000000000011566 Lustar rootrootjai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/jpeg2000/J2KImageReadParamJava.javajai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/jpeg2000/J2KImageReadParamJ0000664000175100017510000001453110203036165032024 0ustar tilletille/* * $RCSfile: J2KImageReadParamJava.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.1 $ * $Date: 2005-02-11 05:01:33 $ * $State: Exp $ */ package com.sun.media.imageioimpl.plugins.jpeg2000; import javax.imageio.ImageReadParam; import com.sun.media.imageio.plugins.jpeg2000.J2KImageReadParam; /** * A subclass of ImageReadParam for reading images in * the JPEG 2000 format. * *

The decoding parameters for JPEG 2000 are listed below: * *

* * * * * * * * * * * * * * * * * * *
JPEG 2000 Plugin Decoding Parameters
Parameter Name Description
decodingRateSpecifies the decoding rate in bits per pixel (bpp) where the * number of pixels is related to the image's original size (Note: * this parameter is not affected by resolution). The * codestream is either parsed (default) or truncated depending * parsingEnabled. The default is Double.MAX_VALUE. * It means decoding with the encoding rate. *
resolutionSpecifies the resolution level wanted for the decoded image * (0 means the lowest available resolution, the resolution * level gives an image with the original dimension). If the given index * is greater than the number of available resolution levels of the * compressed image, the decoded image has the lowest available * resolution (among all tile-components). This parameter affects only * the inverse wavelet transform and not the number of bytes read by the * codestream parser, which depends only on decodingRate. *
noROIDescalingEnsures that no ROI de-scaling is performed. Decompression is done * like there is no ROI in the image. *
parsingEnabledEnable the parsing mode or not when the decoding rate is specified. * If it is false, the codestream is decoded as if it were truncated to * the given rate. If it is true, the decoder creates, truncates and * decodes a virtual layer progressive codestream with the same * truncation points in each code-block. *
*/ public class J2KImageReadParamJava extends J2KImageReadParam { /** Ensures that no ROI de-scaling is performed. Decompression * is done like there is no ROI in the image. */ private boolean noROIDescaling = true; /** Enable the parsing mode or not when the decoding rate is specified . * If it is false, the codestream is decoded as if it were truncated to * the given rate. If it is true, the decoder creates, truncates and * decodes a virtual layer progressive codestream with the same * truncation points in each code-block. */ private boolean parsingEnabled = true; /** Constructs a default instance of J2KImageReadParamJava. */ public J2KImageReadParamJava() { super(); } public J2KImageReadParamJava(ImageReadParam param) { super(); // Generic settings. if(param.hasController()) { setController(param.getController()); } setSourceRegion(param.getSourceRegion()); setSourceBands(param.getSourceBands()); setDestinationBands(param.getDestinationBands()); setDestination(param.getDestination()); setDestinationOffset(param.getDestinationOffset()); setSourceSubsampling(param.getSourceXSubsampling(), param.getSourceYSubsampling(), param.getSubsamplingXOffset(), param.getSubsamplingYOffset()); setDestinationType(param.getDestinationType()); // J2K settings. J2KImageReadParam j2kParam; if(param instanceof J2KImageReadParam) { j2kParam = (J2KImageReadParam)param; } else { j2kParam = new J2KImageReadParam(); } setDecodingRate(j2kParam.getDecodingRate()); setResolution(j2kParam.getResolution()); } /** Sets noROIDescaling */ public void setNoROIDescaling(boolean value) { this.noROIDescaling = value; } /** Gets noROIDescaling */ public boolean getNoROIDescaling() { return noROIDescaling; } /** Sets parsingEnabled */ public void setParsingEnabled(boolean value) { this.parsingEnabled = value; } /** Gets parsingEnabled */ public boolean getParsingEnabled() { return parsingEnabled; } } ././@LongLink0000000000000000000000000000014600000000000011566 Lustar rootrootjai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/jpeg2000/J2KImageReader.javajai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/jpeg2000/J2KImageReader.jav0000664000175100017510000005074710511055416032052 0ustar tilletille/* * $RCSfile: J2KImageReader.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.7 $ * $Date: 2006-10-05 01:08:30 $ * $State: Exp $ */ package com.sun.media.imageioimpl.plugins.jpeg2000; import java.awt.Rectangle; import java.awt.Point; import javax.imageio.IIOException; import javax.imageio.ImageReader; import javax.imageio.ImageReadParam; import javax.imageio.ImageTypeSpecifier; import javax.imageio.metadata.IIOMetadata; import javax.imageio.spi.ImageReaderSpi; import javax.imageio.stream.ImageInputStream; import com.sun.media.imageio.plugins.jpeg2000.J2KImageReadParam; import java.awt.image.BufferedImage; import java.awt.image.Raster; import java.awt.image.RenderedImage; import java.io.*; import java.util.List; import java.util.Iterator; import java.util.ArrayList; import jj2000.j2k.quantization.dequantizer.*; import jj2000.j2k.wavelet.synthesis.*; import jj2000.j2k.image.invcomptransf.*; import jj2000.j2k.fileformat.reader.*; import jj2000.j2k.codestream.reader.*; import jj2000.j2k.entropy.decoder.*; import jj2000.j2k.codestream.*; import jj2000.j2k.decoder.*; import jj2000.j2k.image.*; import jj2000.j2k.util.*; import jj2000.j2k.roi.*; import jj2000.j2k.io.*; import jj2000.j2k.*; /** This class is the Java Image IO plugin reader for JPEG 2000 JP2 image file * format. It has the capability to load the compressed bilevel images, * color-indexed byte images, or multi-band images in byte/ushort/short/int * data type. It may subsample the image, select bands, clip the image, * and shift the decoded image origin if the proper decoding parameter * are set in the provided J2KImageReadParam. */ public class J2KImageReader extends ImageReader implements MsgLogger { /** The input stream where reads from */ private ImageInputStream iis = null; /** Stream position when setInput() was called. */ private long streamPosition0; /** Indicates whether the header is read. */ private boolean gotHeader = false; /** The image width. */ private int width; /** The image height. */ private int height; /** Image metadata, valid for the imageMetadataIndex only. */ private J2KMetadata imageMetadata = null; /** The image index for the cached metadata. */ private int imageMetadataIndex = -1; /** The J2K HeaderDecoder defined in jj2000 packages. Used to extract image * header information. */ private HeaderDecoder hd; /** The J2KReadState for this reading session based on the current input * and J2KImageReadParam. */ private J2KReadState readState = null; /** * Whether to log JJ2000 messages. */ private boolean logJJ2000Msg = false; /** Wrapper for the protected method computeRegions. So it * can be access from the classes which are not in ImageReader * hierarchy. */ public static void computeRegionsWrapper(ImageReadParam param, boolean allowZeroDestOffset, int srcWidth, int srcHeight, BufferedImage image, Rectangle srcRegion, Rectangle destRegion) { if (srcRegion == null) { throw new IllegalArgumentException(I18N.getString("J2KImageReader0")); } if (destRegion == null) { throw new IllegalArgumentException(I18N.getString("J2KImageReader1")); } // Clip that to the param region, if there is one int periodX = 1; int periodY = 1; int gridX = 0; int gridY = 0; if (param != null) { Rectangle paramSrcRegion = param.getSourceRegion(); if (paramSrcRegion != null) { srcRegion.setBounds(srcRegion.intersection(paramSrcRegion)); } periodX = param.getSourceXSubsampling(); periodY = param.getSourceYSubsampling(); gridX = param.getSubsamplingXOffset(); gridY = param.getSubsamplingYOffset(); srcRegion.translate(gridX, gridY); srcRegion.width -= gridX; srcRegion.height -= gridY; if(allowZeroDestOffset) { destRegion.setLocation(param.getDestinationOffset()); } else { Point destOffset = param.getDestinationOffset(); if(destOffset.x != 0 || destOffset.y != 0) { destRegion.setLocation(param.getDestinationOffset()); } } } // Now clip any negative destination offsets, i.e. clip // to the top and left of the destination image if (destRegion.x < 0) { int delta = -destRegion.x*periodX; srcRegion.x += delta; srcRegion.width -= delta; destRegion.x = 0; } if (destRegion.y < 0) { int delta = -destRegion.y*periodY; srcRegion.y += delta; srcRegion.height -= delta; destRegion.y = 0; } // Now clip the destination Region to the subsampled width and height int subsampledWidth = (srcRegion.width + periodX - 1)/periodX; int subsampledHeight = (srcRegion.height + periodY - 1)/periodY; destRegion.width = subsampledWidth; destRegion.height = subsampledHeight; // Now clip that to right and bottom of the destination image, // if there is one, taking subsampling into account if (image != null) { Rectangle destImageRect = new Rectangle(0, 0, image.getWidth(), image.getHeight()); destRegion.setBounds(destRegion.intersection(destImageRect)); if (destRegion.isEmpty()) { throw new IllegalArgumentException (I18N.getString("J2KImageReader2")); } int deltaX = destRegion.x + subsampledWidth - image.getWidth(); if (deltaX > 0) { srcRegion.width -= deltaX*periodX; } int deltaY = destRegion.y + subsampledHeight - image.getHeight(); if (deltaY > 0) { srcRegion.height -= deltaY*periodY; } } if (srcRegion.isEmpty() || destRegion.isEmpty()) { throw new IllegalArgumentException(I18N.getString("J2KImageReader3")); } } /** Wrapper for the protected method checkReadParamBandSettings. * So it can be access from the classes which are not in * ImageReader hierarchy. */ public static void checkReadParamBandSettingsWrapper(ImageReadParam param, int numSrcBands, int numDstBands) { checkReadParamBandSettings(param, numSrcBands, numDstBands); } /** * Convert a rectangle provided in the coordinate system of the JPEG2000 * reference grid to coordinates at a lower resolution level where zero * denotes the lowest resolution level. * * @param r A rectangle in references grid coordinates. * @param maxLevel The highest resolution level in the image. * @param level The resolution level of the returned rectangle. * @param subX The horizontal subsampling step size. * @param subY The vertical subsampling step size. * @return The parameter rectangle converted to a lower resolution level. * @throws IllegalArgumentException if r
is null, * maxLevel or level is negative, or * level is greater than maxLevel. */ static Rectangle getReducedRect(Rectangle r, int maxLevel, int level, int subX, int subY) { if(r == null) { throw new IllegalArgumentException("r == null!"); } else if(maxLevel < 0 || level < 0) { throw new IllegalArgumentException("maxLevel < 0 || level < 0!"); } else if(level > maxLevel) { throw new IllegalArgumentException("level > maxLevel"); } // At the highest level; return the parameter. if(level == maxLevel && subX == 1 && subY == 1) { return r; } // Resolution divisor is step*2^(maxLevel - level). int divisor = 1 << (maxLevel - level); int divX = divisor*subX; int divY = divisor*subY; // Convert upper left and lower right corners. int x1 = (r.x + divX - 1)/divX; int x2 = (r.x + r.width + divX - 1)/divX; int y1 = (r.y + divY - 1)/divY; int y2 = (r.y + r.height + divY - 1)/divY; // Create lower resolution rectangle and return. return new Rectangle(x1, y1, x2 - x1, y2 - y1); } /** Wrapper for the protected method processImageUpdate * So it can be access from the classes which are not in * ImageReader hierarchy. */ public void processImageUpdateWrapper(BufferedImage theImage, int minX, int minY, int width, int height, int periodX, int periodY, int[] bands) { processImageUpdate(theImage, minX, minY, width, height, periodX, periodY, bands); } /** Wrapper for the protected method processImageProgress * So it can be access from the classes which are not in * ImageReader hierarchy. */ public void processImageProgressWrapper(float percentageDone) { processImageProgress(percentageDone); } /** Constructs J2KImageReader from the provided * ImageReaderSpi. */ public J2KImageReader(ImageReaderSpi originator) { super(originator); this.logJJ2000Msg = Boolean.getBoolean("jj2000.j2k.decoder.log"); FacilityManager.registerMsgLogger(null, this); } /** Overrides the method defined in the superclass. */ public void setInput(Object input, boolean seekForwardOnly, boolean ignoreMetadata) { super.setInput(input, seekForwardOnly, ignoreMetadata); this.ignoreMetadata = ignoreMetadata; iis = (ImageInputStream) input; // Always works imageMetadata = null; try { this.streamPosition0 = iis.getStreamPosition(); } catch(IOException e) { // XXX ignore } } /** Overrides the method defined in the superclass. */ public int getNumImages(boolean allowSearch) throws IOException { return 1; } public int getWidth(int imageIndex) throws IOException { checkIndex(imageIndex); readHeader(); return width; } public int getHeight(int imageIndex) throws IOException { checkIndex(imageIndex); readHeader(); return height; } public int getTileGridXOffset(int imageIndex) throws IOException { checkIndex(imageIndex); readHeader(); return hd.getTilingOrigin(null).x; } public int getTileGridYOffset(int imageIndex) throws IOException { checkIndex(imageIndex); readHeader(); return hd.getTilingOrigin(null).y; } public int getTileWidth(int imageIndex) throws IOException { checkIndex(imageIndex); readHeader(); return hd.getNomTileWidth(); } public int getTileHeight(int imageIndex) throws IOException { checkIndex(imageIndex); readHeader(); return hd.getNomTileHeight(); } private void checkIndex(int imageIndex) { if (imageIndex != 0) { throw new IndexOutOfBoundsException(I18N.getString("J2KImageReader4")); } } public void readHeader() { if (gotHeader) return; if (readState == null) { try { iis.seek(streamPosition0); } catch(IOException e) { // XXX ignore } readState = new J2KReadState(iis, new J2KImageReadParamJava(getDefaultReadParam()), this); } hd = readState.getHeader(); gotHeader = true; this.width = hd.getImgWidth(); this.height = hd.getImgHeight(); } public Iterator getImageTypes(int imageIndex) throws IOException { checkIndex(imageIndex); readHeader(); if (readState != null) { ArrayList list = new ArrayList(); list.add(new ImageTypeSpecifier(readState.getColorModel(), readState.getSampleModel())); return list.iterator(); } return null; } public ImageReadParam getDefaultReadParam() { return new J2KImageReadParam(); } public IIOMetadata getImageMetadata(int imageIndex) throws IOException { checkIndex(imageIndex); if (ignoreMetadata) return null; if (imageMetadata == null) { iis.mark(); imageMetadata = new J2KMetadata(iis, this); iis.reset(); } return imageMetadata; } public IIOMetadata getStreamMetadata() throws IOException { return null; } public BufferedImage read(int imageIndex, ImageReadParam param) throws IOException { checkIndex(imageIndex); clearAbortRequest(); processImageStarted(imageIndex); if (param == null) param = getDefaultReadParam(); param = new J2KImageReadParamJava(param); if (!ignoreMetadata) { imageMetadata = new J2KMetadata(); iis.seek(streamPosition0); readState = new J2KReadState(iis, (J2KImageReadParamJava)param, imageMetadata, this); } else { iis.seek(streamPosition0); readState = new J2KReadState(iis, (J2KImageReadParamJava)param, this); } BufferedImage bi = readState.readBufferedImage(); if (abortRequested()) processReadAborted(); else processImageComplete(); return bi; } public RenderedImage readAsRenderedImage(int imageIndex, ImageReadParam param) throws IOException { checkIndex(imageIndex); RenderedImage ri = null; clearAbortRequest(); processImageStarted(imageIndex); if (param == null) param = getDefaultReadParam(); param = new J2KImageReadParamJava(param); if (!ignoreMetadata) { if (imageMetadata == null) imageMetadata = new J2KMetadata(); ri = new J2KRenderedImage(iis, (J2KImageReadParamJava)param, imageMetadata, this); } else ri = new J2KRenderedImage(iis, (J2KImageReadParamJava)param, this); if (abortRequested()) processReadAborted(); else processImageComplete(); return ri; } public boolean canReadRaster() { return true; } public boolean isRandomAccessEasy(int imageIndex) throws IOException { checkIndex(imageIndex); return false; } public Raster readRaster(int imageIndex, ImageReadParam param) throws IOException { checkIndex(imageIndex); processImageStarted(imageIndex); param = new J2KImageReadParamJava(param); if (!ignoreMetadata) { imageMetadata = new J2KMetadata(); iis.seek(streamPosition0); readState = new J2KReadState(iis, (J2KImageReadParamJava)param, imageMetadata, this); } else { iis.seek(streamPosition0); readState = new J2KReadState(iis, (J2KImageReadParamJava)param, this); } Raster ras = readState.readAsRaster(); if (abortRequested()) processReadAborted(); else processImageComplete(); return ras; } public boolean isImageTiled(int imageIndex) { checkIndex(imageIndex); readHeader(); if (readState != null) { RenderedImage image = new J2KRenderedImage(readState); if (image.getNumXTiles() * image.getNumYTiles() > 0) return true; return false; } return false; } public void reset() { // reset local Java structures super.reset(); iis = null; gotHeader = false; imageMetadata = null; readState = null; System.gc(); } /** This method wraps the protected method abortRequested * to allow the abortions be monitored by J2KReadState. */ public boolean getAbortRequest() { return abortRequested(); } private ImageTypeSpecifier getImageType(int imageIndex) throws IOException { checkIndex(imageIndex); readHeader(); if (readState != null) { return new ImageTypeSpecifier(readState.getColorModel(), readState.getSampleModel()); } return null; } // --- Begin jj2000.j2k.util.MsgLogger implementation --- public void flush() { // Do nothing. } public void println(String str, int flind, int ind) { printmsg(INFO, str); } public void printmsg(int sev, String msg) { if(logJJ2000Msg) { String msgSev; switch(sev) { case ERROR: msgSev = "ERROR"; break; case INFO: msgSev = "INFO"; break; case LOG: msgSev = "LOG"; break; case WARNING: default: msgSev = "WARNING"; break; } processWarningOccurred("[JJ2000 "+msgSev+"] "+msg); } } // --- End jj2000.j2k.util.MsgLogger implementation --- } ././@LongLink0000000000000000000000000000015100000000000011562 Lustar rootrootjai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/jpeg2000/J2KImageReaderSpi.javajai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/jpeg2000/J2KImageReaderSpi.0000664000175100017510000001305210413303155032006 0ustar tilletille/* * $RCSfile: J2KImageReaderSpi.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.2 $ * $Date: 2006-03-31 19:43:39 $ * $State: Exp $ */ package com.sun.media.imageioimpl.plugins.jpeg2000; import java.util.Locale; import javax.imageio.spi.ImageReaderSpi; import javax.imageio.stream.ImageInputStream; import javax.imageio.spi.IIORegistry; import javax.imageio.spi.ServiceRegistry; import java.io.IOException; import javax.imageio.ImageReader; import javax.imageio.IIOException; import com.sun.media.imageioimpl.common.PackageUtil; import com.sun.medialib.codec.jiio.Util; public class J2KImageReaderSpi extends ImageReaderSpi { private static String [] writerSpiNames = {"com.sun.media.imageioimpl.plugins.jpeg2000.J2KImageWriterSpi"}; private static String[] formatNames = {"jpeg 2000", "JPEG 2000", "jpeg2000", "JPEG2000"}; private static String[] extensions = {"jp2"}; // Should add jpx or jpm private static String[] mimeTypes = {"image/jp2", "image/jpeg2000"}; private boolean registered = false; public J2KImageReaderSpi() { super(PackageUtil.getVendor(), PackageUtil.getVersion(), formatNames, extensions, mimeTypes, "com.sun.media.imageioimpl.plugins.jpeg2000.J2KImageReader", STANDARD_INPUT_TYPE, writerSpiNames, false, null, null, null, null, true, "com_sun_media_imageio_plugins_jpeg2000_image_1.0", "com.sun.media.imageioimpl.plugins.jpeg2000.J2KMetadataFormat", null, null); } public void onRegistration(ServiceRegistry registry, Class category) { if (registered) { return; } registered = true; // Set pairwise ordering to give codecLib reader precedence. Class codecLibReaderSPIClass = null; try { codecLibReaderSPIClass = Class.forName("com.sun.media.imageioimpl.plugins.jpeg2000.J2KImageReaderCodecLibSpi"); } catch(Throwable t) { // Ignore it. } if(codecLibReaderSPIClass != null) { Object codecLibReaderSPI = registry.getServiceProviderByClass(codecLibReaderSPIClass); if(codecLibReaderSPI != null) { registry.setOrdering(category, codecLibReaderSPI, this); } } } public String getDescription(Locale locale) { String desc = PackageUtil.getSpecificationTitle() + " JPEG 2000 Image Reader"; return desc; } public boolean canDecodeInput(Object source) throws IOException { if (!(source instanceof ImageInputStream)) { return false; } ImageInputStream stream = (ImageInputStream)source; //fix of 4938421 stream.mark(); int marker = (stream.read() << 8) | stream.read(); if (marker == 0xFF4F) { stream.reset(); return true; } stream.reset(); stream.mark(); byte[] b = new byte[12]; stream.readFully(b); stream.reset(); //Verify the signature box // The length of the signature box is 12 if (b[0] !=0 || b[1]!=0 || b[2] != 0 || b[3] != 12) return false; // The signature box type is "jP " if ((b[4] & 0xff) != 0x6A || (b[5] & 0xFF) != 0x50 || (b[6] & 0xFF) !=0x20 || (b[7] & 0xFF) != 0x20) return false; // The signture content is 0x0D0A870A if ((b[8] & 0xFF) != 0x0D || (b[9] & 0xFF) != 0x0A || (b[10] & 0xFF) != 0x87 || (b[11] &0xFF) != 0x0A) return false; return true; } public ImageReader createReaderInstance(Object extension) throws IIOException { return new J2KImageReader(this); } } jai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/jpeg2000/J2KMetadata.java0000664000175100017510000011334610505066255031567 0ustar tilletille/* * $RCSfile: J2KMetadata.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.4 $ * $Date: 2006-09-22 23:07:25 $ * $State: Exp $ */ package com.sun.media.imageioimpl.plugins.jpeg2000; import java.io.InputStream; import javax.imageio.ImageTypeSpecifier; import javax.imageio.ImageWriteParam; import javax.imageio.ImageWriter; import javax.imageio.IIOException; import javax.imageio.stream.ImageInputStream; import javax.imageio.stream.ImageOutputStream; import javax.imageio.metadata.IIOMetadata; import javax.imageio.metadata.IIOMetadataNode; import javax.imageio.metadata.IIOMetadataFormat; import javax.imageio.metadata.IIOMetadataFormatImpl; import javax.imageio.metadata.IIOInvalidTreeException; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.w3c.dom.NamedNodeMap; import java.util.List; import java.util.ArrayList; import java.util.Arrays; import java.util.Hashtable; import java.util.Iterator; import java.util.ListIterator; import java.io.IOException; import java.awt.color.ICC_Profile; import java.awt.color.ICC_ColorSpace; import java.awt.color.ColorSpace; import java.awt.image.ColorModel; import java.awt.image.DataBuffer; import java.awt.image.IndexColorModel; import java.awt.image.SampleModel; import java.awt.Point; import com.sun.media.imageio.plugins.jpeg2000.J2KImageReadParam; import com.sun.media.imageio.plugins.jpeg2000.J2KImageWriteParam; import jj2000.j2k.fileformat.FileFormatBoxes; import jj2000.j2k.fileformat.reader.FileFormatReader; import jj2000.j2k.io.RandomAccessIO; /** * Metadata for the J2K plug-in. */ public class J2KMetadata extends IIOMetadata implements Cloneable { static final String nativeMetadataFormatName = "com_sun_media_imageio_plugins_jpeg2000_image_1.0"; /** cache the metadata format */ private J2KMetadataFormat format; /** The boxes of JP2 file used as meta data, i. e., all the boxes * except the data stream box */ private ArrayList boxes = new ArrayList(); /** * Constructor containing code shared by other constructors. */ public J2KMetadata() { super(true, // Supports standard format nativeMetadataFormatName, // and a native format "com.sun.media.imageioimpl.plugins.jpeg2000.J2KMetadataFormat", null, null); // No other formats format = (J2KMetadataFormat)getMetadataFormat(nativeMetadataFormatName); } /* * Constructs a J2KMetadata object by reading the * contents of an ImageInputStream. Has package-only * access. * * @param iis An ImageInputStream from which to read * the metadata. * @param reader The J2KImageReader calling this * constructor, to which warnings should be sent. */ public J2KMetadata(ImageInputStream iis, J2KImageReader reader) throws IOException { this(); RandomAccessIO in = new IISRandomAccessIO(iis); iis.mark(); // **** File Format **** // If the codestream is wrapped in the jp2 fileformat, Read the // file format wrapper FileFormatReader ff = new FileFormatReader(in, this); ff.readFileFormat(); iis.reset(); } /** * Constructs a default stream J2KMetadata object appropriate * for the given write parameters. */ public J2KMetadata(ImageWriteParam param, ImageWriter writer) { this(null, param, writer); } /** * Constructs a default image J2KMetadata object appropriate * for the given image type and write parameters. */ public J2KMetadata(ImageTypeSpecifier imageType, ImageWriteParam param, ImageWriter writer) { this(imageType != null ? imageType.getColorModel() : null, imageType != null ? imageType.getSampleModel() : null, 0, 0, param, writer); } /** * Constructs a default image J2KMetadata object appropriate * for the given image type and write parameters. */ public J2KMetadata(ColorModel colorModel, SampleModel sampleModel, int width, int height, ImageWriteParam param, ImageWriter writer) { this(); addNode(new SignatureBox()); addNode(new FileTypeBox(0x6A703220, 0, new int[]{0x6A703220})); ImageTypeSpecifier destType = null; if (param != null) { destType = param.getDestinationType(); if (colorModel == null && sampleModel == null) { colorModel = destType == null ? null : destType.getColorModel(); sampleModel = destType == null ? null : destType.getSampleModel(); } } int[] bitDepths = null; if(colorModel != null) { bitDepths = colorModel.getComponentSize(); } else if(sampleModel != null) { bitDepths = sampleModel.getSampleSize(); } int bitsPerComponent = 0xff; if(bitDepths != null) { bitsPerComponent = bitDepths[0]; int numComponents = bitDepths.length; for(int i = 1; i < numComponents; i++) { /* XXX: This statement should be removed when BPC behavior is corrected as derscribed below. */ if(bitDepths[i] > bitsPerComponent) { bitsPerComponent = bitDepths[i]; } /* XXX: When the number of bits per component is not the same for all components the BPC parameter of the Image Header box should be set to 0xff and the actual number of bits per component written in the Bits Per Component box. if(bitDepths[i] != bitsPerComponent) { bitsPerComponent = 0xff; break; } */ } } if (colorModel != null) { ColorSpace cs = colorModel.getColorSpace(); boolean iccColor = (cs instanceof ICC_ColorSpace); int type = cs.getType(); if (type == ColorSpace.TYPE_RGB) { addNode(new ColorSpecificationBox((byte)1, (byte)0, (byte)0, ColorSpecificationBox.ECS_sRGB, null)); } else if (type == ColorSpace.TYPE_GRAY) addNode(new ColorSpecificationBox((byte)1, (byte)0, (byte)0, ColorSpecificationBox.ECS_GRAY, null)); else if (cs instanceof ICC_ColorSpace) addNode(new ColorSpecificationBox((byte)2, (byte)0, (byte)0, 0, ((ICC_ColorSpace)cs).getProfile())); if (colorModel.hasAlpha()) { addNode(new ChannelDefinitionBox(colorModel)); } if (colorModel instanceof IndexColorModel) { addNode(new PaletteBox((IndexColorModel)colorModel)); int numComp = colorModel.getComponentSize().length; short[] channels = new short[numComp]; byte[] types = new byte[numComp]; byte[] maps = new byte[numComp]; for (int i = 0; i < numComp; i++) { channels[i] = 0; types[i] = 1; maps[i] = (byte)i; } addNode(new ComponentMappingBox(channels, types, maps)); } } if (sampleModel != null) { if (width <= 0) width = sampleModel.getWidth(); if (height <= 0) height = sampleModel.getHeight(); int bpc = bitsPerComponent == 0xff ? 0xff : ((bitsPerComponent - 1) | (isOriginalSigned(sampleModel) ? 0x80 : 0)); addNode(new HeaderBox(height, width, sampleModel.getNumBands(), bpc, 7, colorModel == null ? 1 : 0, getElement("JPEG2000IntellectualPropertyRightsBox")==null ? 0 : 1)); } } public Object clone() { J2KMetadata theClone = null; try { theClone = (J2KMetadata) super.clone(); } catch (CloneNotSupportedException e) {} // won't happen if (boxes != null) { int numBoxes = boxes.size(); for(int i = 0; i < numBoxes; i++) { theClone.addNode((Box)boxes.get(i)); } } return theClone; } public Node getAsTree(String formatName) { if (formatName == null) { throw new IllegalArgumentException(I18N.getString("J2KMetadata0")); } if (formatName.equals(nativeMetadataFormatName)) { return getNativeTree(); } if (formatName.equals (IIOMetadataFormatImpl.standardMetadataFormatName)) { return getStandardTree(); } throw new IllegalArgumentException(I18N.getString("J2KMetadata1") + " " + formatName); } IIOMetadataNode getNativeTree() { IIOMetadataNode root = new IIOMetadataNode(nativeMetadataFormatName); Box signatureBox = null, fileTypeBox = null, headerBox = null; int signatureIndex = -1, fileTypeIndex = -1, headerIndex = -1; int numBoxes = boxes.size(); int found = 0; for(int i = 0; i < numBoxes && found < 3; i++) { Box box = (Box)boxes.get(i); if(Box.getName(box.getType()).equals("JPEG2000SignatureBox")) { signatureBox = box; signatureIndex = i; found++; } else if(Box.getName(box.getType()).equals("JPEG2000FileTypeBox")) { fileTypeBox = box; fileTypeIndex = i; found++; } else if(Box.getName(box.getType()).equals("JPEG2000HeaderBox")) { headerBox = box; headerIndex = i; found++; } } if(signatureBox != null) { insertNodeIntoTree(root, signatureBox.getNativeNode()); } if(fileTypeBox != null) { insertNodeIntoTree(root, fileTypeBox.getNativeNode()); } if(headerBox != null) { insertNodeIntoTree(root, headerBox.getNativeNode()); } for(int i = 0; i < numBoxes; i++) { if(i == signatureIndex || i == fileTypeIndex || i == headerIndex) continue; Box box = (Box)boxes.get(i); IIOMetadataNode node = box.getNativeNode(); insertNodeIntoTree(root, node); } return root; } // Standard tree node methods protected IIOMetadataNode getStandardChromaNode() { HeaderBox header = (HeaderBox)getElement("JPEG2000HeaderBox"); PaletteBox palette = (PaletteBox)getElement("JPEG2000PaletteBox"); ColorSpecificationBox color = (ColorSpecificationBox)getElement("JPEG2000ColorSpecificationBox"); IIOMetadataNode node = new IIOMetadataNode("Chroma"); IIOMetadataNode subNode = null; if (header != null) { if (header.getUnknownColorspace() == 0) { if (color != null && color.getMethod() == 1) { subNode = new IIOMetadataNode("ColorSpaceType"); int ecs = color.getEnumeratedColorSpace(); if (ecs == FileFormatBoxes.CSB_ENUM_SRGB) subNode.setAttribute("name", "RGB"); if (ecs == FileFormatBoxes.CSB_ENUM_GREY) subNode.setAttribute("name", "GRAY"); node.appendChild(subNode); } } subNode = new IIOMetadataNode("NumChannels"); subNode.setAttribute("value", "" + header.getNumComponents()); node.appendChild(subNode); if (palette != null) { subNode.setAttribute("value", "" + palette.getNumComp()); subNode = new IIOMetadataNode("Palette"); byte[][] lut = palette.getLUT(); int size = lut[0].length; int numComp = lut.length; for (int i = 0; i < size; i++) { IIOMetadataNode subNode1 = new IIOMetadataNode("PaletteEntry"); subNode1.setAttribute("index", ""+i); subNode1.setAttribute("red", "" + (lut[0][i]&0xff)); subNode1.setAttribute("green", "" + (lut[1][i]&0xff)); subNode1.setAttribute("blue", "" + (lut[2][i]&0xff)); if (numComp == 4) subNode1.setAttribute("alpha", "" + (lut[3][i]&0xff)); subNode.appendChild(subNode1); } node.appendChild(subNode); } } return node; } protected IIOMetadataNode getStandardCompressionNode() { IIOMetadataNode node = new IIOMetadataNode("Compression"); // CompressionTypeName IIOMetadataNode subNode = new IIOMetadataNode("CompressionTypeName"); subNode.setAttribute("value", "JPEG2000"); node.appendChild(subNode); return node; } protected IIOMetadataNode getStandardDataNode() { IIOMetadataNode node = new IIOMetadataNode("Data"); PaletteBox palette = (PaletteBox)getElement("JPEG2000PaletteBox"); boolean sampleFormat = false; if (palette != null) { IIOMetadataNode subNode = new IIOMetadataNode("SampleFormat"); subNode.setAttribute("value", "Index"); node.appendChild(subNode); sampleFormat = true; } BitsPerComponentBox bitDepth = (BitsPerComponentBox)getElement("JPEG2000BitsPerComponentBox"); String value = ""; boolean signed = false; boolean gotSampleInfo = false; // JPEG 2000 "B" parameter represents "bitDepth - 1" in the // right 7 least significant bits with the most significant // bit indicating signed if set and unsigned if not. if (bitDepth != null) { byte[] bits = bitDepth.getBitDepth(); if ((bits[0] & 0x80) == 0x80) signed = true; int numComp = bits.length; for (int i = 0; i < numComp; i++) { value += (bits[i] & 0x7f) + 1; if(i != numComp - 1) value += " "; } gotSampleInfo = true; } else { HeaderBox header = (HeaderBox)getElement("JPEG2000HeaderBox"); if(header != null) { int bits = header.getBitDepth(); if ((bits & 0x80) == 0x80) signed = true; bits = (bits & 0x7f) + 1; int numComp = header.getNumComponents(); for (int i = 0; i < numComp; i++) { value += bits; if(i != numComp - 1) value += " "; } gotSampleInfo = true; } } IIOMetadataNode subNode = null; if(gotSampleInfo) { subNode = new IIOMetadataNode("BitsPerSample"); subNode.setAttribute("value", value); node.appendChild(subNode); } subNode = new IIOMetadataNode("PlanarConfiguration"); subNode.setAttribute("value", "TileInterleaved"); node.appendChild(subNode); if (!sampleFormat && gotSampleInfo) { subNode = new IIOMetadataNode("SampleFormat"); subNode.setAttribute("value", signed ? "SignedIntegral": "UnsignedIntegral"); node.appendChild(subNode); } return node; } protected IIOMetadataNode getStandardDimensionNode() { ResolutionBox box = (ResolutionBox)getElement("JPEG2000CaptureResolutionBox"); if (box != null) { IIOMetadataNode node = new IIOMetadataNode("Dimension"); float hRes = box.getHorizontalResolution(); float vRes = box.getVerticalResolution(); float ratio = vRes / hRes; IIOMetadataNode subNode = new IIOMetadataNode("PixelAspectRatio"); subNode.setAttribute("value", "" + ratio); node.appendChild(subNode); subNode = new IIOMetadataNode("HorizontalPixelSize"); subNode.setAttribute("value", "" + (1000 / hRes)); node.appendChild(subNode); subNode = new IIOMetadataNode("VerticalPixelSize"); subNode.setAttribute("value", "" + (1000 / vRes)); node.appendChild(subNode); return node; } return null; } protected IIOMetadataNode getStandardTransparencyNode() { ChannelDefinitionBox channel = (ChannelDefinitionBox)getElement("JPEG2000ChannelDefinitionBox"); if (channel != null) { IIOMetadataNode node = new IIOMetadataNode("Transparency"); boolean hasAlpha = false; boolean isPremultiplied = false; short[] type = channel.getTypes(); for (int i = 0; i < type.length; i++) { if (type[i] == 1) hasAlpha = true; if (type[i] == 2) isPremultiplied = true; } String value = "none"; if (isPremultiplied) value = "premultiplied"; else if (hasAlpha) value = "nonpremultiplied"; IIOMetadataNode subNode = new IIOMetadataNode("Alpha"); subNode.setAttribute("value", value); node.appendChild(subNode); return node; } IIOMetadataNode node = new IIOMetadataNode("Transparency"); IIOMetadataNode subNode = new IIOMetadataNode("Alpha"); subNode.setAttribute("value", "none"); node.appendChild(subNode); return null; } protected IIOMetadataNode getStandardTextNode() { if (boxes == null) return null; IIOMetadataNode text = null; Iterator iterator = boxes.iterator(); while(iterator.hasNext()) { Box box = (Box)iterator.next(); if (box instanceof XMLBox) { if (text == null) text = new IIOMetadataNode("Text"); IIOMetadataNode subNode = new IIOMetadataNode("TextEntry"); String content = new String(box.getContent()); subNode.setAttribute("value", content); text.appendChild(subNode); } } return text; } public boolean isReadOnly() { return false; } public void mergeTree(String formatName, Node root) throws IIOInvalidTreeException { if (formatName == null) { throw new IllegalArgumentException(I18N.getString("J2KMetadata0")); } if (root == null) { throw new IllegalArgumentException(I18N.getString("J2KMetadata2")); } if (formatName.equals(nativeMetadataFormatName) && root.getNodeName().equals(nativeMetadataFormatName)) { mergeNativeTree(root); } else if (formatName.equals (IIOMetadataFormatImpl.standardMetadataFormatName)) { mergeStandardTree(root); } else { throw new IllegalArgumentException(I18N.getString("J2KMetadata1") + " " + formatName); } } public void setFromTree(String formatName, Node root) throws IIOInvalidTreeException { if (formatName == null) { throw new IllegalArgumentException(I18N.getString("J2KMetadata0")); } if (root == null) { throw new IllegalArgumentException(I18N.getString("J2KMetadata2")); } if (formatName.equals(nativeMetadataFormatName) && root.getNodeName().equals(nativeMetadataFormatName)) { boxes = new ArrayList(); mergeNativeTree(root); } else if (formatName.equals (IIOMetadataFormatImpl.standardMetadataFormatName)) { boxes = new ArrayList(); mergeStandardTree(root); } else { throw new IllegalArgumentException(I18N.getString("J2KMetadata1") + " " + formatName); } } public void reset() { boxes.clear(); } public void addNode(Box node) { if (boxes == null) boxes = new ArrayList(); replace(Box.getName(node.getType()), node); } public Box getElement(String name) { for (int i = boxes.size() - 1; i >= 0; i--) { Box box = (Box)boxes.get(i); if (name.equals(Box.getName(box.getType()))) return box; } return null; } private void mergeNativeTree(Node root) throws IIOInvalidTreeException { NodeList list = root.getChildNodes(); for (int i = list.getLength() - 1; i >= 0; i--) { Node node = list.item(i); String name = node.getNodeName(); if (format.getParent(name) != null) { if (format.isLeaf(name)) { String s = (String)Box.getAttribute(node, "Type"); Box box = Box.createBox(Box.getTypeInt(s), node); if (format.singleInstance(name)&&getElement(name) != null) { replace(name, box); } else boxes.add(box); } else { mergeNativeTree(node); } } } } private void mergeStandardTree(Node root) throws IIOInvalidTreeException { NodeList children = root.getChildNodes(); int numComps = 0; for (int i = 0; i < children.getLength(); i++) { Node node = children.item(i); String name = node.getNodeName(); if (name.equals("Chroma")) { NodeList children1 = node.getChildNodes(); for (int j = 0; j < children1.getLength(); j++) { Node child = children1.item(j); String name1 = child.getNodeName(); if (name1.equals("NumChannels")) { String s = (String)Box.getAttribute(child, "value"); numComps = new Integer(s).intValue(); } if (name1.equals("ColorSpaceType")) createColorSpecificationBoxFromStandardNode(child); if (name1.equals("Palette")) { createPaletteBoxFromStandardNode(child); } } } else if (name.equals("Compression")) { // Intentionally do nothing: just prevent entry into // the default "else" block and an ensuing // IIOInvalidTreeException; fixes 5110389. } else if (name.equals("Data")) { createBitsPerComponentBoxFromStandardNode(node); createHeaderBoxFromStandardNode(node, numComps); } else if (name.equals("Dimension")) { createResolutionBoxFromStandardNode(node); } else if (name.equals("Document")) { createXMLBoxFromStandardNode(node); } else if (name.equals("Text")) { createXMLBoxFromStandardNode(node); } else if (name.equals("Transparency")) { createChannelDefinitionFromStandardNode(node); } else { throw new IIOInvalidTreeException(I18N.getString("J2KMetadata3") + " " + name, node); } } } private void createColorSpecificationBoxFromStandardNode(Node node) { if (node.getNodeName() != "ColorSpaceType") throw new IllegalArgumentException(I18N.getString("J2KMetadata4")); String name = (String)Box.getAttribute(node, "name"); int ecs = name.equals("RGB") ? ColorSpecificationBox.ECS_sRGB : (name.equals("Gray") ? ColorSpecificationBox.ECS_GRAY : 0); if (ecs == ColorSpecificationBox.ECS_sRGB || ecs ==ColorSpecificationBox.ECS_GRAY) { replace ("JPEG2000ColorSpecificationBox", new ColorSpecificationBox((byte)1, (byte)0, (byte)0, ecs, null)); } } private void createPaletteBoxFromStandardNode(Node node) { if (node.getNodeName() != "Palette") throw new IllegalArgumentException(I18N.getString("J2KMetadata5")); NodeList children = node.getChildNodes(); int maxIndex = -1; boolean hasAlpha = false; for (int i = 0; i < children.getLength(); i++) { Node child = children.item(i); String name = child.getNodeName(); if (name.equals("PaletteEntry")) { String s = (String)Box.getAttribute(child, "index"); int index = new Integer(s).intValue(); if(index > maxIndex) { maxIndex = index; } if(Box.getAttribute(child, "alpha") != null) { hasAlpha = true; } } } // Determine palette size. int numBits = 32; int mask = 0x80000000; while(mask != 0 && (maxIndex & mask) == 0) { numBits--; mask >>>= 1; } int size = 1 << numBits; byte[] red = new byte[size]; byte[] green = new byte[size]; byte[] blue = new byte[size]; byte[] alpha = hasAlpha ? new byte[size]: null; for (int i = 0; i < children.getLength(); i++) { Node child = children.item(i); String name = child.getNodeName(); if (name.equals("PaletteEntry")) { String s = (String)Box.getAttribute(child, "index"); int index = new Integer(s).intValue(); s = (String)Box.getAttribute(child, "red"); red[index] = (byte)(new Integer(s).intValue()); s = (String)Box.getAttribute(child, "green"); green[index] = (byte)(new Integer(s).intValue()); s = (String)Box.getAttribute(child, "blue"); blue[index] = (byte)(new Integer(s).intValue()); byte t = (byte)255; s = (String)Box.getAttribute(child, "alpha"); if(s != null) { t = (byte)(new Integer(s).intValue()); } if(alpha != null) { alpha[index] = t; } } } IndexColorModel icm; if (alpha == null) icm = new IndexColorModel(numBits, size, red, green, blue); else icm = new IndexColorModel(numBits, size, red, green, blue, alpha); replace("JPEG2000PaletteBox", new PaletteBox(icm)); } private void createBitsPerComponentBoxFromStandardNode(Node node) { if (node.getNodeName() != "Data") throw new IllegalArgumentException(I18N.getString("J2KMetadata6")); NodeList children = node.getChildNodes(); byte[] bits = null; boolean isSigned = false; for (int i = 0; i < children.getLength(); i++) { Node child = children.item(i); String name = child.getNodeName(); if (name.equals("BitsPerSample")) { String s = (String)Box.getAttribute(child, "value"); bits = (byte[])Box.parseByteArray(s).clone(); } else if(name.equals("SampleFormat")) { String s = (String)Box.getAttribute(child, "value"); isSigned = s.equals("SignedIntegral"); } } if(bits != null) { // JPEG 2000 "B" parameter represents "bitDepth - 1" in the // right 7 least significant bits with the most significant // bit indicating signed if set and unsigned if not. for (int i = 0; i < bits.length; i++) { bits[i] = (byte)((bits[i]&0xff) - 1); if(isSigned) { bits[i] |= 0x80; } } replace("JPEG2000BitsPerComponent", new BitsPerComponentBox(bits)); } } private void createResolutionBoxFromStandardNode(Node node) { if (node.getNodeName() != "Dimension") throw new IllegalArgumentException(I18N.getString("J2KMetadata7")); NodeList children = node.getChildNodes(); float hRes = 0.0f; float vRes = 0.0f; boolean gotH = false, gotV = false; for (int i = 0; i < children.getLength(); i++) { Node child = children.item(i); String name = child.getNodeName(); if (name.equals("HorizontalPixelSize")) { String s = (String)Box.getAttribute(child, "value"); hRes = new Float(s).floatValue(); hRes = 1000 / hRes; gotH = true; } if (name.equals("VerticalPixelSize")) { String s = (String)Box.getAttribute(child, "value"); vRes = new Float(s).floatValue(); vRes = 1000 / vRes; gotV = true; } } if(gotH && !gotV) { vRes = hRes; } else if(gotV && !gotH) { hRes = vRes; } if(gotH || gotV) { replace("JPEG2000CaptureResolutionBox", new ResolutionBox(0x72657363, hRes, vRes)); } } private void createXMLBoxFromStandardNode(Node node) { NodeList children = node.getChildNodes(); String value = "<" + node.getNodeName() + ">"; for (int i = 0; i < children.getLength(); i++) { Node child = children.item(i); String name = child.getNodeName(); value += "<" + name + " "; NamedNodeMap map = child.getAttributes(); for (int j = 0; j < map.getLength(); j++) { Node att = map.item(j); value += att.getNodeName() + "=\"" + att.getNodeValue() + "\" "; } value += " />"; } value += ""; boxes.add(new XMLBox(value.getBytes())); } private void createHeaderBoxFromStandardNode(Node node, int numComps) { HeaderBox header = (HeaderBox)getElement("JPEG2000HeaderBox"); byte unknownColor = (byte)(getElement("JPEG2000ColorSpecificationBox") == null ? 1: 0); if (header != null) { if (numComps ==0); numComps = header.getNumComponents(); header = new HeaderBox(header.getHeight(), header.getWidth(), numComps, header.getBitDepth(), header.getCompressionType(), unknownColor, header.getIntellectualProperty()); } else { header = new HeaderBox(0, 0, numComps, 0, 0, unknownColor, 0); } replace("JPEG2000HeaderBox", header); } private void createChannelDefinitionFromStandardNode(Node node) { if (node.getNodeName() != "Transparency") throw new IllegalArgumentException(I18N.getString("J2KMetadata8")); HeaderBox header = (HeaderBox)getElement("JPEG2000HeaderBox"); int numComps = 3; if (header != null) { numComps = header.getNumComponents(); } NodeList children = node.getChildNodes(); boolean hasAlpha = false; boolean isPremultiplied = false; for (int i = 0; i < children.getLength(); i++) { Node child = children.item(i); String name = child.getNodeName(); if (name.equals("Alpha")) { String value = (String)Box.getAttribute(child, "value"); if (value.equals("premultiplied")) isPremultiplied = true; if (value.equals("nonpremultiplied")) hasAlpha = true; } } if (!hasAlpha) return; int num = (short)(numComps * (isPremultiplied ? 3 : 2)); short[] channels = new short[num]; short[] types = new short[num]; short[] associations = new short[num]; ChannelDefinitionBox.fillBasedOnBands(numComps, isPremultiplied, channels, types, associations); replace("JPEG2000ChannelDefinitionBox", new ChannelDefinitionBox(channels, types, associations)); } private void replace(String name, Box box) { for (int i = boxes.size() - 1; i >= 0; i--) { Box box1 = (Box)boxes.get(i); if (name.equals(Box.getName(box1.getType()))) { boxes.set(i, box); return; } } boxes.add(box); } private boolean insertNodeIntoTree(IIOMetadataNode root, IIOMetadataNode node) { String name = node.getNodeName(); String parent = format.getParent(name); if (parent == null) return false; IIOMetadataNode parentNode = getNodeFromTree(root, parent, name); if (parentNode == null) parentNode = createNodeIntoTree(root, parent); parentNode.appendChild(node); return true; } private IIOMetadataNode getNodeFromTree(IIOMetadataNode root, String name, String childName) { if (name.equals(root.getNodeName())) return root; NodeList list = root.getChildNodes(); for (int i = 0; i < list.getLength(); i++) { IIOMetadataNode node = (IIOMetadataNode)list.item(i); if (node.getNodeName().equals(name)) { if (name.equals("JPEG2000UUIDInfoBox") && checkUUIDInfoBox(node, childName)) continue; else return node; } node = getNodeFromTree(node, name, childName); if (node != null) return node; } return null; } private IIOMetadataNode createNodeIntoTree(IIOMetadataNode root, String name) { IIOMetadataNode node = getNodeFromTree(root, name, null); if (node != null) return node; node = new IIOMetadataNode(name); String parent = format.getParent(name); IIOMetadataNode parentNode = createNodeIntoTree(root, parent); parentNode.appendChild(node); return node; } private boolean isOriginalSigned(SampleModel sampleModel) { int type = sampleModel.getDataType(); if (type == DataBuffer.TYPE_BYTE || type == DataBuffer.TYPE_USHORT) return false; return true; } /** Check whether the child with a name childName exists. * This method is designed because UUID info box may have many instances. * So if one of its sub-box is inserted into the tree, an empty slut for * this sub-box has to be find or created to avoid one UUID info box * has duplicated sub-boxes. The users have to guarantee each UUID info * box has all the sub-boxes. */ private boolean checkUUIDInfoBox(Node node, String childName) { NodeList list = node.getChildNodes(); for (int i = 0; i < list.getLength(); i++) { IIOMetadataNode child = (IIOMetadataNode)list.item(i); String name = child.getNodeName(); if (name.equals(childName)) return true; } return false; } } ././@LongLink0000000000000000000000000000015100000000000011562 Lustar rootrootjai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/jpeg2000/J2KMetadataFormat.javajai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/jpeg2000/J2KMetadataFormat.0000664000175100017510000003240410233754207032070 0ustar tilletille/* * $RCSfile: J2KMetadataFormat.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.2 $ * $Date: 2005-04-27 18:23:01 $ * $State: Exp $ */ package com.sun.media.imageioimpl.plugins.jpeg2000; import java.awt.image.ColorModel; import java.awt.image.IndexColorModel; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Enumeration; import java.util.Hashtable; import java.util.Iterator; import java.util.List; import java.util.Set; import javax.imageio.metadata.*; import javax.imageio.ImageTypeSpecifier; public class J2KMetadataFormat extends IIOMetadataFormatImpl { /** The table to link the child to its parent. */ private static Hashtable parents = new Hashtable(); static { //children for the root parents.put("JPEG2000SignatureBox", "com_sun_media_imageio_plugins_jpeg2000_image_1.0"); parents.put("JPEG2000FileTypeBox", "com_sun_media_imageio_plugins_jpeg2000_image_1.0"); parents.put("OtherBoxes", "com_sun_media_imageio_plugins_jpeg2000_image_1.0"); // children for the boxes other than // JPEG2000SignatureBox/JPEG2000FileTypeBox parents.put("JPEG2000HeaderSuperBox", "OtherBoxes"); parents.put("JPEG2000CodeStreamBox", "OtherBoxes"); parents.put("JPEG2000IntellectualPropertyRightsBox", "OtherBoxes"); parents.put("JPEG2000XMLBox", "OtherBoxes"); parents.put("JPEG2000UUIDBox", "OtherBoxes"); parents.put("JPEG2000UUIDInfoBox", "OtherBoxes"); // Children of JPEG2000HeaderSuperBox parents.put("JPEG2000HeaderBox", "JPEG2000HeaderSuperBox"); parents.put("OptionalBoxes", "JPEG2000HeaderSuperBox"); // Optional boxes in JPEG2000HeaderSuperBox parents.put("JPEG2000BitsPerComponentBox", "OptionalBoxes"); parents.put("JPEG2000ColorSpecificationBox", "OptionalBoxes"); parents.put("JPEG2000PaletteBox", "OptionalBoxes"); parents.put("JPEG2000ComponentMappingBox", "OptionalBoxes"); parents.put("JPEG2000ChannelDefinitionBox", "OptionalBoxes"); parents.put("JPEG2000ResolutionBox", "OptionalBoxes"); // Children of JPEG2000ResolutionBox parents.put("JPEG2000CaptureResolutionBox", "JPEG2000ResolutionBox"); parents.put("JPEG2000DefaultDisplayResolutionBox", "JPEG2000ResolutionBox"); // Children of JPEG2000UUIDInfoBox parents.put("JPEG2000UUIDListBox", "JPEG2000UUIDInfoBox"); parents.put("JPEG2000DataEntryURLBox", "JPEG2000UUIDInfoBox"); } private static J2KMetadataFormat instance; public static synchronized J2KMetadataFormat getInstance() { if (instance == null) instance = new J2KMetadataFormat(); return instance; } String resourceBaseName = this.getClass().getName() + "Resources"; /** Constructs J2KMetadataFormat. Calls the super * class constructor. Sets the resource base name. Adds the elements * into this format object based on the XML schema and DTD. */ J2KMetadataFormat() { super("com_sun_media_imageio_plugins_jpeg2000_image_1.0", CHILD_POLICY_ALL); setResourceBaseName(resourceBaseName); addElements(); } /** Adds the elements into this format object based on the XML * schema and DTD. */ private void addElements() { addElement("JPEG2000SignatureBox", getParent("JPEG2000SignatureBox"), CHILD_POLICY_EMPTY); addElement("JPEG2000FileTypeBox", getParent("JPEG2000FileTypeBox"), CHILD_POLICY_ALL); addElement("OtherBoxes", getParent("OtherBoxes"), CHILD_POLICY_CHOICE); addElement("JPEG2000HeaderSuperBox", getParent("JPEG2000HeaderSuperBox"), CHILD_POLICY_CHOICE); addElement("JPEG2000CodeStreamBox", getParent("JPEG2000CodeStreamBox"), CHILD_POLICY_EMPTY); addElement("JPEG2000IntellectualPropertyRightsBox", getParent("JPEG2000IntellectualPropertyRightsBox"), CHILD_POLICY_ALL); addElement("JPEG2000XMLBox", getParent("JPEG2000XMLBox"), CHILD_POLICY_ALL); addElement("JPEG2000UUIDBox", getParent("JPEG2000UUIDBox"), CHILD_POLICY_ALL); addElement("JPEG2000UUIDInfoBox", getParent("JPEG2000UUIDInfoBox"), CHILD_POLICY_ALL); addElement("JPEG2000HeaderBox", "JPEG2000HeaderSuperBox", CHILD_POLICY_ALL); addElement("OptionalBoxes", "JPEG2000HeaderSuperBox", CHILD_POLICY_CHOICE); addElement("JPEG2000BitsPerComponentBox", "OptionalBoxes", CHILD_POLICY_ALL); addElement("JPEG2000ColorSpecificationBox", "OptionalBoxes", CHILD_POLICY_ALL); addElement("JPEG2000PaletteBox", "OptionalBoxes", CHILD_POLICY_ALL); addElement("JPEG2000ComponentMappingBox", "OptionalBoxes", CHILD_POLICY_ALL); addElement("JPEG2000ChannelDefinitionBox", "OptionalBoxes", CHILD_POLICY_ALL); addElement("JPEG2000ResolutionBox", "OptionalBoxes", CHILD_POLICY_ALL); addElement("JPEG2000CaptureResolutionBox", "JPEG2000ResolutionBox", CHILD_POLICY_ALL); addElement("JPEG2000DefaultDisplayResolutionBox", "JPEG2000ResolutionBox", CHILD_POLICY_ALL); addElement("JPEG2000UUIDListBox", "JPEG2000UUIDInfoBox", CHILD_POLICY_ALL); addElement("JPEG2000DataEntryURLBox", "JPEG2000UUIDInfoBox", CHILD_POLICY_ALL); // Adds the default attributes "Length", "Type" and "ExtraLength" into // the J2K box-related data elements Enumeration keys = parents.keys(); while (keys.hasMoreElements()) { String s = (String)keys.nextElement(); if (s.startsWith("JPEG2000")) { addAttribute(s, "Length", DATATYPE_INTEGER, true, null); addAttribute(s, "Type", DATATYPE_STRING, true, Box.getTypeByName(s)); addAttribute(s, "ExtraLength", DATATYPE_STRING, false, null); // If it is a simple node, adds the data elements by using // relection. Class c = Box.getBoxClass(Box.getTypeInt(Box.getTypeByName(s))); try { Method m = c.getMethod("getElementNames", (Class[])null); String[] elementNames = (String[])m.invoke(null, (Object[])null); for (int i = 0; i < elementNames.length; i++) addElement(elementNames[i], s, CHILD_POLICY_EMPTY); } catch (Exception e) { // no such method } } } addAttribute("JPEG2000SignatureBox", "Signature", DATATYPE_STRING, true, "0D0A870A"); addElement("BitDepth", "JPEG2000BitsPerComponentBox", CHILD_POLICY_EMPTY); addElement("NumberEntries", "JPEG2000PaletteBox", CHILD_POLICY_EMPTY); addElement("NumberColors", "JPEG2000PaletteBox", CHILD_POLICY_EMPTY); addElement("BitDepth", "JPEG2000PaletteBox", CHILD_POLICY_EMPTY); addElement("LUT", "JPEG2000PaletteBox", 1, 1024); addElement("LUTRow", "LUT", CHILD_POLICY_EMPTY); addElement("Component", "JPEG2000ComponentMappingBox", CHILD_POLICY_EMPTY); addElement("ComponentType", "JPEG2000ComponentMappingBox", CHILD_POLICY_EMPTY); addElement("ComponentAssociation", "JPEG2000ComponentMappingBox", CHILD_POLICY_EMPTY); addElement("NumberOfDefinition", "JPEG2000ChannelDefinitionBox", CHILD_POLICY_EMPTY); addElement("Definitions", "JPEG2000ChannelDefinitionBox", 0, 9); addElement("ChannelNumber", "Definitions", CHILD_POLICY_EMPTY); addElement("ChannelType", "Definitions", CHILD_POLICY_EMPTY); addElement("ChannelAssociation", "Definitions", CHILD_POLICY_EMPTY); addElement("CodeStream", "JPEG2000CodeStreamBox", CHILD_POLICY_EMPTY); addElement("Content", "JPEG2000IntellectualPropertyRightsBox", CHILD_POLICY_EMPTY); addElement("Content", "JPEG2000XMLBox", CHILD_POLICY_EMPTY); addElement("UUID", "JPEG2000UUIDBox", CHILD_POLICY_EMPTY); addElement("Data", "JPEG2000UUIDBox", CHILD_POLICY_EMPTY); addElement("NumberUUID", "JPEG2000UUIDListBox", CHILD_POLICY_EMPTY); addElement("UUID", "JPEG2000UUIDListBox", CHILD_POLICY_EMPTY); addElement("Version", "JPEG2000DataEntryURLBox", CHILD_POLICY_EMPTY); addElement("Flags", "JPEG2000DataEntryURLBox", CHILD_POLICY_EMPTY); addElement("URL", "JPEG2000DataEntryURLBox", CHILD_POLICY_EMPTY); } public String getParent(String elementName) { return (String)parents.get(elementName); } public boolean canNodeAppear(String elementName, ImageTypeSpecifier imageType) { ColorModel cm = imageType.getColorModel(); if (!(cm instanceof IndexColorModel)) if ("JPEG2000PaletteBox".equals(elementName)) return false; if (!cm.hasAlpha()) if ("JPEG2000ChannelDefinitionBox".equals(elementName)) return false; if (getParent(elementName) != null) return true; return false; } public boolean isLeaf(String name) { Set keys = parents.keySet(); Iterator iterator = keys.iterator(); while(iterator.hasNext()) { if (name.equals(parents.get(iterator.next()))) return false; } return true; } public boolean singleInstance(String name) { return !(name.equals("JPEG2000IntellectualPropertyRightsBox") || name.equals("JPEG2000XMLBox") || name.equals("JPEG2000UUIDBox") || name.equals("JPEG2000UUIDInfoBox") || name.equals("JPEG2000UUIDListBox") || name.equals("JPEG2000DataEntryURLBox")); } } jai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/jpeg2000/UUIDListBox.java0000664000175100017510000001267710513030551031605 0ustar tilletille/* * $RCSfile: UUIDListBox.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.2 $ * $Date: 2006-10-10 23:48:57 $ * $State: Exp $ */ package com.sun.media.imageioimpl.plugins.jpeg2000; import javax.imageio.metadata.IIOInvalidTreeException; import javax.imageio.metadata.IIOMetadataNode; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import com.sun.media.imageioimpl.common.ImageUtil; /** This class is defined to represent a UUID list Box of JPEG JP2 * file format. This type of box has a length, a type of "ulst". Its * contents include the number of UUID entry and a list of 16-byte UUIDs. */ public class UUIDListBox extends Box { /** The data elements of this box. */ private short num; private byte[][] uuids; /** Constructs a UUIDListBox from the provided uuid number * and uuids. The provided uuids should have a size of 16; otherwise, * Exception may thrown in later the process. The provided * number should consistent with the size of the uuid array. */ public UUIDListBox(short num, byte[][] uuids) { super(10 + (uuids.length << 4), 0x756c7374, null); this.num = num; this.uuids = uuids; } /** Constructs a UUIDListBox from the provided content * data array. */ public UUIDListBox(byte[] data) { super(8 + data.length, 0x756c7374, data); } /** Constructs a UUIDListBox based on the provided * org.w3c.dom.Node. */ public UUIDListBox(Node node) throws IIOInvalidTreeException { super(node); NodeList children = node.getChildNodes(); int index = 0; for (int i = 0; i < children.getLength(); i++) { Node child = children.item(i); if ("NumberUUID".equals(child.getNodeName())) { num = (short)Box.getShortElementValue(child); uuids = new byte[num][]; } } for (int i = 0; i < children.getLength(); i++) { Node child = children.item(i); if ("UUID".equals(child.getNodeName()) && index < num) { uuids[index++] = Box.getByteArrayElementValue(child); } } } /** Parses the data elements from the provided content data array. */ protected void parse(byte[] data) { num = (short)(((data[0] & 0xFF) << 8) | (data[1] & 0xFF)); uuids = new byte[num][]; int pos = 2; for (int i = 0; i < num; i++) { uuids[i] = new byte[16]; System.arraycopy(data, pos, uuids[i], 0, 16); pos += 16; } } /** Creates an IIOMetadataNode from this UUID list * box. The format of this node is defined in the XML dtd and xsd * for the JP2 image file. */ public IIOMetadataNode getNativeNode() { IIOMetadataNode node = new IIOMetadataNode(Box.getName(getType())); setDefaultAttributes(node); IIOMetadataNode child = new IIOMetadataNode("NumberUUID"); child.setUserObject(new Short(num)); child.setNodeValue("" + num); node.appendChild(child); for (int i = 0; i < num; i++) { child = new IIOMetadataNode("UUID"); child.setUserObject(uuids[i]); child.setNodeValue(ImageUtil.convertObjectToString(uuids[i])); node.appendChild(child); } return node; } protected void compose() { if (data != null) return; data = new byte[2 + num * 16]; data[0] = (byte)(num >> 8); data[1] = (byte)(num & 0xFF); for (int i = 0, pos = 2; i < num; i++) { System.arraycopy(uuids[i], 0, data, pos, 16); pos += 16; } } } jai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/jpeg2000/I18N.java0000664000175100017510000000421710203036165030203 0ustar tilletille/* * $RCSfile: I18N.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.1 $ * $Date: 2005-02-11 05:01:32 $ * $State: Exp $ */ package com.sun.media.imageioimpl.plugins.jpeg2000; import com.sun.media.imageioimpl.common.I18NImpl; final class I18N extends I18NImpl { static String getString(String key) { return getString("com.sun.media.imageioimpl.plugins.jpeg2000.I18N", key); } } ././@LongLink0000000000000000000000000000015100000000000011562 Lustar rootrootjai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/jpeg2000/J2KImageWriterSpi.javajai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/jpeg2000/J2KImageWriterSpi.0000664000175100017510000001164310413303155032064 0ustar tilletille/* * $RCSfile: J2KImageWriterSpi.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.2 $ * $Date: 2006-03-31 19:43:39 $ * $State: Exp $ */ package com.sun.media.imageioimpl.plugins.jpeg2000; import java.awt.image.DataBuffer; import java.awt.image.SampleModel; import javax.imageio.spi.ImageWriterSpi; import javax.imageio.spi.ServiceRegistry; import javax.imageio.spi.IIORegistry; import javax.imageio.ImageWriter; import javax.imageio.ImageTypeSpecifier; import javax.imageio.IIOException; import java.awt.image.ColorModel; import java.awt.image.IndexColorModel; import java.util.Locale; import com.sun.media.imageioimpl.common.PackageUtil; import com.sun.medialib.codec.jiio.Util; public class J2KImageWriterSpi extends ImageWriterSpi { private static String [] readerSpiNames = {"com.sun.media.imageioimpl.plugins.jpeg2000.J2KImageReaderSpi"}; private static String[] formatNames = {"jpeg 2000", "JPEG 2000", "jpeg2000", "JPEG2000"}; private static String[] extensions = {"jp2"}; // Should add jpx or jpm private static String[] mimeTypes = {"image/jp2", "image/jpeg2000"}; private boolean registered = false; public J2KImageWriterSpi() { super(PackageUtil.getVendor(), PackageUtil.getVersion(), formatNames, extensions, mimeTypes, "com.sun.media.imageioimpl.plugins.jpeg2000.J2KImageWriter", STANDARD_OUTPUT_TYPE, readerSpiNames, false, null, null, null, null, true, "com_sun_media_imageio_plugins_jpeg2000_image_1.0", "com.sun.media.imageioimpl.plugins.jpeg2000.J2KMetadataFormat", null, null); } public String getDescription(Locale locale) { String desc = PackageUtil.getSpecificationTitle() + " JPEG 2000 Image Writer"; return desc; } public void onRegistration(ServiceRegistry registry, Class category) { if (registered) { return; } registered = true; // Set pairwise ordering to give codecLib writer precedence. Class codecLibWriterSPIClass = null; try { codecLibWriterSPIClass = Class.forName("com.sun.media.imageioimpl.plugins.jpeg2000.J2KImageWriterCodecLibSpi"); } catch(Throwable t) { // Ignore it. } if(codecLibWriterSPIClass != null) { Object codecLibWriterSPI = registry.getServiceProviderByClass(codecLibWriterSPIClass); if(codecLibWriterSPI != null) { registry.setOrdering(category, codecLibWriterSPI, this); } } } public boolean canEncodeImage(ImageTypeSpecifier type) { SampleModel sm = type.getSampleModel(); if (sm.getNumBands() > 16384) return false; if (sm.getDataType() < DataBuffer.TYPE_BYTE || sm.getDataType() > DataBuffer.TYPE_INT) return false; return true; } public ImageWriter createWriterInstance(Object extension) throws IIOException { return new J2KImageWriter(this); } } ././@LongLink0000000000000000000000000000014600000000000011566 Lustar rootrootjai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/jpeg2000/J2KImageWriter.javajai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/jpeg2000/J2KImageWriter.jav0000664000175100017510000004623310203036165032115 0ustar tilletille/* * $RCSfile: J2KImageWriter.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.1 $ * $Date: 2005-02-11 05:01:34 $ * $State: Exp $ */ package com.sun.media.imageioimpl.plugins.jpeg2000; import java.awt.image.ColorModel; import java.awt.image.DataBuffer; import java.awt.image.DataBufferByte; import java.awt.image.IndexColorModel; import java.awt.image.MultiPixelPackedSampleModel; import java.awt.image.Raster; import java.awt.image.RenderedImage; import java.awt.image.SampleModel; import java.io.File; import java.io.IOException; import java.util.Arrays; import java.util.List; import javax.imageio.IIOImage; import javax.imageio.IIOException; import javax.imageio.ImageTypeSpecifier; import javax.imageio.ImageWriteParam; import javax.imageio.ImageWriter; import javax.imageio.metadata.IIOMetadata; import javax.imageio.metadata.IIOMetadataFormatImpl; import javax.imageio.metadata.IIOInvalidTreeException; import javax.imageio.spi.ImageWriterSpi; import javax.imageio.stream.ImageOutputStream; import jj2000.j2k.codestream.writer.CodestreamWriter; import jj2000.j2k.codestream.writer.FileCodestreamWriter; import jj2000.j2k.codestream.writer.HeaderEncoder; import jj2000.j2k.entropy.encoder.EntropyCoder; import jj2000.j2k.entropy.encoder.PostCompRateAllocator; import jj2000.j2k.fileformat.writer.FileFormatWriter; import jj2000.j2k.image.ImgDataConverter; import jj2000.j2k.image.Tiler; import jj2000.j2k.image.forwcomptransf.ForwCompTransf; import jj2000.j2k.quantization.quantizer.Quantizer; import jj2000.j2k.roi.encoder.ROIScaler; import jj2000.j2k.util.CodestreamManipulator; import jj2000.j2k.wavelet.analysis.ForwardWT; import com.sun.media.imageioimpl.common.ImageUtil; import com.sun.media.imageio.plugins.jpeg2000.J2KImageWriteParam; import org.w3c.dom.Node; /** * The Java Image IO plugin writer for encoding a RenderedImage into * a JPEG 2000 part 1 file (JP2) format. * * This writer has the capability to (1) Losslessly encode * RenderedImages with an IndexColorModel (for * example, bi-level or color indexed images). (2) Losslessly or lossy encode * RenderedImage with a byte, short, ushort or integer types with * band number upto 16384. (3) Encode an image with alpha channel. * (4) Write the provided metadata into the code stream. It also can encode * a raster wrapped in the provided IIOImage. * * The encoding process may re-tile image, clip, subsample, and select bands * using the parameters specified in the ImageWriteParam. * * @see com.sun.media.imageio.plugins.J2KImageWriteParam */ public class J2KImageWriter extends ImageWriter { /** Wrapper for the protected method processImageProgress * So it can be access from the classes which are not in * ImageWriter hierachy. */ public void processImageProgressWrapper(float percentageDone) { processImageProgress(percentageDone); } /** When the writing is aborted, RenderedImageSrc throws a * RuntimeException. */ public static String WRITE_ABORTED = "Write aborted."; /** The output stream to write into */ private ImageOutputStream stream = null; /** Constructs J2KImageWriter based on the provided * ImageWriterSpi. */ public J2KImageWriter(ImageWriterSpi originator) { super(originator); } public void setOutput(Object output) { super.setOutput(output); // validates output if (output != null) { if (!(output instanceof ImageOutputStream)) throw new IllegalArgumentException(I18N.getString("J2KImageWriter0")); this.stream = (ImageOutputStream)output; } else this.stream = null; } public ImageWriteParam getDefaultWriteParam() { return new J2KImageWriteParam(); } public IIOMetadata getDefaultStreamMetadata(ImageWriteParam param) { return null; } public IIOMetadata getDefaultImageMetadata(ImageTypeSpecifier imageType, ImageWriteParam param) { return new J2KMetadata(imageType, param, this); } public IIOMetadata convertStreamMetadata(IIOMetadata inData, ImageWriteParam param) { return null; } public IIOMetadata convertImageMetadata(IIOMetadata inData, ImageTypeSpecifier imageType, ImageWriteParam param) { // Check arguments. if(inData == null) { throw new IllegalArgumentException("inData == null!"); } if(imageType == null) { throw new IllegalArgumentException("imageType == null!"); } // If it's one of ours, return a clone. if (inData instanceof J2KMetadata) { return (IIOMetadata)((J2KMetadata)inData).clone(); } try { J2KMetadata outData = new J2KMetadata(); List formats = Arrays.asList(inData.getMetadataFormatNames()); String format = null; if(formats.contains(J2KMetadata.nativeMetadataFormatName)) { // Initialize from native image metadata format. format = J2KMetadata.nativeMetadataFormatName; } else if(inData.isStandardMetadataFormatSupported()) { // Initialize from standard metadata form of the input tree. format = IIOMetadataFormatImpl.standardMetadataFormatName; } if(format != null) { outData.setFromTree(format, inData.getAsTree(format)); return outData; } } catch(IIOInvalidTreeException e) { return null; } return null; } public boolean canWriteRasters() { return true; } public void write(IIOMetadata streamMetadata, IIOImage image, ImageWriteParam param) throws IOException { if (stream == null) { throw new IllegalStateException(I18N.getString("J2KImageWriter7")); } if (image == null) { throw new IllegalArgumentException(I18N.getString("J2KImageWriter8")); } clearAbortRequest(); processImageStarted(0); RenderedImage input = null; boolean writeRaster = image.hasRaster(); Raster raster = null; SampleModel sampleModel = null; if (writeRaster) { raster = image.getRaster(); sampleModel = raster.getSampleModel(); } else { input = image.getRenderedImage(); sampleModel = input.getSampleModel(); } checkSampleModel(sampleModel); if (param == null) param = getDefaultWriteParam(); J2KImageWriteParamJava j2kwparam = new J2KImageWriteParamJava(image, param); // Packet header cannot exist in two places. if (j2kwparam.getPackPacketHeaderInTile() && j2kwparam.getPackPacketHeaderInMain()) throw new IllegalArgumentException(I18N.getString("J2KImageWriter1")); // Lossless and encoding rate cannot be set at the same time if (j2kwparam.getLossless() && j2kwparam.getEncodingRate()!=Double.MAX_VALUE) throw new IllegalArgumentException(I18N.getString("J2KImageWriter2")); // If the source image is bilevel or color-indexed, or, the // encoding rate is Double.MAX_VALUE, use lossless if ((!writeRaster && input.getColorModel() instanceof IndexColorModel) || (writeRaster && raster.getSampleModel() instanceof MultiPixelPackedSampleModel)) { j2kwparam.setDecompositionLevel("0"); j2kwparam.setLossless(true); j2kwparam.setEncodingRate(Double.MAX_VALUE); j2kwparam.setQuantizationType("reversible"); j2kwparam.setFilters(J2KImageWriteParam.FILTER_53); } else if (j2kwparam.getEncodingRate() == Double.MAX_VALUE) { j2kwparam.setLossless(true); j2kwparam.setQuantizationType("reversible"); j2kwparam.setFilters(J2KImageWriteParam.FILTER_53); } // Gets parameters from the write parameter boolean pphTile = j2kwparam.getPackPacketHeaderInTile(); boolean pphMain = j2kwparam.getPackPacketHeaderInMain(); boolean tempSop = false; boolean tempEph = false; int[] bands = param.getSourceBands(); int ncomp = sampleModel.getNumBands(); if (bands != null) ncomp = bands.length; // create the encoding source recognized by jj2000 packages RenderedImageSrc imgsrc = null; if (writeRaster) imgsrc = new RenderedImageSrc(raster, j2kwparam, this); else imgsrc = new RenderedImageSrc(input, j2kwparam, this); // if the components signed boolean[] imsigned = new boolean[ncomp]; if (bands != null) { for (int i=0; i refx || trefy > refy) throw new IIOException(I18N.getString("J2KImageWriter4")); // Instantiate tiler Tiler imgtiler = new Tiler(imgsrc,refx,refy,trefx,trefy,tw,th); // Creates the forward component transform ForwCompTransf fctransf = new ForwCompTransf(imgtiler, j2kwparam); // Creates ImgDataConverter ImgDataConverter converter = new ImgDataConverter(fctransf); // Creates ForwardWT (forward wavelet transform) ForwardWT dwt = ForwardWT.createInstance(converter, j2kwparam); // Creates Quantizer Quantizer quant = Quantizer.createInstance(dwt,j2kwparam); // Creates ROIScaler ROIScaler rois = ROIScaler.createInstance(quant, j2kwparam); // Creates EntropyCoder EntropyCoder ecoder = EntropyCoder.createInstance(rois, j2kwparam, j2kwparam.getCodeBlockSize(), j2kwparam.getPrecinctPartition(), j2kwparam.getBypass(), j2kwparam.getResetMQ(), j2kwparam.getTerminateOnByte(), j2kwparam.getCausalCXInfo(), j2kwparam.getCodeSegSymbol(), j2kwparam.getMethodForMQLengthCalc(), j2kwparam.getMethodForMQTermination()); // Rely on rate allocator to limit amount of data File tmpFile = File.createTempFile("jiio-", ".tmp"); tmpFile.deleteOnExit(); // Creates CodestreamWriter FileCodestreamWriter bwriter = new FileCodestreamWriter(tmpFile, Integer.MAX_VALUE); // Creates the rate allocator float rate = (float)j2kwparam.getEncodingRate(); PostCompRateAllocator ralloc = PostCompRateAllocator.createInstance(ecoder, rate, bwriter, j2kwparam); // Instantiates the HeaderEncoder HeaderEncoder headenc = new HeaderEncoder(imgsrc, imsigned, dwt, imgtiler, j2kwparam, rois,ralloc); ralloc.setHeaderEncoder(headenc); // Writes header to be able to estimate header overhead headenc.encodeMainHeader(); //Initializes rate allocator, with proper header // overhead. This will also encode all the data try { ralloc.initialize(); } catch (RuntimeException e) { if (WRITE_ABORTED.equals(e.getMessage())) { bwriter.close(); tmpFile.delete(); processWriteAborted(); return; } else throw e; } // Write header (final) headenc.reset(); headenc.encodeMainHeader(); // Insert header into the codestream bwriter.commitBitstreamHeader(headenc); // Now do the rate-allocation and write result ralloc.runAndWrite(); //Done for data encoding bwriter.close(); // Calculate file length int fileLength = bwriter.getLength(); // Tile-parts and packed packet headers int pktspertp = j2kwparam.getPacketPerTilePart(); int ntiles = imgtiler.getNumTiles(); if (pktspertp>0 || pphTile || pphMain){ CodestreamManipulator cm = new CodestreamManipulator(tmpFile, ntiles, pktspertp, pphMain, pphTile, tempSop, tempEph); fileLength += cm.doCodestreamManipulation(); } // File Format int nc= imgsrc.getNumComps() ; int[] bpc = new int[nc]; for(int comp = 0; compabortRequested * to allow the abortions be monitored by J2KRenderedImage. */ public boolean getAbortRequest() { return abortRequested(); } private void checkSampleModel(SampleModel sm) { int type = sm.getDataType(); if (type < DataBuffer.TYPE_BYTE || type > DataBuffer.TYPE_INT) throw new IllegalArgumentException(I18N.getString("J2KImageWriter5")); if (sm.getNumBands() > 16384) throw new IllegalArgumentException(I18N.getString("J2KImageWriter6")); } } ././@LongLink0000000000000000000000000000015700000000000011570 Lustar rootrootjai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/jpeg2000/J2KImageReaderResources.javajai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/jpeg2000/J2KImageReaderReso0000664000175100017510000000421710203036165032111 0ustar tilletille/* * $RCSfile: J2KImageReaderResources.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.1 $ * $Date: 2005-02-11 05:01:34 $ * $State: Exp $ */ package com.sun.media.imageioimpl.plugins.jpeg2000; public class J2KImageReaderResources { static final Object[][] contents = { }; public J2KImageReaderResources() {} public Object[][] getContents() { return contents; } } jai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/jpeg2000/UUIDBox.java0000664000175100017510000001101210203036165030732 0ustar tilletille/* * $RCSfile: UUIDBox.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.1 $ * $Date: 2005-02-11 05:01:37 $ * $State: Exp $ */ package com.sun.media.imageioimpl.plugins.jpeg2000; import javax.imageio.metadata.IIOInvalidTreeException; import javax.imageio.metadata.IIOMetadataNode; import org.w3c.dom.Node; import org.w3c.dom.NodeList; /** This class is defined to represent a UUID Box of JPEG JP2 * file format. This type of box has a length, a type of "uuid". Its * content is a 16-byte UUID followed with a various-length data. */ public class UUIDBox extends Box { /** Cache the element names for this box's xml definition */ private static String[] elementNames = {"UUID", "Data"}; /** This method will be called by the getNativeNodeForSimpleBox of the * class Box to get the element names. */ public static String[] getElementNames() { return elementNames; } /** The data elements in this UUID box. */ private byte[] uuid; private byte[] udata; /** Constructs a UUIDBox from its content data array. */ public UUIDBox(byte[] data) { super(8 + data.length, 0x75756964, data); } /** Constructs a UUIDBox based on the provided * org.w3c.dom.Node. */ public UUIDBox(Node node) throws IIOInvalidTreeException { super(node); NodeList children = node.getChildNodes(); for (int i = 0; i < children.getLength(); i++) { Node child = children.item(i); String name = child.getNodeName(); if ("UUID".equals(name)) { uuid = Box.getByteArrayElementValue(child); } if ("Data".equals(name)) { udata = Box.getByteArrayElementValue(child); } } } /** Parses the data elements from the provided data array. */ protected void parse(byte[] data) { uuid = new byte[16]; System.arraycopy(data, 0, uuid, 0, 16); udata = new byte[data.length - 16]; System.arraycopy(data, 16, udata, 0, udata.length); } /** Returns the UUID of this box. */ public byte[] getUUID() { return uuid; } /** Returns the UUID data of this box. */ public byte[] getData() { return udata; } /** Creates an IIOMetadataNode from this UUID * box. The format of this node is defined in the XML dtd and xsd * for the JP2 image file. */ public IIOMetadataNode getNativeNode() { return getNativeNodeForSimpleBox(); } protected void compose() { if (data != null) return; data = new byte[16 + udata.length]; System.arraycopy(uuid, 0, data, 0, 16); System.arraycopy(udata, 0, data, 16, udata.length); } } jai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/jpeg2000/SignatureBox.java0000664000175100017510000000702510203036165032136 0ustar tilletille/* * $RCSfile: SignatureBox.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.1 $ * $Date: 2005-02-11 05:01:37 $ * $State: Exp $ */ package com.sun.media.imageioimpl.plugins.jpeg2000; import org.w3c.dom.Node; import javax.imageio.metadata.IIOInvalidTreeException; import javax.imageio.metadata.IIOMetadataNode; /** This class is defined to represent a Signature Box of JPEG JP2 * file format. This type of box has a fixed length of 12, a type of "jP " * and a four byte content of 0x0D0A870A, which is used to detects of the * common file transmission errors which substitutes with or * vice versa. */ public class SignatureBox extends Box { /** Constructs a SignatureBox. */ public SignatureBox() { super(12, 0x6A502020, null); } /** Constructs a SignatureBox based on the provided * org.w3c.dom.Node. */ public SignatureBox(Node node) throws IIOInvalidTreeException { super(node); } /** Constructs a SignatureBox based on the provided * byte array. */ public SignatureBox(byte[] data) throws IIOInvalidTreeException { super(12, 0x6A502020, data); } /** Creates an IIOMetadataNode from this signature * box. The format of this node is defined in the XML dtd and xsd * for the JP2 image file. */ public IIOMetadataNode getNativeNode() { IIOMetadataNode node = new IIOMetadataNode(Box.getName(getType())); setDefaultAttributes(node); node.setAttribute("Signature", Integer.toString(0x0D0A870A)); return node; } protected void compose() { if (data != null) return; data = new byte[]{(byte)0x0D, (byte)0x0A, (byte)0x87, (byte)0x0A}; } } ././@LongLink0000000000000000000000000000015300000000000011564 Lustar rootrootjai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/jpeg2000/ComponentMappingBox.javajai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/jpeg2000/ComponentMappingBo0000664000175100017510000001417110203036165032343 0ustar tilletille/* * $RCSfile: ComponentMappingBox.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.1 $ * $Date: 2005-02-11 05:01:32 $ * $State: Exp $ */ package com.sun.media.imageioimpl.plugins.jpeg2000; import javax.imageio.metadata.IIOInvalidTreeException; import javax.imageio.metadata.IIOMetadataNode; import org.w3c.dom.Node; import org.w3c.dom.NodeList; /** This class is defined to represent a Color Specification Box of JPEG JP2 * file format. A Channel Definition Box has a length, and a fixed type * of "cmap". This box exists if and only is a PaletteBox exists. Its * content defines the type LUT output components and their mapping to the * color component. */ public class ComponentMappingBox extends Box { /** The data elements. */ private short[] components; private byte[] type; private byte[] map; /** Constructs a ComponentMappingBox from the provided * content byte array. */ public ComponentMappingBox(byte[] data) { super(8 + data.length, 0x636D6170, data); } /** Constructs a ComponentMappingBox from the provided * component mapping. */ public ComponentMappingBox(short[] comp, byte[] t, byte[] m) { super(8 + (comp.length << 2), 0x636D6170, null); this.components = comp; this.type = t; this.map = m; } /** Constructs a ComponentMappingBox based on the provided * org.w3c.dom.Node. */ public ComponentMappingBox(Node node) throws IIOInvalidTreeException { super(node); NodeList children = node.getChildNodes(); int len = children.getLength() / 3; components = new short[len]; type = new byte[len]; map = new byte[len]; len *= 3; int index = 0; for (int i = 0; i < len; i++) { Node child = children.item(i); String name = child.getNodeName(); if ("Component".equals(name)) { components[index] = Box.getShortElementValue(child); } if ("ComponentType".equals(name)) { type[index] = Box.getByteElementValue(child); } if ("ComponentAssociation".equals(name)) { map[index++] = Box.getByteElementValue(child); } } } /** Parse the component mapping from the provided content data array. */ protected void parse(byte[] data) { int len = data.length / 4; components = new short[len]; type = new byte[len]; map = new byte[len]; for (int i = 0, j = 0; i < len; i++) { components[i] = (short)(((data[j++] & 0xFF) << 8) | (data[j++] & 0xFF)); type[i] = data[j++]; map[i] = data[j++]; } } /** Creates an IIOMetadataNode from this component mapping * box. The format of this node is defined in the XML dtd and xsd * for the JP2 image file. */ public IIOMetadataNode getNativeNode() { IIOMetadataNode node = new IIOMetadataNode(Box.getName(getType())); setDefaultAttributes(node); for (int i = 0; i < components.length; i++) { IIOMetadataNode child = new IIOMetadataNode("Component"); Short obj = new Short(components[i]); child.setUserObject(new Short(components[i])); child.setNodeValue("" + components[i]); node.appendChild(child); child = new IIOMetadataNode("ComponentType"); child.setUserObject(new Byte(type[i])); child.setNodeValue("" + type[i]); node.appendChild(child); child = new IIOMetadataNode("ComponentAssociation"); child.setUserObject(new Byte(map[i])); child.setNodeValue("" + map[i]); node.appendChild(child); } return node; } public short[] getComponent() { return components; } public byte[] getComponentType() { return type; } public byte[] getComponentAssociation() { return map; } protected void compose() { if (data != null) return; data = new byte[type.length << 2]; for (int i = 0, j = 0; i < type.length; i++) { data[j++] = (byte)(components[i] >> 8); data[j++] = (byte)(components[i] & 0xFF); data[j++] = type[i]; data[j++] = map[i]; } } } jai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/clib/0000775000175100017510000000000011650556210026344 5ustar tilletille././@LongLink0000000000000000000000000000014600000000000011566 Lustar rootrootjai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/clib/InputStreamAdapter.javajai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/clib/InputStreamAdapter.jav0000664000175100017510000000561310203036165032622 0ustar tilletille/* * $RCSfile: InputStreamAdapter.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.1 $ * $Date: 2005-02-11 05:01:28 $ * $State: Exp $ */ package com.sun.media.imageioimpl.plugins.clib; import java.io.IOException; import java.io.InputStream; import javax.imageio.stream.ImageInputStream; /** */ public final class InputStreamAdapter extends InputStream { ImageInputStream stream; public InputStreamAdapter(ImageInputStream stream) { super(); this.stream = stream; } public void close() throws IOException { stream.close(); } public void mark(int readlimit) { stream.mark(); } public boolean markSupported() { return true; } public int read() throws IOException { return stream.read(); } public int read(byte b[], int off, int len) throws IOException { return stream.read(b, off, len); } public void reset() throws IOException { stream.reset(); } public long skip(long n) throws IOException { return stream.skipBytes(n); } public ImageInputStream getWrappedStream() { return stream; } } ././@LongLink0000000000000000000000000000014700000000000011567 Lustar rootrootjai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/clib/OutputStreamAdapter.javajai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/clib/OutputStreamAdapter.ja0000664000175100017510000000515110203036165032632 0ustar tilletille/* * $RCSfile: OutputStreamAdapter.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.1 $ * $Date: 2005-02-11 05:01:28 $ * $State: Exp $ */ package com.sun.media.imageioimpl.plugins.clib; import java.io.IOException; import java.io.OutputStream; import javax.imageio.stream.ImageOutputStream; /** */ public final class OutputStreamAdapter extends OutputStream { ImageOutputStream stream; public OutputStreamAdapter(ImageOutputStream stream) { super(); this.stream = stream; } public void close() throws IOException { stream.close(); } public void write(byte[] b) throws IOException { stream.write(b); } public void write(byte[] b, int off, int len) throws IOException { stream.write(b, off, len); } public void write(int b) throws IOException { stream.write(b); } } jai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/clib/properties0000664000175100017510000000060610203036165030460 0ustar tilletille# # $RCSfile: properties,v $ # # Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved. # # Use is subject to license terms. # # $Revision: 1.1 $ # $Date: 2005-02-11 05:01:28 $ # $State: Exp $ # # Internationalization file for com.sun.media.imageioimpl.plugins.clib Generic0=Unsupported data type CLibImageReader0=Parameter may not be null. CLibImageWriter0=Unsupported data depth jai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/clib/CLibImageWriter.java0000664000175100017510000010336710562176743032204 0ustar tilletille/* * $RCSfile: CLibImageWriter.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.6 $ * $Date: 2007-02-06 22:14:59 $ * $State: Exp $ */ package com.sun.media.imageioimpl.plugins.clib; import java.awt.Point; import java.awt.Rectangle; import java.awt.color.ColorSpace; import java.awt.geom.AffineTransform; import java.awt.image.AffineTransformOp; import java.awt.image.ColorModel; import java.awt.image.ComponentSampleModel; import java.awt.image.DataBuffer; import java.awt.image.DataBufferByte; import java.awt.image.DataBufferUShort; import java.awt.image.IndexColorModel; import java.awt.image.MultiPixelPackedSampleModel; import java.awt.image.PixelInterleavedSampleModel; import java.awt.image.Raster; import java.awt.image.RenderedImage; import java.awt.image.SampleModel; import java.awt.image.SinglePixelPackedSampleModel; import java.awt.image.WritableRaster; import java.io.IOException; import javax.imageio.IIOImage; import javax.imageio.ImageWriter; import javax.imageio.ImageWriteParam; import javax.imageio.ImageTypeSpecifier; import javax.imageio.metadata.IIOMetadata; import javax.imageio.spi.ImageWriterSpi; import com.sun.medialib.codec.jiio.Constants; import com.sun.medialib.codec.jiio.mediaLibImage; public abstract class CLibImageWriter extends ImageWriter { /** * Returns the data array from the DataBuffer. */ private static final Object getDataBufferData(DataBuffer db) { Object data; int dType = db.getDataType(); switch (dType) { case DataBuffer.TYPE_BYTE: data = ((DataBufferByte)db).getData(); break; case DataBuffer.TYPE_USHORT: data = ((DataBufferUShort)db).getData(); break; default: throw new IllegalArgumentException (I18N.getString("Generic0")+" "+dType); } return data; } /** * Returns the mediaLib type enum given the Java2D type enum. */ private static final int getMediaLibDataType(int dataType) { int mlibType; switch (dataType) { case DataBuffer.TYPE_BYTE: mlibType = mediaLibImage.MLIB_BYTE; break; case DataBuffer.TYPE_USHORT: mlibType = mediaLibImage.MLIB_USHORT; break; default: throw new IllegalArgumentException (I18N.getString("Generic0")+" "+dataType); } return mlibType; } /** * Returns the mediaLib format enum given the SampleModel * and ColorModel of an image. If the format cannot be * determined to be anything more specific, the value * Constants.MLIB_FORMAT_UNKNOWN will be returned. * * @param sampleModel The SampleModel describing the * layout of the DataBuffer; may be null. * @param colorModel The ColorModel describing the * mapping of the samples in a pixel to a color. * * @throws IllegalArgumentExcaption if sampleModel is * null. * * @return One of the Constants.MLIB_FORMAT constants. */ private static final int getMediaLibFormat(SampleModel sampleModel, ColorModel colorModel) { if(sampleModel == null) { throw new IllegalArgumentException("sampleModel == null!"); } int mlibFormat = Constants.MLIB_FORMAT_UNKNOWN; if(sampleModel instanceof SinglePixelPackedSampleModel && sampleModel.getNumBands() == 4 && colorModel != null && colorModel.hasAlpha()) { int[] masks = ((SinglePixelPackedSampleModel)sampleModel).getBitMasks(); if(masks[3] == 0xff000000) { if(masks[0] == 0xff && masks[1] == 0xff00 && masks[2] == 0xff0000) { mlibFormat = Constants.MLIB_FORMAT_PACKED_ABGR; } else if(masks[0] == 0xff0000 && masks[1] == 0xff00 && masks[2] == 0xff) { mlibFormat = Constants.MLIB_FORMAT_PACKED_ARGB; } } } else if(sampleModel instanceof ComponentSampleModel) { ComponentSampleModel csm = (ComponentSampleModel)sampleModel; int bandOffsets[] = csm.getBandOffsets(); int pixelStride = csm.getPixelStride(); if (pixelStride == bandOffsets.length) { int numBands = pixelStride; // for clarity boolean hasOneBank = true; int bankIndices[] = csm.getBankIndices(); for (int i = 1; i < bankIndices.length; i++) { if(bankIndices[i] != bankIndices[0]) { hasOneBank = false; } } if(hasOneBank) { if(colorModel instanceof IndexColorModel) { mlibFormat = Constants.MLIB_FORMAT_INDEXED; } else if(numBands == 1) { mlibFormat = Constants.MLIB_FORMAT_GRAYSCALE; } else if(numBands == 2 && bandOffsets[0] == 0 && bandOffsets[1] == 1) { mlibFormat = Constants.MLIB_FORMAT_GRAYSCALE_ALPHA; } else if(numBands == 3) { int csType = colorModel != null ? colorModel.getColorSpace().getType() : ColorSpace.TYPE_RGB; if(csType == ColorSpace.TYPE_RGB) { if(bandOffsets[0] == 2 && bandOffsets[1] == 1 && bandOffsets[2] == 0) { mlibFormat = Constants.MLIB_FORMAT_BGR; } else if(bandOffsets[0] == 0 && bandOffsets[1] == 1 && bandOffsets[2] == 2) { mlibFormat = Constants.MLIB_FORMAT_RGB; } } else if(csType == ColorSpace.TYPE_Yxy && bandOffsets[0] == 0 && bandOffsets[1] == 1 && bandOffsets[2] == 2) { mlibFormat = Constants.MLIB_FORMAT_YCC; } } else if(numBands == 4) { int csType = colorModel != null ? colorModel.getColorSpace().getType() : ColorSpace.TYPE_RGB; if(csType == ColorSpace.TYPE_RGB) { if(bandOffsets[3] == 0) { if(bandOffsets[0] == 3 && bandOffsets[1] == 2 && bandOffsets[2] == 1) { mlibFormat = Constants.MLIB_FORMAT_ABGR; } else if(bandOffsets[0] == 1 && bandOffsets[1] == 2 && bandOffsets[2] == 3) { mlibFormat = Constants.MLIB_FORMAT_ARGB; } } else if(bandOffsets[3] == 3) { if(bandOffsets[0] == 0 && bandOffsets[1] == 1 && bandOffsets[2] == 2) { mlibFormat = Constants.MLIB_FORMAT_RGBA; } else if(bandOffsets[0] == 2 && bandOffsets[1] == 1 && bandOffsets[2] == 0) { mlibFormat = Constants.MLIB_FORMAT_BGRA; } } } else if(csType == ColorSpace.TYPE_CMYK && bandOffsets[0] == 0 && bandOffsets[1] == 1 && bandOffsets[2] == 2 && bandOffsets[3] == 3) { mlibFormat = Constants.MLIB_FORMAT_CMYK; } else if(csType == ColorSpace.TYPE_Yxy && bandOffsets[0] == 0 && bandOffsets[1] == 1 && bandOffsets[2] == 2 && bandOffsets[3] == 3) { if(colorModel != null && colorModel.hasAlpha()) { mlibFormat = Constants.MLIB_FORMAT_YCCA; } else { mlibFormat = Constants.MLIB_FORMAT_YCCK; } } } } } } return mlibFormat; } /** * Returns a contiguous Raster of data over the specified * Rectangle. If the region is a sub-region of a single * tile, then a child of that tile will be returned. If the region * overlaps more than one tile and has 8 bits per sample, then a * pixel interleaved Raster having band offsets 0,1,... will be returned. * Otherwise the Raster returned by im.copyData(null) will * be returned. */ private static final Raster getContiguousData(RenderedImage im, Rectangle region) { if(im == null) { throw new IllegalArgumentException("im == null"); } else if(region == null) { throw new IllegalArgumentException("region == null"); } Raster raster; if(im.getNumXTiles() == 1 && im.getNumYTiles() == 1) { // Image is not tiled so just get a reference to the tile. raster = im.getTile(im.getMinTileX(), im.getMinTileY()); // Ensure result has requested coverage. Rectangle bounds = raster.getBounds(); if (!bounds.equals(region)) { raster = raster.createChild(region.x, region.y, region.width, region.height, region.x, region.y, null); } } else { // Image is tiled. // Create an interleaved raster for copying for 8-bit case. // This ensures that for RGB data the band offsets are {0,1,2}. SampleModel sampleModel = im.getSampleModel(); WritableRaster target = sampleModel.getSampleSize(0) == 8 ? Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE, im.getWidth(), im.getHeight(), sampleModel.getNumBands(), new Point(im.getMinX(), im.getMinY())) : null; // Copy the data. raster = im.copyData(target); } return raster; } /** * Subsamples and sub-bands the input Raster over a * sub-region and stores the result in a WritableRaster. * * @param src The source Raster * @param sourceBands The source bands to use; may be null * @param subsampleX The subsampling factor along the horizontal axis. * @param subsampleY The subsampling factor along the vertical axis. * in which case all bands will be used. * @param dst The destination WritableRaster. * @throws IllegalArgumentException if source is * null or empty, dst is null, * sourceBands.length exceeds the number of bands in * source, or sourcBands contains an element * which is negative or greater than or equal to the number of bands * in source. */ private static void reformat(Raster source, int[] sourceBands, int subsampleX, int subsampleY, WritableRaster dst) { // Check for nulls. if(source == null) { throw new IllegalArgumentException("source == null!"); } else if(dst == null) { throw new IllegalArgumentException("dst == null!"); } // Validate the source bounds. XXX is this needed? Rectangle sourceBounds = source.getBounds(); if(sourceBounds.isEmpty()) { throw new IllegalArgumentException ("source.getBounds().isEmpty()!"); } // Check sub-banding. boolean isSubBanding = false; int numSourceBands = source.getSampleModel().getNumBands(); if(sourceBands != null) { if(sourceBands.length > numSourceBands) { throw new IllegalArgumentException ("sourceBands.length > numSourceBands!"); } boolean isRamp = sourceBands.length == numSourceBands; for(int i = 0; i < sourceBands.length; i++) { if(sourceBands[i] < 0 || sourceBands[i] >= numSourceBands) { throw new IllegalArgumentException ("sourceBands[i] < 0 || sourceBands[i] >= numSourceBands!"); } else if(sourceBands[i] != i) { isRamp = false; } } isSubBanding = !isRamp; } // Allocate buffer for a single source row. int sourceWidth = sourceBounds.width; int[] pixels = new int[sourceWidth*numSourceBands]; // Initialize variables used in loop. int sourceX = sourceBounds.x; int sourceY = sourceBounds.y; int numBands = sourceBands != null ? sourceBands.length : numSourceBands; int dstWidth = dst.getWidth(); int dstYMax = dst.getHeight() - 1; int copyFromIncrement = numSourceBands*subsampleX; // Loop over source rows, subsample each, and store in destination. for(int dstY = 0; dstY <= dstYMax; dstY++) { // Read one row. source.getPixels(sourceX, sourceY, sourceWidth, 1, pixels); // Copy within the same buffer by left shifting. if(isSubBanding) { int copyFrom = 0; int copyTo = 0; for(int i = 0; i < dstWidth; i++) { for(int j = 0; j < numBands; j++) { pixels[copyTo++] = pixels[copyFrom + sourceBands[j]]; } copyFrom += copyFromIncrement; } } else { int copyFrom = copyFromIncrement; int copyTo = numSourceBands; // Start from index 1 as no need to copy the first pixel. for(int i = 1; i < dstWidth; i++) { int k = copyFrom; for(int j = 0; j < numSourceBands; j++) { pixels[copyTo++] = pixels[k++]; } copyFrom += copyFromIncrement; } } // Set the destionation row. dst.setPixels(0, dstY, dstWidth, 1, pixels); // Increment the source row. sourceY += subsampleY; } } protected CLibImageWriter(ImageWriterSpi originatingProvider) { super(originatingProvider); } public IIOMetadata convertImageMetadata(IIOMetadata inData, ImageTypeSpecifier imageType, ImageWriteParam param) { return null; } public IIOMetadata convertStreamMetadata(IIOMetadata inData, ImageWriteParam param) { return null; } public IIOMetadata getDefaultImageMetadata(ImageTypeSpecifier imageType, ImageWriteParam param) { return null; } public IIOMetadata getDefaultStreamMetadata(ImageWriteParam param) { return null; } /* XXX protected int getSignificantBits(RenderedImage image) { SampleModel sampleModel = image.getSampleModel(); int numBands = sampleModel.getNumBands(); int[] sampleSize = sampleModel.getSampleSize(); int significantBits = sampleSize[0]; for(int i = 1; i < numBands; i++) { significantBits = Math.max(significantBits, sampleSize[i]); } return significantBits; } */ // Code copied from ImageReader.java with ImageReadParam replaced // by ImageWriteParam. private static final Rectangle getSourceRegion(ImageWriteParam param, int sourceMinX, int sourceMinY, int srcWidth, int srcHeight) { Rectangle sourceRegion = new Rectangle(sourceMinX, sourceMinY, srcWidth, srcHeight); if (param != null) { Rectangle region = param.getSourceRegion(); if (region != null) { sourceRegion = sourceRegion.intersection(region); } int subsampleXOffset = param.getSubsamplingXOffset(); int subsampleYOffset = param.getSubsamplingYOffset(); sourceRegion.x += subsampleXOffset; sourceRegion.y += subsampleYOffset; sourceRegion.width -= subsampleXOffset; sourceRegion.height -= subsampleYOffset; } return sourceRegion; } /** * Returns a mediaLibImage for a specific encoder to use * to encode image. * * @param image The image to encode. * @param param The write parameters. * @param allowBilevel Whether bilevel images are allowed. A bilevel * image must have one 1-bit sample per pixel, have data type * DataBuffer.TYE_BYTE, and have a * MultiPixelPackedSampleModel. * @param supportedFormats An array containing constan values from * the set of mediaLibImage.MLIB_FORMAT enums. * * @throws IllegalArgumentException if supportedFormats * is null. * * @return A mediaLibImage in a format capable of being written * by the encoder. */ protected mediaLibImage getMediaLibImage(RenderedImage image, ImageWriteParam param, boolean allowBilevel, int[] supportedFormats) { if(supportedFormats == null) { throw new IllegalArgumentException("supportedFormats == null!"); } // Determine the source region. Rectangle sourceRegion = getSourceRegion(param, image.getMinX(), image.getMinY(), image.getWidth(), image.getHeight()); if(sourceRegion.isEmpty()) { throw new IllegalArgumentException("sourceRegion.isEmpty()"); } // Check whether reformatting is necessary to conform to mediaLib // image format (packed bilevel if allowed or ((G|I)|(RGB))[A]). // Flag indicating need to reformat data. boolean reformatData = false; // Flag indicating bilevel data. boolean isBilevel = false; // Value indicating the mediaLib image format. int mediaLibFormat = Constants.MLIB_FORMAT_UNKNOWN; // Get the SampleModel. SampleModel sampleModel = image.getSampleModel(); // Get the number of bands. int numSourceBands = sampleModel.getNumBands(); // Get the source sub-banding array. int[] sourceBands = param != null ? param.getSourceBands() : null; // Check for non-nominal sub-banding. int numBands; if(sourceBands != null) { numBands = sourceBands.length; if(numBands != numSourceBands) { // The number of bands must be the same. reformatData = true; } else { // The band order must not change. for(int i = 0; i < numSourceBands; i++) { if(sourceBands[i] != i) { reformatData = true; break; } } } } else { numBands = numSourceBands; } // If sub-banding does not dictate reformatting, check subsampling.. if(!reformatData && param != null && (param.getSourceXSubsampling() != 1 || param.getSourceXSubsampling() != 1)) { reformatData = true; } // If sub-banding does not dictate reformatting check SampleModel. if(!reformatData) { if(allowBilevel && sampleModel.getNumBands() == 1 && sampleModel.getSampleSize(0) == 1 && sampleModel instanceof MultiPixelPackedSampleModel && sampleModel.getDataType() == DataBuffer.TYPE_BYTE) { // Need continguous packed bits. MultiPixelPackedSampleModel mppsm = (MultiPixelPackedSampleModel)sampleModel; if(mppsm.getPixelBitStride() == 1) { isBilevel = true; } else { reformatData = true; } } else { // Set the mediaLib format flag. mediaLibFormat = getMediaLibFormat(sampleModel, image.getColorModel()); // Set the data reformatting flag. reformatData = true; int len = supportedFormats.length; for(int i = 0; i < len; i++) { if(mediaLibFormat == supportedFormats[i]) { reformatData = false; break; } } } } // Variable for the eventual destination data. Raster raster = null; if(reformatData) { // Determine the maximum bit depth. int[] sampleSize = sampleModel.getSampleSize(); int bitDepthMax = sampleSize[0]; for(int i = 1; i < numSourceBands; i++) { bitDepthMax = Math.max(bitDepthMax, sampleSize[i]); } // Set the data type as a function of bit depth. int dataType; if(bitDepthMax <= 8) { dataType = DataBuffer.TYPE_BYTE; } else if(bitDepthMax <= 16) { dataType = DataBuffer.TYPE_USHORT; } else { throw new UnsupportedOperationException (I18N.getString("CLibImageWriter0")+" "+bitDepthMax); } // Determine the width and height. int width; int height; if(param != null) { int subsampleX = param.getSourceXSubsampling(); int subsampleY = param.getSourceYSubsampling(); width = (sourceRegion.width + subsampleX - 1)/subsampleX; height = (sourceRegion.height + subsampleY - 1)/subsampleY; } else { width = sourceRegion.width; height = sourceRegion.height; } // Load a ramp for band offsets. int[] newBandOffsets = new int[numBands]; for(int i = 0; i < numBands; i++) { newBandOffsets[i] = i; } // Create a new SampleModel. SampleModel newSampleModel; if(allowBilevel && sampleModel.getNumBands() == 1 && bitDepthMax == 1) { // Bilevel image. newSampleModel = new MultiPixelPackedSampleModel(dataType, width, height, 1); isBilevel = true; } else { // Pixel interleaved image. newSampleModel = new PixelInterleavedSampleModel(dataType, width, height, newBandOffsets.length, width*numSourceBands, newBandOffsets); } // Create a new Raster at (0,0). WritableRaster newRaster = Raster.createWritableRaster(newSampleModel, null); // Populate the new Raster. if(param != null && (param.getSourceXSubsampling() != 1 || param.getSourceXSubsampling() != 1)) { // Subsampling, possibly with sub-banding. reformat(getContiguousData(image, sourceRegion), sourceBands, param.getSourceXSubsampling(), param.getSourceYSubsampling(), newRaster); } else if(sourceBands == null && image.getSampleModel().getClass().isInstance (newSampleModel) && newSampleModel.getTransferType() == image.getSampleModel().getTransferType()) { // Neither subsampling nor sub-banding. WritableRaster translatedChild = newRaster.createWritableTranslatedChild(sourceRegion.x, sourceRegion.y); // Use copyData() to avoid potentially cobbling the entire // source region into an extra Raster via getData(). image.copyData(translatedChild); } else { // Cannot use copyData() so use getData() to retrieve and // possibly sub-band the source data and use setRect(). WritableRaster translatedChild = newRaster.createWritableTranslatedChild(sourceRegion.x, sourceRegion.y); Raster sourceRaster = getContiguousData(image, sourceRegion); if(sourceBands != null) { // Copy only the requested bands. sourceRaster = sourceRaster.createChild(sourceRegion.x, sourceRegion.y, sourceRegion.width, sourceRegion.height, sourceRegion.x, sourceRegion.y, sourceBands); } // Get the region from the image and set it into the Raster. translatedChild.setRect(sourceRaster); } // Replace Raster and SampleModel. raster = newRaster; sampleModel = newRaster.getSampleModel(); } else { // !reformatData // No reformatting needed. raster = getContiguousData(image, sourceRegion).createTranslatedChild(0, 0); sampleModel = raster.getSampleModel(); // Update mediaLibFormat indicator in case getContiguousData() // has changed the layout of the data. mediaLibFormat = getMediaLibFormat(sampleModel, image.getColorModel()); } // The mediaLib image. mediaLibImage mlibImage = null; // Create a mediaLibImage with reference to the Raster data. if(isBilevel) { // Bilevel image: either is was already bilevel or was // formatted to bilevel. MultiPixelPackedSampleModel mppsm = ((MultiPixelPackedSampleModel)sampleModel); // Get the line stride. int stride = mppsm.getScanlineStride(); // Determine the offset to the start of the data. int offset = raster.getDataBuffer().getOffset() - raster.getSampleModelTranslateY()*stride - raster.getSampleModelTranslateX()/8 + mppsm.getOffset(0, 0); // Get a reference to the internal data array. Object bitData = getDataBufferData(raster.getDataBuffer()); mlibImage = new mediaLibImage(mediaLibImage.MLIB_BIT, 1, raster.getWidth(), raster.getHeight(), stride, offset, (byte)mppsm.getBitOffset(0), bitData); } else { // If the image is not bilevel then it has to be component. ComponentSampleModel csm = (ComponentSampleModel)sampleModel; // Set the mediaLib data type int mlibDataType = getMediaLibDataType(sampleModel.getDataType()); // Get a reference to the internal data array. Object data = getDataBufferData(raster.getDataBuffer()); // Get the line stride. int stride = csm.getScanlineStride(); // Determine the offset of the first sample from the offset // indicated by the (x,y) coordinates. This offset is the // minimum valued offset, not the offset of, e.g., red (index 0) // as the Raster is by now in a contiguous format that // the encoder is guaranteed to handle regardless of whether // the smallest offset is to the, e.g., red band. int[] bandOffsets = csm.getBandOffsets(); int minBandOffset = bandOffsets[0]; for(int i = 1; i < bandOffsets.length; i++) { if(bandOffsets[i] < minBandOffset) { minBandOffset = bandOffsets[i]; } } // Determine the offset to the start of the data. The // sampleModelTranslate parameters are the translations from // Raster to SampleModel coordinates and must be subtracted // from the Raster coordinates. int offset = (raster.getMinY() - raster.getSampleModelTranslateY())*stride + (raster.getMinX() - raster.getSampleModelTranslateX())*numSourceBands + minBandOffset; // Create the image. mlibImage = !reformatData && mediaLibFormat != Constants.MLIB_FORMAT_UNKNOWN ? new mediaLibImage(mlibDataType, numSourceBands, raster.getWidth(), raster.getHeight(), stride, offset, mediaLibFormat, data) : new mediaLibImage(mlibDataType, numSourceBands, raster.getWidth(), raster.getHeight(), stride, offset, data); } return mlibImage; } } jai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/clib/CLibImageReader.java0000664000175100017510000007021710400724153032110 0ustar tilletille/* * $RCSfile: CLibImageReader.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.11 $ * $Date: 2006-02-28 01:33:31 $ * $State: Exp $ */ package com.sun.media.imageioimpl.plugins.clib; import java.awt.Point; import java.awt.Rectangle; import java.awt.Transparency; import java.awt.color.ColorSpace; import java.awt.geom.AffineTransform; import java.awt.image.AffineTransformOp; import java.awt.image.BufferedImage; import java.awt.image.ColorModel; import java.awt.image.ComponentColorModel; import java.awt.image.ComponentSampleModel; import java.awt.image.DataBuffer; import java.awt.image.DataBufferByte; import java.awt.image.DataBufferUShort; import java.awt.image.IndexColorModel; import java.awt.image.MultiPixelPackedSampleModel; import java.awt.image.PixelInterleavedSampleModel; import java.awt.image.Raster; import java.awt.image.SampleModel; import java.awt.image.WritableRaster; import java.io.InputStream; import java.io.IOException; import java.util.ArrayList; import java.util.Iterator; import java.util.NoSuchElementException; import javax.imageio.IIOException; import javax.imageio.ImageReader; import javax.imageio.ImageReadParam; import javax.imageio.ImageTypeSpecifier; import javax.imageio.metadata.IIOMetadata; import javax.imageio.spi.ImageReaderSpi; import javax.imageio.stream.ImageInputStream; import com.sun.medialib.codec.jiio.Constants; import com.sun.medialib.codec.jiio.mediaLibImage; // XXX Need to verify compliance of all methods with ImageReader specificaiton. public abstract class CLibImageReader extends ImageReader { // The current image index. private int currIndex = -1; // The position of the byte after the last byte read so far. private long highWaterMark = Long.MIN_VALUE; // An ArrayList of Longs indicating the stream // positions of the start of each image. Entries are added as needed. private ArrayList imageStartPosition = new ArrayList(); // The number of images in the stream, if known, otherwise -1. private int numImages = -1; // The image returned by the codecLib Decoder. private mediaLibImage mlibImage = null; // The index of the cached image. private int mlibImageIndex = -1; /** * Returns true if and only if both arguments are null or * both are non-null and have the same length and content. */ private static boolean subBandsMatch(int[] sourceBands, int[] destinationBands) { if(sourceBands == null && destinationBands == null) { return true; } else if(sourceBands != null && destinationBands != null) { if (sourceBands.length != destinationBands.length) { // Shouldn't happen ... return false; } for (int i = 0; i < sourceBands.length; i++) { if (sourceBands[i] != destinationBands[i]) { return false; } } return true; } return false; } /** * Creates a ImageTypeSpecifier corresponding to a * mediaLibImage. The mediaLibImage is * assumed always to be either bilevel-packed (MLIB_BIT) or * pixel interleaved in the order ((G|I)|RGB)[A] where 'I' indicates * an index as for palette images. */ protected static final ImageTypeSpecifier createImageType(mediaLibImage mlImage, ColorSpace colorSpace, int bitDepth, byte[] redPalette, byte[] greenPalette, byte[] bluePalette, byte[] alphaPalette) throws IOException { // Get the mediaLibImage attributes. int mlibType = mlImage.getType(); int mlibWidth = mlImage.getWidth(); int mlibHeight = mlImage.getHeight(); int mlibBands = mlImage.getChannels(); int mlibStride = mlImage.getStride(); // Convert mediaLib type to Java2D type. int dataType; switch(mlibType) { case Constants.MLIB_BIT: case Constants.MLIB_BYTE: dataType = DataBuffer.TYPE_BYTE; break; case Constants.MLIB_SHORT: case Constants.MLIB_USHORT: // Deliberately cast MLIB_SHORT to TYPE_USHORT. dataType = DataBuffer.TYPE_USHORT; break; default: throw new UnsupportedOperationException (I18N.getString("Generic0")+" "+mlibType); } // Set up the SampleModel. SampleModel sampleModel = null; if(mlibType == Constants.MLIB_BIT) { // Bilevel-packed sampleModel = new MultiPixelPackedSampleModel(dataType, mlibWidth, mlibHeight, 1, mlibStride, mlImage.getBitOffset()); } else { // Otherwise has to be interleaved in the order ((G|I)|RGB)[A]. int[] bandOffsets = new int[mlibBands]; for(int i = 0; i < mlibBands; i++) { bandOffsets[i] = i; } sampleModel = new PixelInterleavedSampleModel(dataType, mlibWidth, mlibHeight, mlibBands, mlibStride, bandOffsets); } // Set up the ColorModel. ColorModel colorModel = null; if(mlibBands == 1 && redPalette != null && greenPalette != null && bluePalette != null && redPalette.length == greenPalette.length && redPalette.length == bluePalette.length) { // Indexed image. int paletteLength = redPalette.length; if(alphaPalette != null) { if(alphaPalette.length != paletteLength) { byte[] alphaTmp = new byte[paletteLength]; if(alphaPalette.length > paletteLength) { System.arraycopy(alphaPalette, 0, alphaTmp, 0, paletteLength); } else { // alphaPalette.length < paletteLength System.arraycopy(alphaPalette, 0, alphaTmp, 0, alphaPalette.length); for(int i = alphaPalette.length; i < paletteLength; i++) { alphaTmp[i] = (byte)255; // Opaque. } } alphaPalette = alphaTmp; } colorModel = new IndexColorModel(bitDepth, //XXX 8 paletteLength, redPalette, greenPalette, bluePalette, alphaPalette); } else { colorModel = new IndexColorModel(bitDepth, //XXX 8 paletteLength, redPalette, greenPalette, bluePalette); } } else if(mlibType == Constants.MLIB_BIT) { // Bilevel image with no palette: assume black-is-zero. byte[] cmap = new byte[] { (byte)0x00, (byte)0xFF }; colorModel = new IndexColorModel(1, 2, cmap, cmap, cmap); } else { // Set the color space and the alpha flag. ColorSpace cs; boolean hasAlpha; if(colorSpace != null && (colorSpace.getNumComponents() == mlibBands || colorSpace.getNumComponents() == mlibBands - 1)) { // Use the provided ColorSpace. cs = colorSpace; // Set alpha if numBands == numColorComponents + 1. hasAlpha = colorSpace.getNumComponents() != mlibBands; } else { // RGB if more than 2 bands. cs = ColorSpace.getInstance(mlibBands < 3 ? ColorSpace.CS_GRAY : ColorSpace.CS_sRGB); // Alpha if band count is even. hasAlpha = mlibBands % 2 == 0; } // All bands have same depth. int[] bits = new int[mlibBands]; for(int i = 0; i < mlibBands; i++) { bits[i] = bitDepth; } colorModel = new ComponentColorModel(cs, bits, hasAlpha, false, hasAlpha ? Transparency.TRANSLUCENT : Transparency.OPAQUE, dataType); } return new ImageTypeSpecifier(colorModel, sampleModel); } private static final void subsample(Raster src, int subX, int subY, WritableRaster dst) { int sx0 = src.getMinX(); int sy0 = src.getMinY(); int sw = src.getWidth(); int syUB = sy0 + src.getHeight(); int dx0 = dst.getMinX(); int dy0 = dst.getMinY(); int dw = dst.getWidth(); int b = src.getSampleModel().getNumBands(); int t = src.getSampleModel().getDataType(); int numSubSamples = (sw + subX - 1)/subX; if(t == DataBuffer.TYPE_FLOAT || t == DataBuffer.TYPE_DOUBLE) { float[] fsamples = new float[sw]; float[] fsubsamples = new float[numSubSamples]; for(int k = 0; k < b; k++) { for(int sy = sy0, dy = dy0; sy < syUB; sy += subY, dy++) { src.getSamples(sx0, sy, sw, 1, k, fsamples); for(int i = 0, s = 0; i < sw; s++, i += subX) { fsubsamples[s] = fsamples[i]; } dst.setSamples(dx0, dy, dw, 1, k, fsubsamples); } } } else { int[] samples = new int[sw]; int[] subsamples = new int[numSubSamples]; for(int k = 0; k < b; k++) { for(int sy = sy0, dy = dy0; sy < syUB; sy += subY, dy++) { src.getSamples(sx0, sy, sw, 1, k, samples); for(int i = 0, s = 0; i < sw; s++, i += subX) { subsamples[s] = samples[i]; } dst.setSamples(dx0, dy, dw, 1, k, subsamples); } } } } protected CLibImageReader(ImageReaderSpi originatingProvider) { super(originatingProvider); } /** * An Iterator over a single element. */ private class SoloIterator implements Iterator { Object theObject; SoloIterator(Object o) { if(o == null) { new IllegalArgumentException (I18N.getString("CLibImageReader0")); } theObject = o; } public boolean hasNext() { return theObject != null; } public Object next() { if(theObject == null) { throw new NoSuchElementException(); } Object theNextObject = theObject; theObject = null; return theNextObject; } public void remove() { throw new UnsupportedOperationException(); } } // Stores the location of the image at the specified index in the // imageStartPosition List. private int locateImage(int imageIndex) throws IIOException { if (imageIndex < 0) { throw new IndexOutOfBoundsException("imageIndex < 0!"); } try { // Find closest known index (which can be -1 if none read before). int index = Math.min(imageIndex, imageStartPosition.size() - 1); ImageInputStream stream = (ImageInputStream)input; // Seek unless at beginning of stream if(index >= 0) { // index == -1 if(index == imageIndex) { // Seek to previously identified position and return. Long l = (Long)imageStartPosition.get(index); stream.seek(l.longValue()); return imageIndex; } else if(highWaterMark >= 0) { // index >= imageStartPosition.size() // Seek to first unread byte. stream.seek(highWaterMark); } } // Get the reader SPI. ImageReaderSpi provider = getOriginatingProvider(); // Search images until at desired index or last image found. do { try { if(provider.canDecodeInput(stream)) { // Append the image position. long offset = stream.getStreamPosition(); imageStartPosition.add(new Long(offset)); } else { return index; } } catch(IOException e) { // Ignore it. return index; } // Incrememt the index. if(++index == imageIndex) break; // Skip the image. if(!skipImage()) return index - 1; } while(true); } catch (IOException e) { throw new IIOException("IOException", e); } currIndex = imageIndex; return imageIndex; } // Verify that imageIndex is in bounds and find the image position. protected void seekToImage(int imageIndex) throws IIOException { // Check lower bound. if (imageIndex < minIndex) { throw new IndexOutOfBoundsException("imageIndex < minIndex!"); } // Update lower bound if cannot seek back. if (seekForwardOnly) { minIndex = imageIndex; } // Locate the image. int index = locateImage(imageIndex); // If the located is not the one sought => exception. if (index != imageIndex) { throw new IndexOutOfBoundsException("imageIndex out of bounds!"); } } /** * Skip the current image. If possible subclasses should override * this method with a more efficient implementation. * * @return Whether the image was successfully skipped. */ protected boolean skipImage() throws IOException { boolean retval = false; if(input == null) { throw new IllegalStateException("input == null"); } InputStream stream = null; if(input instanceof ImageInputStream) { stream = new InputStreamAdapter((ImageInputStream)input); } else { throw new IllegalArgumentException ("!(input instanceof ImageInputStream)"); } retval = decode(stream) != null; if(retval) { long pos = ((ImageInputStream)input).getStreamPosition(); if(pos > highWaterMark) { highWaterMark = pos; } } return retval; } /** * Decodes an image from the supplied InputStream. */ protected abstract mediaLibImage decode(InputStream stream) throws IOException; /** * Returns the value of the private mlibImage instance * variable initializing it first if it is null. */ protected synchronized mediaLibImage getImage(int imageIndex) throws IOException { if(mlibImage == null || imageIndex != mlibImageIndex) { if(input == null) { throw new IllegalStateException("input == null"); } seekToImage(imageIndex); InputStream stream = null; if(input instanceof ImageInputStream) { stream = new InputStreamAdapter((ImageInputStream)input); } else { throw new IllegalArgumentException ("!(input instanceof ImageInputStream)"); } mlibImage = decode(stream); if(mlibImage != null) { mlibImageIndex = imageIndex; long pos = ((ImageInputStream)input).getStreamPosition(); if(pos > highWaterMark) { highWaterMark = pos; } } else { // mlibImage == null mlibImageIndex = -1; } } return mlibImage; } /** * Returns the index of the image cached in the private * mlibImage instance variable or -1 if no * image is currently cached. */ protected int getImageIndex() { return mlibImageIndex; } public int getNumImages(boolean allowSearch) throws IOException { if (input == null) { throw new IllegalStateException("input == null"); } if (seekForwardOnly && allowSearch) { throw new IllegalStateException ("seekForwardOnly && allowSearch!"); } if (numImages > 0) { return numImages; } if (allowSearch) { this.numImages = locateImage(Integer.MAX_VALUE) + 1; } return numImages; } public int getWidth(int imageIndex) throws IOException { seekToImage(imageIndex); return getImage(imageIndex).getWidth(); } public int getHeight(int imageIndex) throws IOException { seekToImage(imageIndex); return getImage(imageIndex).getHeight(); } public IIOMetadata getStreamMetadata() throws IOException { return null; } public IIOMetadata getImageMetadata(int imageIndex) throws IOException { seekToImage(imageIndex); return null; } public synchronized BufferedImage read(int imageIndex, ImageReadParam param) throws IOException { processImageStarted(imageIndex); seekToImage(imageIndex); processImageProgress(0.0F); processImageProgress(0.5F); ImageTypeSpecifier rawImageType = getRawImageType(imageIndex); processImageProgress(0.95F); mediaLibImage mlImage = getImage(imageIndex); int dataOffset = mlImage.getOffset(); SampleModel rawSampleModel = rawImageType.getSampleModel(); DataBuffer db; int smType = rawSampleModel.getDataType(); switch(smType) { case DataBuffer.TYPE_BYTE: byte[] byteData = mlImage.getType() == mediaLibImage.MLIB_BIT ? mlImage.getBitData() : mlImage.getByteData(); db = new DataBufferByte(byteData, byteData.length - dataOffset, dataOffset); break; case DataBuffer.TYPE_USHORT: // Deliberately cast MLIB_SHORT to TYPE_USHORT. short[] shortData = mlImage.getShortData(); if(shortData == null) { shortData = mlImage.getUShortData(); } db = new DataBufferUShort(shortData, shortData.length - dataOffset, dataOffset); break; default: throw new UnsupportedOperationException (I18N.getString("Generic0")+" "+smType); } WritableRaster rawRaster = Raster.createWritableRaster(rawSampleModel, db, null); ColorModel rawColorModel = rawImageType.getColorModel(); BufferedImage image = new BufferedImage(rawColorModel, rawRaster, rawColorModel.isAlphaPremultiplied(), null); // XXX getDestination()? Rectangle destRegion = new Rectangle(image.getWidth(), image.getHeight()); int[] destinationBands = null; int subX = 1; int subY = 1; if(param != null) { BufferedImage destination = param.getDestination(); destinationBands = param.getDestinationBands(); Point destinationOffset = param.getDestinationOffset(); int[] sourceBands = param.getSourceBands(); Rectangle sourceRegion = param.getSourceRegion(); subX = param.getSourceXSubsampling(); subY = param.getSourceYSubsampling(); boolean isNominal = destination == null && destinationBands == null & destinationOffset.x == 0 && destinationOffset.y == 0 && sourceBands == null && sourceRegion == null && subX == 1 && subY == 1; if(!isNominal) { int srcWidth = image.getWidth(); int srcHeight = image.getHeight(); if(destination == null) { destination = getDestination(param, getImageTypes(imageIndex), srcWidth, srcHeight); } checkReadParamBandSettings(param, image.getSampleModel().getNumBands(), destination.getSampleModel().getNumBands()); Rectangle srcRegion = new Rectangle(); computeRegions(param, srcWidth, srcHeight, destination, srcRegion, destRegion); WritableRaster dst = destination.getWritableTile(0, 0).createWritableChild( destRegion.x, destRegion.y, destRegion.width, destRegion.height, destRegion.x, destRegion.y, destinationBands); if(subX != 1 || subY != 1) { // Subsampling WritableRaster src = image.getWritableTile(0, 0).createWritableChild( srcRegion.x, srcRegion.y, srcRegion.width, srcRegion.height, srcRegion.x, srcRegion.y, sourceBands); subsample(src, subX, subY, dst); } else { // No subsampling WritableRaster src = image.getWritableTile(0, 0).createWritableChild( srcRegion.x, srcRegion.y, srcRegion.width, srcRegion.height, destRegion.x, destRegion.y, sourceBands); dst.setRect(src); } image = destination; } else if(param.getDestinationType() != null) { // Check for image type other than raw image type. ImageTypeSpecifier destImageType = param.getDestinationType(); ColorSpace rawColorSpace = rawColorModel.getColorSpace(); ColorSpace destColorSpace = destImageType.getColorModel().getColorSpace(); if(!destColorSpace.equals(rawColorSpace) || !destImageType.equals(rawImageType)) { // Look for destination type in legal types list. Iterator imageTypes = getImageTypes(imageIndex); boolean isLegalType = false; while(imageTypes.hasNext()) { ImageTypeSpecifier imageType = (ImageTypeSpecifier)imageTypes.next(); if(imageType.equals(destImageType)) { isLegalType = true; break; } } if(isLegalType) { // Set the destination raster. WritableRaster raster; if(rawSampleModel.equals(destImageType.getSampleModel())) { // Re-use the raw raster. raster = rawRaster; } else { // Create a new raster and copy the data. SampleModel sm = destImageType.getSampleModel(); raster = Raster.createWritableRaster(sm, null); raster.setRect(rawRaster); } // Replace the output image. ColorModel cm = destImageType.getColorModel(); image = new BufferedImage(cm, raster, cm.isAlphaPremultiplied(), null); } } } } processImageUpdate(image, destRegion.x, destRegion.y, destRegion.width, destRegion.height, subX, subY, destinationBands); processImageProgress(1.0F); processImageComplete(); return image; } public void reset() { resetLocal(); super.reset(); } protected void resetLocal() { currIndex = -1; highWaterMark = Long.MIN_VALUE; imageStartPosition.clear(); numImages = -1; mlibImage = null; mlibImageIndex = -1; } public void setInput(Object input, boolean seekForwardOnly, boolean ignoreMetadata) { super.setInput(input, seekForwardOnly, ignoreMetadata); if (input != null) { // Check the class type. if (!(input instanceof ImageInputStream)) { throw new IllegalArgumentException ("!(input instanceof ImageInputStream)"); } } resetLocal(); } } jai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/clib/I18N.java0000664000175100017510000000420710203036165027664 0ustar tilletille/* * $RCSfile: I18N.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.1 $ * $Date: 2005-02-11 05:01:27 $ * $State: Exp $ */ package com.sun.media.imageioimpl.plugins.clib; import com.sun.media.imageioimpl.common.I18NImpl; final class I18N extends I18NImpl { static String getString(String key) { return getString("com.sun.media.imageioimpl.plugins.clib.I18N", key); } } jai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/pnm/0000775000175100017510000000000011650556211026226 5ustar tilletillejai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/pnm/PNMImageWriter.java0000664000175100017510000006236110203036165031665 0ustar tilletille/* * $RCSfile: PNMImageWriter.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.1 $ * $Date: 2005-02-11 05:01:40 $ * $State: Exp $ */ package com.sun.media.imageioimpl.plugins.pnm; import java.awt.Point; import java.awt.Rectangle; import java.awt.color.ColorSpace; import java.awt.image.ColorModel; import java.awt.image.ComponentSampleModel; import java.awt.image.DataBuffer; import java.awt.image.DataBufferByte; import java.awt.image.IndexColorModel; import java.awt.image.MultiPixelPackedSampleModel; import java.awt.image.Raster; import java.awt.image.RenderedImage; import java.awt.image.SampleModel; import java.awt.image.WritableRaster; import java.io.IOException; import java.util.Iterator; import javax.imageio.IIOImage; import javax.imageio.IIOException; import javax.imageio.ImageTypeSpecifier; import javax.imageio.ImageWriteParam; import javax.imageio.ImageWriter; import javax.imageio.metadata.IIOMetadata; import javax.imageio.metadata.IIOMetadataNode; import javax.imageio.metadata.IIOMetadataFormatImpl; import javax.imageio.metadata.IIOInvalidTreeException; import javax.imageio.spi.ImageWriterSpi; import javax.imageio.stream.ImageOutputStream; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import com.sun.media.imageio.plugins.pnm.PNMImageWriteParam; import com.sun.media.imageioimpl.common.ImageUtil; /** * The Java Image IO plugin writer for encoding a binary RenderedImage into * a PNM format. * * The encoding process may clip, subsample using the parameters * specified in the ImageWriteParam. * * @see com.sun.media.imageio.plugins.PNMImageWriteParam */ public class PNMImageWriter extends ImageWriter { private static final int PBM_ASCII = '1'; private static final int PGM_ASCII = '2'; private static final int PPM_ASCII = '3'; private static final int PBM_RAW = '4'; private static final int PGM_RAW = '5'; private static final int PPM_RAW = '6'; private static final int SPACE = ' '; private static final String COMMENT = "# written by com.sun.media.imageioimpl.PNMImageWriter"; private static byte[] lineSeparator; private int variant; private int maxValue; static { if (lineSeparator == null) { String ls = (String)java.security.AccessController.doPrivileged( new sun.security.action.GetPropertyAction("line.separator")); lineSeparator = ls.getBytes(); } } /** The output stream to write into */ private ImageOutputStream stream = null; /** Constructs PNMImageWriter based on the provided * ImageWriterSpi. */ public PNMImageWriter(ImageWriterSpi originator) { super(originator); } public void setOutput(Object output) { super.setOutput(output); // validates output if (output != null) { if (!(output instanceof ImageOutputStream)) throw new IllegalArgumentException(I18N.getString("PNMImageWriter0")); this.stream = (ImageOutputStream)output; } else this.stream = null; } public ImageWriteParam getDefaultWriteParam() { return new PNMImageWriteParam(); } public IIOMetadata getDefaultStreamMetadata(ImageWriteParam param) { return null; } public IIOMetadata getDefaultImageMetadata(ImageTypeSpecifier imageType, ImageWriteParam param) { return new PNMMetadata(imageType, param); } public IIOMetadata convertStreamMetadata(IIOMetadata inData, ImageWriteParam param) { return null; } public IIOMetadata convertImageMetadata(IIOMetadata inData, ImageTypeSpecifier imageType, ImageWriteParam param) { // Check arguments. if(inData == null) { throw new IllegalArgumentException("inData == null!"); } if(imageType == null) { throw new IllegalArgumentException("imageType == null!"); } PNMMetadata outData = null; // Obtain a PNMMetadata object. if(inData instanceof PNMMetadata) { // Clone the input metadata. outData = (PNMMetadata)((PNMMetadata)inData).clone(); } else { try { outData = new PNMMetadata(inData); } catch(IIOInvalidTreeException e) { // XXX Warning outData = new PNMMetadata(); } } // Update the metadata per the image type and param. outData.initialize(imageType, param); return outData; } public boolean canWriteRasters() { return true; } public void write(IIOMetadata streamMetadata, IIOImage image, ImageWriteParam param) throws IOException { clearAbortRequest(); processImageStarted(0); if (param == null) param = getDefaultWriteParam(); RenderedImage input = null; Raster inputRaster = null; boolean writeRaster = image.hasRaster(); Rectangle sourceRegion = param.getSourceRegion(); SampleModel sampleModel = null; ColorModel colorModel = null; if (writeRaster) { inputRaster = image.getRaster(); sampleModel = inputRaster.getSampleModel(); if (sourceRegion == null) sourceRegion = inputRaster.getBounds(); else sourceRegion = sourceRegion.intersection(inputRaster.getBounds()); } else { input = image.getRenderedImage(); sampleModel = input.getSampleModel(); colorModel = input.getColorModel(); Rectangle rect = new Rectangle(input.getMinX(), input.getMinY(), input.getWidth(), input.getHeight()); if (sourceRegion == null) sourceRegion = rect; else sourceRegion = sourceRegion.intersection(rect); } if (sourceRegion.isEmpty()) throw new RuntimeException(I18N.getString("PNMImageWrite1")); ImageUtil.canEncodeImage(this, colorModel, sampleModel); int scaleX = param.getSourceXSubsampling(); int scaleY = param.getSourceYSubsampling(); int xOffset = param.getSubsamplingXOffset(); int yOffset = param.getSubsamplingYOffset(); sourceRegion.translate(xOffset, yOffset); sourceRegion.width -= xOffset; sourceRegion.height -= yOffset; int minX = sourceRegion.x / scaleX; int minY = sourceRegion.y / scaleY; int w = (sourceRegion.width + scaleX - 1) / scaleX; int h = (sourceRegion.height + scaleY - 1) / scaleY; Rectangle destinationRegion = new Rectangle(minX, minY, w, h); int tileHeight = sampleModel.getHeight(); int tileWidth = sampleModel.getWidth(); // Raw data can only handle bytes, everything greater must be ASCII. int[] sampleSize = sampleModel.getSampleSize(); int[] sourceBands = param.getSourceBands(); boolean noSubband = true; int numBands = sampleModel.getNumBands(); if (sourceBands != null) { sampleModel = sampleModel.createSubsetSampleModel(sourceBands); colorModel = null; noSubband = false; numBands = sampleModel.getNumBands(); } else { sourceBands = new int[numBands]; for (int i = 0; i < numBands; i++) sourceBands[i] = i; } // Colormap populated for non-bilevel IndexColorModel only. byte[] reds = null; byte[] greens = null; byte[] blues = null; // Flag indicating that PB data should be inverted before writing. boolean isPBMInverted = false; if (numBands == 1) { if (colorModel instanceof IndexColorModel) { IndexColorModel icm = (IndexColorModel)colorModel; int mapSize = icm.getMapSize(); if (mapSize < (1 << sampleSize[0])) throw new RuntimeException(I18N.getString("PNMImageWrite2")); if(sampleSize[0] == 1) { variant = PBM_RAW; // Set PBM inversion flag if 1 maps to a higher color // value than 0: PBM expects white-is-zero so if this // does not obtain then inversion needs to occur. isPBMInverted = icm.getRed(1) > icm.getRed(0); } else { variant = PPM_RAW; reds = new byte[mapSize]; greens = new byte[mapSize]; blues = new byte[mapSize]; icm.getReds(reds); icm.getGreens(greens); icm.getBlues(blues); } } else if (sampleSize[0] == 1) { variant = PBM_RAW; } else if (sampleSize[0] <= 8) { variant = PGM_RAW; } else { variant = PGM_ASCII; } } else if (numBands == 3) { if (sampleSize[0] <= 8 && sampleSize[1] <= 8 && sampleSize[2] <= 8) { // all 3 bands must be <= 8 variant = PPM_RAW; } else { variant = PPM_ASCII; } } else { throw new RuntimeException(I18N.getString("PNMImageWrite3")); } IIOMetadata inputMetadata = image.getMetadata(); ImageTypeSpecifier imageType; if(colorModel != null) { imageType = new ImageTypeSpecifier(colorModel, sampleModel); } else { int dataType = sampleModel.getDataType(); switch(numBands) { case 1: imageType = ImageTypeSpecifier.createGrayscale(sampleSize[0], dataType, false); break; case 3: ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_sRGB); imageType = ImageTypeSpecifier.createInterleaved(cs, new int[] {0, 1, 2}, dataType, false, false); break; default: throw new IIOException("Cannot encode image with "+ numBands+" bands!"); } } PNMMetadata metadata; if(inputMetadata != null) { // Convert metadata. metadata = (PNMMetadata)convertImageMetadata(inputMetadata, imageType, param); } else { // Use default. metadata = (PNMMetadata)getDefaultImageMetadata(imageType, param); } // Read parameters boolean isRawPNM; if(param instanceof PNMImageWriteParam) { isRawPNM = ((PNMImageWriteParam)param).getRaw(); } else { isRawPNM = metadata.isRaw(); } maxValue = metadata.getMaxValue(); for (int i = 0; i < sampleSize.length; i++) { int v = (1 << sampleSize[i]) - 1; if (v > maxValue) { maxValue = v; } } if (isRawPNM) { // Raw output is desired. int maxBitDepth = metadata.getMaxBitDepth(); if (!isRaw(variant) && maxBitDepth <= 8) { // Current variant is ASCII and the bit depth is acceptable // so convert to RAW variant by adding '3' to variant. variant += 0x3; } else if(isRaw(variant) && maxBitDepth > 8) { // Current variant is RAW and the bit depth it too large for // RAW so convert to ASCII. variant -= 0x3; } // Omitted cases are (variant == RAW && max <= 8) and // (variant == ASCII && max > 8) neither of which requires action. } else if(isRaw(variant)) { // Raw output is NOT desired so convert to ASCII variant -= 0x3; } // Write PNM file. stream.writeByte('P'); // magic value: 'P' stream.writeByte(variant); stream.write(lineSeparator); stream.write(COMMENT.getBytes()); // comment line // Write the comments provided in the metadata Iterator comments = metadata.getComments(); if(comments != null) { while(comments.hasNext()) { stream.write(lineSeparator); String comment = "# " + (String)comments.next(); stream.write(comment.getBytes()); } } stream.write(lineSeparator); writeInteger(stream, w); // width stream.write(SPACE); writeInteger(stream, h); // height // Write sample max value for non-binary images if ((variant != PBM_RAW) && (variant != PBM_ASCII)) { stream.write(lineSeparator); writeInteger(stream, maxValue); } // The spec allows a single character between the // last header value and the start of the raw data. if (variant == PBM_RAW || variant == PGM_RAW || variant == PPM_RAW) { stream.write('\n'); } // Set flag for optimal image writing case: row-packed data with // correct band order if applicable. boolean writeOptimal = false; if (variant == PBM_RAW && sampleModel.getTransferType() == DataBuffer.TYPE_BYTE && sampleModel instanceof MultiPixelPackedSampleModel) { MultiPixelPackedSampleModel mppsm = (MultiPixelPackedSampleModel)sampleModel; int originX = 0; if (writeRaster) originX = inputRaster.getMinX(); else originX = input.getMinX(); // Must have left-aligned bytes with unity bit stride. if(mppsm.getBitOffset((sourceRegion.x - originX) % tileWidth) == 0 && mppsm.getPixelBitStride() == 1 && scaleX == 1) writeOptimal = true; } else if ((variant == PGM_RAW || variant == PPM_RAW) && sampleModel instanceof ComponentSampleModel && !(colorModel instanceof IndexColorModel)) { ComponentSampleModel csm = (ComponentSampleModel)sampleModel; // Pixel stride must equal band count. if(csm.getPixelStride() == numBands && scaleX == 1) { writeOptimal = true; // Band offsets must equal band indices. if(variant == PPM_RAW) { int[] bandOffsets = csm.getBandOffsets(); for(int b = 0; b < numBands; b++) { if(bandOffsets[b] != b) { writeOptimal = false; break; } } } } } // Write using an optimal approach if possible. if(writeOptimal) { int bytesPerRow = variant == PBM_RAW ? (w + 7)/8 : w * sampleModel.getNumBands(); byte[] bdata = null; byte[] invertedData = new byte[bytesPerRow]; // Loop over tiles to minimize cobbling. for(int j = 0; j < sourceRegion.height; j++) { if (abortRequested()) break; Raster lineRaster = null; if (writeRaster) { lineRaster = inputRaster.createChild(sourceRegion.x, j, sourceRegion.width, 1, 0, 0, null); } else { lineRaster = input.getData(new Rectangle(sourceRegion.x, sourceRegion.y + j, w, 1)); lineRaster = lineRaster.createTranslatedChild(0, 0); } bdata = ((DataBufferByte)lineRaster.getDataBuffer()).getData(); sampleModel = lineRaster.getSampleModel(); int offset = 0; if (sampleModel instanceof ComponentSampleModel) { offset = ((ComponentSampleModel)sampleModel).getOffset(lineRaster.getMinX()-lineRaster.getSampleModelTranslateX(), lineRaster.getMinY()-lineRaster.getSampleModelTranslateY()); } else if (sampleModel instanceof MultiPixelPackedSampleModel) { offset = ((MultiPixelPackedSampleModel)sampleModel).getOffset(lineRaster.getMinX() - lineRaster.getSampleModelTranslateX(), lineRaster.getMinX()-lineRaster.getSampleModelTranslateY()); } if (isPBMInverted) { for(int k = offset, m = 0; m < bytesPerRow; k++, m++) invertedData[m] = (byte)~bdata[k]; bdata = invertedData; offset = 0; } stream.write(bdata, offset, bytesPerRow); processImageProgress(100.0F * j / sourceRegion.height); } // Write all buffered bytes and return. stream.flush(); if (abortRequested()) processWriteAborted(); else processImageComplete(); return; } // Buffer for 1 rows of original pixels int size = sourceRegion.width * numBands; int[] pixels = new int[size]; // Also allocate a buffer to hold the data to be written to the file, // so we can use array writes. byte[] bpixels = reds == null ? new byte[w * numBands] : new byte[w * 3]; // The index of the sample being written, used to // place a line separator after every 16th sample in // ASCII mode. Not used in raw mode. int count = 0; // Process line by line int lastRow = sourceRegion.y + sourceRegion.height; for (int row = sourceRegion.y; row < lastRow; row += scaleY) { if (abortRequested()) break; // Grab the pixels Raster src = null; if (writeRaster) src = inputRaster.createChild(sourceRegion.x, row, sourceRegion.width, 1, sourceRegion.x, row, sourceBands); else src = input.getData(new Rectangle(sourceRegion.x, row, sourceRegion.width, 1)); src.getPixels(sourceRegion.x, row, sourceRegion.width, 1, pixels); if (isPBMInverted) for (int i = 0; i < size; i += scaleX) bpixels[i] ^= 1; switch (variant) { case PBM_ASCII: case PGM_ASCII: for (int i = 0; i < size; i += scaleX) { if ((count++ % 16) == 0) stream.write(lineSeparator); else stream.write(SPACE); writeInteger(stream, pixels[i]); } stream.write(lineSeparator); break; case PPM_ASCII: if (reds == null) { // no need to expand int[] bandOffset = ((ComponentSampleModel)sampleModel).getBandOffsets(); for (int i = 0; i < size; i += scaleX * numBands) { for (int j = 0; j < numBands; j++) { if ((count++ % 16) == 0) stream.write(lineSeparator); else stream.write(SPACE); writeInteger(stream, pixels[i + j]); } } } else { for (int i = 0; i < size; i += scaleX) { if ((count++ % 5) == 0) stream.write(lineSeparator); else stream.write(SPACE); writeInteger(stream, (reds[pixels[i]] & 0xFF)); stream.write(SPACE); writeInteger(stream, (greens[pixels[i]] & 0xFF)); stream.write(SPACE); writeInteger(stream, (blues[pixels[i]] & 0xFF)); } } stream.write(lineSeparator); break; case PBM_RAW: // 8 pixels packed into 1 byte, the leftovers are padded. int kdst = 0; int ksrc = 0; int b = 0; int pos = 7; for (int i = 0; i < size; i += scaleX) { b |= pixels[i] << pos; pos--; if (pos == -1) { bpixels[kdst++] = (byte)b; b = 0; pos = 7; } } if (pos != 7) bpixels[kdst++] = (byte)b; stream.write(bpixels, 0, kdst); break; case PGM_RAW: for (int i = 0, j = 0; i < size; i += scaleX) { bpixels[j++] = (byte)(pixels[i]); } stream.write(bpixels, 0, w); break; case PPM_RAW: if (reds == null) { // no need to expand for (int i = 0, k = 0; i < size; i += scaleX * numBands) { for (int j = 0; j < numBands; j++) bpixels[k++] = (byte)(pixels[i + j] & 0xFF); } } else { for (int i = 0, j = 0; i < size; i += scaleX) { bpixels[j++] = reds[pixels[i]]; bpixels[j++] = greens[pixels[i]]; bpixels[j++] = blues[pixels[i]]; } } stream.write(bpixels, 0, bpixels.length); break; } processImageProgress(100.0F * (row - sourceRegion.y) / sourceRegion.height); } // Force all buffered bytes to be written out. stream.flush(); if (abortRequested()) processWriteAborted(); else processImageComplete(); } public void reset() { super.reset(); stream = null; } /** Writes an integer to the output in ASCII format. */ private void writeInteger(ImageOutputStream output, int i) throws IOException { output.write(Integer.toString(i).getBytes()); } /** Writes a byte to the output in ASCII format. */ private void writeByte(ImageOutputStream output, byte b) throws IOException { output.write(Byte.toString(b).getBytes()); } /** Returns true if file variant is raw format, false if ASCII. */ private boolean isRaw(int v) { return (v >= PBM_RAW); } } jai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/pnm/PNMImageWriterSpi.java0000664000175100017510000001032710413303155032333 0ustar tilletille/* * $RCSfile: PNMImageWriterSpi.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.2 $ * $Date: 2006-03-31 19:43:40 $ * $State: Exp $ */ package com.sun.media.imageioimpl.plugins.pnm; import java.awt.image.DataBuffer; import javax.imageio.spi.ImageWriterSpi; import javax.imageio.spi.ServiceRegistry; import javax.imageio.spi.IIORegistry; import javax.imageio.ImageWriter; import javax.imageio.ImageTypeSpecifier; import javax.imageio.IIOException; import java.util.Locale; import com.sun.media.imageio.plugins.pnm.PNMImageWriteParam; import com.sun.media.imageioimpl.common.PackageUtil; public class PNMImageWriterSpi extends ImageWriterSpi { private static String [] readerSpiNames = {"com.sun.media.imageioimpl.plugins.pnm.PNMImageReaderSpi"}; private static String[] formatNames = {"pnm", "PNM"}; private static String[] entensions = {"pbm", "pgm", "ppm"}; private static String[] mimeType = {"image/x-portable-anymap", "image/x-portable-bitmap", "image/x-portable-graymap", "image/x-portable-pixmap"}; private boolean registered = false; public PNMImageWriterSpi() { super(PackageUtil.getVendor(), PackageUtil.getVersion(), formatNames, entensions, mimeType, "com.sun.media.imageioimpl.plugins.pnm.PNMImageWriter", STANDARD_OUTPUT_TYPE, readerSpiNames, true, null, null, null, null, true, null, null, null, null); } public String getDescription(Locale locale) { String desc = PackageUtil.getSpecificationTitle() + " PNM Image Writer"; return desc; } public void onRegistration(ServiceRegistry registry, Class category) { if (registered) { return; } registered = true; } public boolean canEncodeImage(ImageTypeSpecifier type) { int dataType = type.getSampleModel().getDataType(); if ((dataType < DataBuffer.TYPE_BYTE) || (dataType > DataBuffer.TYPE_INT)) return false; int numBands = type.getSampleModel().getNumBands(); if (numBands != 1 && numBands != 3) return false; return true; } public ImageWriter createWriterInstance(Object extension) throws IIOException { return new PNMImageWriter(this); } } jai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/pnm/PNMImageReaderSpi.java0000664000175100017510000001025710413303155032263 0ustar tilletille/* * $RCSfile: PNMImageReaderSpi.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.2 $ * $Date: 2006-03-31 19:43:40 $ * $State: Exp $ */ package com.sun.media.imageioimpl.plugins.pnm; import java.util.Locale; import javax.imageio.spi.ImageReaderSpi; import javax.imageio.stream.ImageInputStream; import javax.imageio.spi.IIORegistry; import javax.imageio.spi.ServiceRegistry; import java.io.IOException; import javax.imageio.ImageReader; import javax.imageio.IIOException; import com.sun.media.imageioimpl.common.PackageUtil; public class PNMImageReaderSpi extends ImageReaderSpi { private static String [] writerSpiNames = {"com.sun.media.imageioimpl.plugins.pnm.PNMImageWriterSpi"}; private static String[] formatNames = {"pnm", "PNM"}; private static String[] entensions = {"pbm", "pgm", "ppm"}; private static String[] mimeType = {"image/x-portable-anymap", "image/x-portable-bitmap", "image/x-portable-graymap", "image/x-portable-pixmap"}; private boolean registered = false; public PNMImageReaderSpi() { super(PackageUtil.getVendor(), PackageUtil.getVersion(), formatNames, entensions, mimeType, "com.sun.media.imageioimpl.plugins.pnm.PNMImageReader", STANDARD_INPUT_TYPE, writerSpiNames, true, null, null, null, null, true, null, null, null, null); } public void onRegistration(ServiceRegistry registry, Class category) { if (registered) { return; } registered = true; } public String getDescription(Locale locale) { String desc = PackageUtil.getSpecificationTitle() + " PNM Image Reader"; return desc; } public boolean canDecodeInput(Object source) throws IOException { if (!(source instanceof ImageInputStream)) { return false; } ImageInputStream stream = (ImageInputStream)source; byte[] b = new byte[2]; stream.mark(); stream.readFully(b); stream.reset(); return (b[0] == 0x50) && (b[1] >= 0x31) && (b[1] <= 0x36); } public ImageReader createReaderInstance(Object extension) throws IIOException { return new PNMImageReader(this); } } jai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/pnm/PNMMetadata.java0000664000175100017510000005154610203036165031171 0ustar tilletille/* * $RCSfile: PNMMetadata.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.1 $ * $Date: 2005-02-11 05:01:41 $ * $State: Exp $ */ package com.sun.media.imageioimpl.plugins.pnm; import java.io.InputStream; import javax.imageio.ImageTypeSpecifier; import javax.imageio.ImageWriteParam; import javax.imageio.ImageWriter; import javax.imageio.IIOException; import javax.imageio.stream.ImageInputStream; import javax.imageio.stream.ImageOutputStream; import javax.imageio.metadata.IIOMetadata; import javax.imageio.metadata.IIOMetadataNode; import javax.imageio.metadata.IIOMetadataFormat; import javax.imageio.metadata.IIOMetadataFormatImpl; import javax.imageio.metadata.IIOInvalidTreeException; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.w3c.dom.NamedNodeMap; import java.util.List; import java.util.ArrayList; import java.util.Arrays; import java.util.Hashtable; import java.util.Iterator; import java.util.ListIterator; import java.util.StringTokenizer; import java.io.IOException; import java.awt.color.ICC_Profile; import java.awt.color.ICC_ColorSpace; import java.awt.color.ColorSpace; import java.awt.image.ColorModel; import java.awt.image.DataBuffer; import java.awt.image.IndexColorModel; import java.awt.image.SampleModel; import java.awt.Point; import com.sun.media.imageio.plugins.pnm.PNMImageWriteParam; import com.sun.media.imageioimpl.common.ImageUtil; /** * Metadata for the PNM plug-in. */ public class PNMMetadata extends IIOMetadata implements Cloneable { static final String nativeMetadataFormatName = "com_sun_media_imageio_plugins_pnm_image_1.0"; /** The max value for the encoded/decoded image. */ private int maxSample; /** The image width. */ private int width; /** The image height. */ private int height; /** The image variants. */ private int variant; /** The comments. */ private ArrayList comments; /** Maximum number of bits per sample (not in metadata). */ private int maxSampleSize; /** * Constructor containing code shared by other constructors. */ PNMMetadata() { super(true, // Supports standard format nativeMetadataFormatName, // and a native format "com.sun.media.imageioimpl.plugins.pnm.PNMMetadataFormat", null, null); // No other formats } public PNMMetadata(IIOMetadata metadata) throws IIOInvalidTreeException { this(); if(metadata != null) { List formats = Arrays.asList(metadata.getMetadataFormatNames()); if(formats.contains(nativeMetadataFormatName)) { // Initialize from native image metadata format. setFromTree(nativeMetadataFormatName, metadata.getAsTree(nativeMetadataFormatName)); } else if(metadata.isStandardMetadataFormatSupported()) { // Initialize from standard metadata form of the input tree. String format = IIOMetadataFormatImpl.standardMetadataFormatName; setFromTree(format, metadata.getAsTree(format)); } } } /** * Constructs a default image PNMMetadata object appropriate * for the given image type and write parameters. */ PNMMetadata(ImageTypeSpecifier imageType, ImageWriteParam param) { this(); initialize(imageType, param); } void initialize(ImageTypeSpecifier imageType, ImageWriteParam param) { ImageTypeSpecifier destType = null; if (param != null) { destType = param.getDestinationType(); if (destType == null) { destType = imageType; } } else { destType = imageType; } if (destType != null) { SampleModel sm = destType.getSampleModel(); int[] sampleSize = sm.getSampleSize(); this.width = sm.getWidth(); this.height = sm.getHeight(); for (int i = 0; i < sampleSize.length; i++) { if (sampleSize[i] > maxSampleSize) { maxSampleSize = sampleSize[i]; } } this.maxSample = (1 << maxSampleSize) - 1; boolean isRaw = true; // default value if(param instanceof PNMImageWriteParam) { isRaw = ((PNMImageWriteParam)param).getRaw(); } if (maxSampleSize == 1) variant = '1'; else if (sm.getNumBands() == 1) { variant = '2'; } else if (sm.getNumBands() == 3) { variant = '3'; } // Force to Raw if the sample size is small enough. if (variant <= '3' && isRaw && maxSampleSize <= 8) { variant += 0x3; } } } protected Object clone() { PNMMetadata theClone = null; try { theClone = (PNMMetadata) super.clone(); } catch (CloneNotSupportedException e) {} // won't happen if (comments != null) { int numComments = comments.size(); for(int i = 0; i < numComments; i++) { theClone.addComment((String)comments.get(i)); } } return theClone; } public Node getAsTree(String formatName) { if (formatName == null) { throw new IllegalArgumentException(I18N.getString("PNMMetadata0")); } if (formatName.equals(nativeMetadataFormatName)) { return getNativeTree(); } if (formatName.equals (IIOMetadataFormatImpl.standardMetadataFormatName)) { return getStandardTree(); } throw new IllegalArgumentException(I18N.getString("PNMMetadata1") + " " + formatName); } IIOMetadataNode getNativeTree() { IIOMetadataNode root = new IIOMetadataNode(nativeMetadataFormatName); IIOMetadataNode child = new IIOMetadataNode("FormatName"); child.setUserObject(getFormatName()); child.setNodeValue(getFormatName()); root.appendChild(child); child = new IIOMetadataNode("Variant"); child.setUserObject(getVariant()); child.setNodeValue(getVariant()); root.appendChild(child); child = new IIOMetadataNode("Width"); Object tmp = new Integer(width); child.setUserObject(tmp); child.setNodeValue(ImageUtil.convertObjectToString(tmp)); root.appendChild(child); child = new IIOMetadataNode("Height"); tmp = new Integer(height); child.setUserObject(tmp); child.setNodeValue(ImageUtil.convertObjectToString(tmp)); root.appendChild(child); child = new IIOMetadataNode("MaximumSample"); tmp = new Byte((byte)maxSample); child.setUserObject(tmp); child.setNodeValue(ImageUtil.convertObjectToString(new Integer(maxSample))); root.appendChild(child); if(comments != null) { for (int i = 0; i < comments.size(); i++) { child = new IIOMetadataNode("Comment"); tmp = comments.get(i); child.setUserObject(tmp); child.setNodeValue(ImageUtil.convertObjectToString(tmp)); root.appendChild(child); } } return root; } // Standard tree node methods protected IIOMetadataNode getStandardChromaNode() { IIOMetadataNode node = new IIOMetadataNode("Chroma"); int temp = (variant - '1') % 3 + 1; IIOMetadataNode subNode = new IIOMetadataNode("ColorSpaceType"); if (temp == 3) { subNode.setAttribute("name", "RGB"); } else { subNode.setAttribute("name", "GRAY"); } node.appendChild(subNode); subNode = new IIOMetadataNode("NumChannels"); subNode.setAttribute("value", "" + (temp == 3 ? 3 : 1)); node.appendChild(subNode); if(temp != 3) { subNode = new IIOMetadataNode("BlackIsZero"); subNode.setAttribute("value", "TRUE"); node.appendChild(subNode); } return node; } protected IIOMetadataNode getStandardDataNode() { IIOMetadataNode node = new IIOMetadataNode("Data"); IIOMetadataNode subNode = new IIOMetadataNode("SampleFormat"); subNode.setAttribute("value", "UnsignedIntegral"); node.appendChild(subNode); int temp = (variant - '1') % 3 + 1; subNode = new IIOMetadataNode("BitsPerSample"); if(temp == 1) { subNode.setAttribute("value", "1"); } else if(temp == 2) { subNode.setAttribute("value", "8"); } else { subNode.setAttribute("value", "8 8 8"); } node.appendChild(subNode); subNode = new IIOMetadataNode("SignificantBitsPerSample"); if(temp == 1 || temp == 2) { subNode.setAttribute("value", "" + maxSampleSize); } else { subNode.setAttribute("value", maxSampleSize + " " + maxSampleSize + " " + maxSampleSize); } node.appendChild(subNode); return node; } protected IIOMetadataNode getStandardDimensionNode() { IIOMetadataNode node = new IIOMetadataNode("Dimension"); IIOMetadataNode subNode = new IIOMetadataNode("ImageOrientation"); subNode.setAttribute("value", "Normal"); node.appendChild(subNode); return node; } protected IIOMetadataNode getStandardTextNode() { if(comments != null) { IIOMetadataNode node = new IIOMetadataNode("Text"); Iterator iter = comments.iterator(); while(iter.hasNext()) { String comment = (String)iter.next(); IIOMetadataNode subNode = new IIOMetadataNode("TextEntry"); subNode.setAttribute("keyword", "comment"); subNode.setAttribute("value", comment); node.appendChild(subNode); } return node; } return null; } public boolean isReadOnly() { return false; } public void mergeTree(String formatName, Node root) throws IIOInvalidTreeException { if (formatName == null) { throw new IllegalArgumentException(I18N.getString("PNMMetadata0")); } if (root == null) { throw new IllegalArgumentException(I18N.getString("PNMMetadata2")); } if (formatName.equals(nativeMetadataFormatName) && root.getNodeName().equals(nativeMetadataFormatName)) { mergeNativeTree(root); } else if (formatName.equals (IIOMetadataFormatImpl.standardMetadataFormatName)) { mergeStandardTree(root); } else { throw new IllegalArgumentException(I18N.getString("PNMMetadata1") + " " + formatName); } } public void setFromTree(String formatName, Node root) throws IIOInvalidTreeException { if (formatName == null) { throw new IllegalArgumentException(I18N.getString("PNMMetadata0")); } if (root == null) { throw new IllegalArgumentException(I18N.getString("PNMMetadata2")); } if (formatName.equals(nativeMetadataFormatName) && root.getNodeName().equals(nativeMetadataFormatName)) { mergeNativeTree(root); } else if (formatName.equals (IIOMetadataFormatImpl.standardMetadataFormatName)) { mergeStandardTree(root); } else { throw new IllegalArgumentException(I18N.getString("PNMMetadata2") + " " + formatName); } } public void reset() { maxSample = width = height = variant = maxSampleSize = 0; comments = null; } public String getFormatName() { int v = (variant - '1') % 3 + 1; if (v == 1) return "PBM"; if (v == 2) return "PGM"; if (v == 3) return "PPM"; return null; } public String getVariant() { if (variant > '3') return "RAWBITS"; return "ASCII"; } boolean isRaw() { return getVariant().equals("RAWBITS"); } /** Sets the variant: '1' - '6'. */ public void setVariant(int v) { this.variant = v; } public void setWidth(int w) { this.width = w; } public void setHeight(int h) { this.height = h; } int getMaxBitDepth() { return maxSampleSize; } int getMaxValue() { return maxSample; } /** Set the maximum sample size and maximum sample value. * @param maxValue The maximum sample value. This method computes the * maximum sample size. */ public void setMaxBitDepth(int maxValue) { this.maxSample = maxValue; this.maxSampleSize = 0; while(maxValue > 0) { maxValue >>>= 1; maxSampleSize++; } } public synchronized void addComment(String comment) { if (comments == null) { comments = new ArrayList(); } comment = comment.replaceAll("[\n\r\f]", " "); comments.add(comment); } Iterator getComments() { return comments == null ? null : comments.iterator(); } private void mergeNativeTree(Node root) throws IIOInvalidTreeException { NodeList list = root.getChildNodes(); String format = null; String var = null; for (int i = list.getLength() - 1; i >= 0; i--) { IIOMetadataNode node = (IIOMetadataNode)list.item(i); String name = node.getNodeName(); if (name.equals("Comment")) { addComment((String)node.getUserObject()); } else if (name.equals("Width")) { this.width = ((Integer)node.getUserObject()).intValue(); } else if (name.equals("Height")) { this.width = ((Integer)node.getUserObject()).intValue(); } else if (name.equals("MaximumSample")) { int maxValue = ((Integer)node.getUserObject()).intValue(); setMaxBitDepth(maxValue); } else if (name.equals("FormatName")) { format = (String)node.getUserObject(); } else if (name.equals("Variant")) { var = (String)node.getUserObject(); } } if (format.equals("PBM")) variant = '1'; else if (format.equals("PGM")) variant = '2'; else if (format.equals("PPM")) variant = '3'; if (var.equals("RAWBITS")) variant += 3; } private void mergeStandardTree(Node root) throws IIOInvalidTreeException { NodeList children = root.getChildNodes(); String colorSpace = null; int numComps = 0; int[] bitsPerSample = null; for (int i = 0; i < children.getLength(); i++) { Node node = children.item(i); String name = node.getNodeName(); if (name.equals("Chroma")) { NodeList children1 = node.getChildNodes(); for (int j = 0; j < children1.getLength(); j++) { Node child = children1.item(j); String name1 = child.getNodeName(); if (name1.equals("NumChannels")) { String s = (String)getAttribute(child, "value"); numComps = new Integer(s).intValue(); } else if (name1.equals("ColorSpaceType")) { colorSpace = (String)getAttribute(child, "name"); } } } else if (name.equals("Compression")) { // Do nothing. } else if (name.equals("Data")) { NodeList children1 = node.getChildNodes(); int maxBitDepth = -1; for (int j = 0; j < children1.getLength(); j++) { Node child = children1.item(j); String name1 = child.getNodeName(); if (name1.equals("BitsPerSample")) { List bps = new ArrayList(3); String s = (String)getAttribute(child, "value"); StringTokenizer t = new StringTokenizer(s); while(t.hasMoreTokens()) { bps.add(Integer.valueOf(t.nextToken())); } bitsPerSample = new int[bps.size()]; for(int k = 0; k < bitsPerSample.length; k++) { bitsPerSample[k] = ((Integer)bps.get(k)).intValue(); } } else if (name1.equals("SignificantBitsPerSample")) { String s = (String)getAttribute(child, "value"); StringTokenizer t = new StringTokenizer(s); while(t.hasMoreTokens()) { int sbps = Integer.valueOf(t.nextToken()).intValue(); maxBitDepth = Math.max(sbps, maxBitDepth); } } } // Set maximum bit depth and value. if(maxBitDepth > 0) { setMaxBitDepth((1 << maxBitDepth) - 1); } else if(bitsPerSample != null) { for(int k = 0; k < bitsPerSample.length; k++) { if(bitsPerSample[k] > maxBitDepth) { maxBitDepth = bitsPerSample[k]; } } setMaxBitDepth((1 << maxBitDepth) - 1); } } else if (name.equals("Dimension")) { // Do nothing. } else if (name.equals("Document")) { // Do nothing. } else if (name.equals("Text")) { NodeList children1 = node.getChildNodes(); for (int j = 0; j < children1.getLength(); j++) { Node child = children1.item(j); String name1 = child.getNodeName(); if (name1.equals("TextEntry")) { addComment((String)getAttribute(child, "value")); } } } else if (name.equals("Transparency")) { // Do nothing. } else { throw new IIOInvalidTreeException(I18N.getString("PNMMetadata3") + " " + name, node); } } // Go from higher to lower: PPM > PGM > PBM. if((colorSpace != null && colorSpace.equals("RGB")) || numComps > 1 || bitsPerSample.length > 1) { variant = '3'; } else if(maxSampleSize > 1) { variant = '2'; } else { variant = '1'; } } public Object getAttribute(Node node, String name) { NamedNodeMap map = node.getAttributes(); node = map.getNamedItem(name); return (node != null) ? node.getNodeValue() : null; } } jai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/pnm/PNMMetadataFormat.java0000664000175100017510000001107210203036165032330 0ustar tilletille/* * $RCSfile: PNMMetadataFormat.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.1 $ * $Date: 2005-02-11 05:01:41 $ * $State: Exp $ */ package com.sun.media.imageioimpl.plugins.pnm; import java.util.Hashtable; import javax.imageio.metadata.*; import javax.imageio.ImageTypeSpecifier; public class PNMMetadataFormat extends IIOMetadataFormatImpl { /** The table to link the child to its parent. */ private static Hashtable parents = new Hashtable(); static { //children for the root parents.put("FormatName", "com_sun_media_imageio_plugins_pnm_image_1.0"); parents.put("Variant", "com_sun_media_imageio_plugins_pnm_image_1.0"); parents.put("Width", "com_sun_media_imageio_plugins_pnm_image_1.0"); parents.put("Height", "com_sun_media_imageio_plugins_pnm_image_1.0"); parents.put("MaximumSample", "com_sun_media_imageio_plugins_pnm_image_1.0"); parents.put("Comment", "com_sun_media_imageio_plugins_pnm_image_1.0"); } private static PNMMetadataFormat instance; public static synchronized PNMMetadataFormat getInstance() { if (instance == null) instance = new PNMMetadataFormat(); return instance; } String resourceBaseName = this.getClass().getName() + "Resources"; /** Constructs PNMMetadataFormat. Calls the super * class constructor. Sets the resource base name. Adds the elements * into this format object based on the XML schema and DTD. */ PNMMetadataFormat() { super("com_sun_media_imageio_plugins_pnm_image_1.0", CHILD_POLICY_ALL); setResourceBaseName(resourceBaseName); addElements(); } /** Adds the elements into this format object based on the XML * schema and DTD. */ private void addElements() { addElement("FormatName", getParent("FormatName"), CHILD_POLICY_EMPTY); addElement("Variant", getParent("Variant"), CHILD_POLICY_EMPTY); addElement("Width", getParent("Width"), CHILD_POLICY_EMPTY); addElement("Height", getParent("Height"), CHILD_POLICY_EMPTY); addElement("MaximumSample", getParent("MaximumSample"), CHILD_POLICY_EMPTY); addElement("Comment", getParent("Comment"), CHILD_POLICY_EMPTY); } public String getParent(String elementName) { return (String)parents.get(elementName); } public boolean canNodeAppear(String elementName, ImageTypeSpecifier imageType) { if (getParent(elementName) != null) return true; return false; } } ././@LongLink0000000000000000000000000000015500000000000011566 Lustar rootrootjai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/pnm/PNMMetadataFormatResources.javajai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/pnm/PNMMetadataFormatResour0000664000175100017510000000476510203036165032623 0ustar tilletille/* * $RCSfile: PNMMetadataFormatResources.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.1 $ * $Date: 2005-02-11 05:01:41 $ * $State: Exp $ */ package com.sun.media.imageioimpl.plugins.pnm; import java.util.*; public class PNMMetadataFormatResources extends ListResourceBundle { static final Object[][] contents = { {"FormatName", "The format name. One of PBM, PGM or PPM"}, {"Variant", "The variant: RAWBITS or ASCII"}, {"Width", "The image width"}, {"Height", "The image height"}, {"MaximumSample", "The maximum bit depth of one sample."}, {"Comment", "A comment."} }; public PNMMetadataFormatResources() { } protected Object[][] getContents() { return contents; } } jai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/pnm/properties0000664000175100017510000000151310203036165030337 0ustar tilletille# # $RCSfile: properties,v $ # # Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved. # # Use is subject to license terms. # # $Revision: 1.1 $ # $Date: 2005-02-11 05:01:41 $ # $State: Exp $ # # Internationalization file for com.sun.media.imageioimpl.plugins.pnm PNMImageReader0=What in the stream isn't a PNM image. PNMImageReader1=Only support to decode the first image in PNM stream. PNMImageWriter0=The provided output is not an ImageOutputStream. PNMImageWriter1=The image region to be encoded is empty. PNMImageWriter2=Wrong color index. PNMImageWriter3=Cannot encode this image. PNMImageWriter4=Only byte/short/ushort/int types are supported. PNMMetadata0=The provided metadata format is null. PNMMetadata1=The provided metadata format isn't recognized. PNMMetadata2=The tree to be merged is null. PNMMetadata3=Invalid node jai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/pnm/PNMImageReader.java0000664000175100017510000010064010203036165031604 0ustar tilletille/* * $RCSfile: PNMImageReader.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.1 $ * $Date: 2005-02-11 05:01:40 $ * $State: Exp $ */ package com.sun.media.imageioimpl.plugins.pnm; import java.awt.Point; import java.awt.Rectangle; import java.awt.Transparency; import java.awt.color.ColorSpace; import java.awt.image.BufferedImage; import java.awt.image.ColorModel; import java.awt.image.ComponentColorModel; import java.awt.image.ComponentSampleModel; import java.awt.image.DataBuffer; import java.awt.image.DataBufferByte; import java.awt.image.DataBufferInt; import java.awt.image.DataBufferUShort; import java.awt.image.IndexColorModel; import java.awt.image.MultiPixelPackedSampleModel; import java.awt.image.PixelInterleavedSampleModel; import java.awt.image.Raster; import java.awt.image.SampleModel; import java.awt.image.WritableRaster; import javax.imageio.IIOException; import javax.imageio.ImageReader; import javax.imageio.ImageReadParam; import javax.imageio.ImageTypeSpecifier; import javax.imageio.metadata.IIOMetadata; import javax.imageio.spi.ImageReaderSpi; import javax.imageio.stream.ImageInputStream; import java.io.*; import java.util.ArrayList; import java.util.Iterator; import java.util.StringTokenizer; import com.sun.media.imageioimpl.common.ImageUtil; /** This class is the Java Image IO plugin reader for PNM images. * It may subsample the image, clip the image, select sub-bands, * and shift the decoded image origin if the proper decoding parameter * are set in the provided PNMImageReadParam. */ public class PNMImageReader extends ImageReader { private static final int PBM_ASCII = '1'; private static final int PGM_ASCII = '2'; private static final int PPM_ASCII = '3'; private static final int PBM_RAW = '4'; private static final int PGM_RAW = '5'; private static final int PPM_RAW = '6'; private static final int LINE_FEED = 0x0A; private static byte[] lineSeparator; static { if (lineSeparator == null) { String ls = (String)java.security.AccessController.doPrivileged( new sun.security.action.GetPropertyAction("line.separator")); lineSeparator = ls.getBytes(); } } /** File variant: PBM/PGM/PPM, ASCII/RAW. */ private int variant; /** Maximum pixel value. */ private int maxValue; /** The input stream where reads from */ private ImageInputStream iis = null; /** Indicates whether the header is read. */ private boolean gotHeader = false; /** The stream position where the image data starts. */ private long imageDataOffset; /** The original image width. */ private int width; /** The original image height. */ private int height; private String aLine; private StringTokenizer token; private PNMMetadata metadata; /** Constructs PNMImageReader from the provided * ImageReaderSpi. */ public PNMImageReader(ImageReaderSpi originator) { super(originator); } /** Overrides the method defined in the superclass. */ public void setInput(Object input, boolean seekForwardOnly, boolean ignoreMetadata) { super.setInput(input, seekForwardOnly, ignoreMetadata); iis = (ImageInputStream) input; // Always works } /** Overrides the method defined in the superclass. */ public int getNumImages(boolean allowSearch) throws IOException { return 1; } public int getWidth(int imageIndex) throws IOException { checkIndex(imageIndex); readHeader(); return width; } public int getHeight(int imageIndex) throws IOException { checkIndex(imageIndex); readHeader(); return height; } public int getVariant() { return variant; } public int getMaxValue() { return maxValue; } private void checkIndex(int imageIndex) { if (imageIndex != 0) { throw new IndexOutOfBoundsException(I18N.getString("PNMImageReader1")); } } public synchronized void readHeader() throws IOException { if (gotHeader) { // Seek to where the image data starts, since that is where // the stream pointer should be after header is read iis.seek(imageDataOffset); return; } if (iis != null) { if (iis.readByte() != 'P') { // magic number throw new RuntimeException(I18N.getString("PNMImageReader0")); } variant = iis.readByte(); // file variant if ((variant < PBM_ASCII) || (variant > PPM_RAW)) { throw new RuntimeException(I18N.getString("PNMImageReader0")); } // Create the metadata object. metadata = new PNMMetadata(); // Set the variant. metadata.setVariant(variant); // Read the line separator. iis.readLine(); readComments(iis, metadata); width = readInteger(iis); // width height = readInteger(iis); // height if (variant == PBM_ASCII || variant == PBM_RAW) { maxValue = 1; } else { maxValue = readInteger(iis); // maximum value } metadata.setWidth(width); metadata.setHeight(height); metadata.setMaxBitDepth(maxValue); gotHeader = true; // Store the stream position where the image data starts imageDataOffset = iis.getStreamPosition(); } } public Iterator getImageTypes(int imageIndex) throws IOException { checkIndex(imageIndex); readHeader(); int tmp = (variant - '1') % 3 ; ArrayList list = new ArrayList(1); int dataType = DataBuffer.TYPE_INT; // Determine data type based on maxValue. if (maxValue < 0x100) { dataType = DataBuffer.TYPE_BYTE; } else if (maxValue < 0x10000) { dataType = DataBuffer.TYPE_USHORT; } // Choose an appropriate SampleModel. SampleModel sampleModel = null; ColorModel colorModel = null; if ((variant == PBM_ASCII) || (variant == PBM_RAW)) { // Each pixel takes 1 bit, pack 8 pixels into a byte. sampleModel = new MultiPixelPackedSampleModel( DataBuffer.TYPE_BYTE, width, height, 1); byte[] color = {(byte)0xFF, (byte)0}; colorModel = new IndexColorModel(1, 2, color, color, color); } else { sampleModel = new PixelInterleavedSampleModel(dataType, width, height, tmp == 1 ? 1 : 3, width * (tmp == 1 ? 1 : 3), tmp == 1 ? new int[]{0} : new int[]{0, 1, 2}); colorModel = ImageUtil.createColorModel(null, sampleModel); } list.add(new ImageTypeSpecifier(colorModel, sampleModel)); return list.iterator(); } public ImageReadParam getDefaultReadParam() { return new ImageReadParam(); } public IIOMetadata getImageMetadata(int imageIndex) throws IOException { checkIndex(imageIndex); readHeader(); return metadata; } public IIOMetadata getStreamMetadata() throws IOException { return null; } public boolean isRandomAccessEasy(int imageIndex) throws IOException { checkIndex(imageIndex); return true; } public BufferedImage read(int imageIndex, ImageReadParam param) throws IOException { checkIndex(imageIndex); clearAbortRequest(); processImageStarted(imageIndex); if (param == null) param = getDefaultReadParam(); //read header readHeader(); Rectangle sourceRegion = new Rectangle(0, 0, 0, 0); Rectangle destinationRegion = new Rectangle(0, 0, 0, 0); computeRegions(param, this.width, this.height, param.getDestination(), sourceRegion, destinationRegion); int scaleX = param.getSourceXSubsampling(); int scaleY = param.getSourceYSubsampling(); // If the destination band is set used it int[] sourceBands = param.getSourceBands(); int[] destBands = param.getDestinationBands(); boolean seleBand = (sourceBands != null) && (destBands != null); boolean noTransform = destinationRegion.equals(new Rectangle(0, 0, width, height)) || seleBand; // The RAWBITS format can only support byte image data, which means // maxValue should be less than 0x100. In case there's a conflict, // base the maxValue on variant. if (isRaw(variant) && maxValue >= 0x100) { maxValue = 0xFF; } int numBands = 1; // Determine number of bands: pixmap (PPM) is 3 bands, // bitmap (PBM) and greymap (PGM) are 1 band. if (variant == PPM_ASCII || variant == PPM_RAW) { numBands = 3; } if (!seleBand) { sourceBands = new int[numBands]; destBands = new int[numBands]; for (int i = 0; i < numBands; i++) destBands[i] = sourceBands[i] = i; } int dataType = DataBuffer.TYPE_INT; // Determine data type based on maxValue. if (maxValue < 0x100) { dataType = DataBuffer.TYPE_BYTE; } else if (maxValue < 0x10000) { dataType = DataBuffer.TYPE_USHORT; } // Choose an appropriate SampleModel. SampleModel sampleModel = null; ColorModel colorModel = null; if ((variant == PBM_ASCII) || (variant == PBM_RAW)) { // Each pixel takes 1 bit, pack 8 pixels into a byte. sampleModel = new MultiPixelPackedSampleModel( DataBuffer.TYPE_BYTE, destinationRegion.width, destinationRegion.height, 1); byte[] color = {(byte)0xFF, (byte)0}; colorModel = new IndexColorModel(1, 2, color, color, color); } else { sampleModel = new PixelInterleavedSampleModel(dataType, destinationRegion.width, destinationRegion.height, sourceBands.length, destinationRegion.width * sourceBands.length, destBands); colorModel = ImageUtil.createColorModel(null, sampleModel); } // If the destination is provided, then use it. Otherwise, create new // one BufferedImage bi = param.getDestination(); // Get the image data. WritableRaster raster = null; if (bi == null) { sampleModel = sampleModel.createCompatibleSampleModel( destinationRegion.x + destinationRegion.width, destinationRegion.y + destinationRegion.height); if (seleBand) sampleModel = sampleModel.createSubsetSampleModel(sourceBands); raster = Raster.createWritableRaster(sampleModel, new Point()); bi = new BufferedImage(colorModel, raster, false, null); } else { raster = bi.getWritableTile(0, 0); sampleModel = bi.getSampleModel(); colorModel = bi.getColorModel(); noTransform &= destinationRegion.equals(raster.getBounds()); } switch (variant) { case PBM_RAW: { // SampleModel for these cases should be MultiPixelPacked. DataBuffer dataBuffer = raster.getDataBuffer(); // Read the entire image. byte[] buf = ((DataBufferByte)dataBuffer).getData(); if (noTransform) { iis.readFully(buf, 0, buf.length); processImageUpdate(bi, 0, 0, width, height, 1, 1, destBands); processImageProgress(100.0F); } else if (scaleX == 1 && sourceRegion.x % 8 == 0) { int skip = sourceRegion.x >> 3; int originalLS = width + 7 >> 3; int destLS = raster.getWidth() + 7 >> 3; int readLength = sourceRegion.width + 7 >> 3; int offset = sourceRegion.y * originalLS; iis.skipBytes(offset + skip); offset = originalLS * (scaleY - 1) + originalLS - readLength; byte[] lineData = new byte[readLength]; int bitoff = destinationRegion.x & 7; boolean reformat = !(bitoff == 0); for (int i = 0, j = 0, k = destinationRegion.y * destLS + (destinationRegion.x >> 3); i < destinationRegion.height; i++, j += scaleY) { if (reformat) { iis.read(lineData, 0, readLength); int mask1 = (255 << bitoff) & 255; int mask2 = ~mask1 & 255; int shift = 8 - bitoff; int n = 0; int m = k; for (; n < readLength -1; n++, m++) buf[m] = (byte)(((lineData[n] & mask2) << shift) | (lineData[n + 1] & mask1) >>bitoff); buf[m] = (byte)((lineData[n] & mask2) << shift); } else { iis.read(buf, k, readLength); } iis.skipBytes(offset); k += destLS; processImageUpdate(bi, 0, i, destinationRegion.width, 1, 1, 1, destBands); processImageProgress(100.0F*i/destinationRegion.height); } } else { int originalLS = width + 7 >> 3; byte[] data = new byte[originalLS]; iis.skipBytes(sourceRegion.y * originalLS); int destLS = bi.getWidth() + 7 >> 3; int offset = originalLS * (scaleY - 1); int dsx = destLS * destinationRegion.y + (destinationRegion.x >> 3); for (int i = 0, j = 0, n = dsx; i < destinationRegion.height; i++, j += scaleY) { iis.read(data, 0, originalLS); iis.skipBytes(offset); int b = 0; int pos = 7 - (destinationRegion.x & 7); for (int m = sourceRegion.x; m < sourceRegion.x + sourceRegion.width; m += scaleX) { b |= (data[m >> 3] >> (7 - (m & 7)) & 1) << pos; pos--; if (pos == -1) { buf[n++] = (byte)b; b = 0; pos = 7; } } if (pos != 7) buf[n++] = (byte)b; n += destinationRegion.x >> 3; processImageUpdate(bi, 0, i, destinationRegion.width, 1, 1, 1, destBands); processImageProgress(100.0F*i/destinationRegion.height); } } break; } case PBM_ASCII: { DataBuffer dataBuffer = raster.getDataBuffer(); byte[] buf = ((DataBufferByte)dataBuffer).getData(); if (noTransform) for (int i = 0, n = 0; i < height; i++) { int b = 0; int pos = 7; for (int j = 0; j < width; j++) { b |= (readInteger(iis) & 1) << pos; pos--; if (pos == -1 ) { buf[n++] = (byte)b; b = 0; pos = 7; } } if (pos != 7) buf[n++] = (byte)b; processImageUpdate(bi, 0, i, width, 1, 1, 1, destBands); processImageProgress(100.0F * i / height); } else { skipInteger(iis, sourceRegion.y * width + sourceRegion.x); int skipX = scaleX - 1; int skipY = (scaleY - 1) * width + width - destinationRegion.width * scaleX; int dsx = (bi.getWidth() + 7 >> 3) * destinationRegion.y + (destinationRegion.x >> 3); for (int i = 0, n = dsx; i < destinationRegion.height; i++) { int b = 0; int pos = 7 - (destinationRegion.x & 7); for (int j = 0; j < destinationRegion.width; j++) { b |= (readInteger(iis) & 1) << pos; pos--; if (pos == -1 ) { buf[n++] = (byte)b; b = 0; pos = 7; } skipInteger(iis, skipX); } if (pos != 7) buf[n++] = (byte)b; n += destinationRegion.x >> 3; skipInteger(iis, skipY); processImageUpdate(bi, 0, i, destinationRegion.width, 1, 1, 1, destBands); processImageProgress(100.0F*i/destinationRegion.height); } } break; } case PGM_ASCII: case PGM_RAW: case PPM_ASCII: case PPM_RAW: // SampleModel for these cases should be PixelInterleaved. int skipX = (scaleX - 1) * numBands; int skipY = (scaleY * width - destinationRegion.width * scaleX) * numBands; int dsx = (bi.getWidth() * destinationRegion. y + destinationRegion.x) * numBands; switch (dataType) { case DataBuffer.TYPE_BYTE: DataBufferByte bbuf = (DataBufferByte)raster.getDataBuffer(); byte[] byteArray = bbuf.getData(); if (isRaw(variant)) { if (noTransform) { iis.readFully(byteArray); processImageUpdate(bi, 0, 0, width, height, 1, 1, destBands); processImageProgress(100.0F); } else { iis.skipBytes(sourceRegion.y * width * numBands); int skip = (scaleY - 1) * width * numBands; byte[] data = new byte[width * numBands]; int pixelStride = scaleX * numBands; int sx = sourceRegion.x * numBands; int ex = width; for (int i = 0, n = dsx ; i < destinationRegion.height; i++) { iis.read(data); for (int j = sourceRegion.x, k = sx; j < sourceRegion.x + sourceRegion.width; j+= scaleX, k += pixelStride) { for (int m = 0; m < sourceBands.length; m++) byteArray[n+ destBands[m]] = data[k + sourceBands[m]]; n += sourceBands.length; } n += destinationRegion.x * numBands; iis.skipBytes(skip); processImageUpdate(bi, 0, i, destinationRegion.width, 1, 1, 1, destBands); processImageProgress(100.0F*i/destinationRegion.height); } } } else { skipInteger(iis, (sourceRegion.y * width + sourceRegion.x) * numBands); if (seleBand) { byte[] data = new byte[numBands]; for (int i = 0, n = dsx; i < destinationRegion.height; i++) { for (int j = 0; j < destinationRegion.width; j++) { for (int k = 0; k < numBands; k++) data[k] = (byte)readInteger(iis); for (int k = 0; k < sourceBands.length; k++) byteArray[n+destBands[k]] = data[sourceBands[k]]; n += sourceBands.length; skipInteger(iis, skipX); } n += destinationRegion.x * sourceBands.length; skipInteger(iis, skipY); processImageUpdate(bi, 0, i, destinationRegion.width, 1, 1, 1, destBands); processImageProgress(100.0F*i/destinationRegion.height); } } else for (int i = 0, n = dsx; i < destinationRegion.height; i++) { for (int j = 0; j < destinationRegion.width; j++) { for (int k = 0; k < numBands; k++) byteArray[n++] = (byte)readInteger(iis); skipInteger(iis, skipX); } n += destinationRegion.x * sourceBands.length; skipInteger(iis, skipY); processImageUpdate(bi, 0, i, destinationRegion.width, 1, 1, 1, destBands); processImageProgress(100.0F*i/destinationRegion.height); } } break; case DataBuffer.TYPE_USHORT: DataBufferUShort sbuf = (DataBufferUShort)raster.getDataBuffer(); short[] shortArray = sbuf.getData(); skipInteger(iis, sourceRegion.y * width * numBands + sourceRegion.x); if (seleBand) { short[] data = new short[numBands]; for (int i = 0, n = dsx; i < destinationRegion.height; i++) { for (int j = 0; j < destinationRegion.width; j++) { for (int k = 0; k < numBands; k++) data[k] = (short)readInteger(iis); for (int k = 0; k < sourceBands.length; k++) shortArray[n+destBands[k]] = data[sourceBands[k]]; n += sourceBands.length; skipInteger(iis, skipX); } n += destinationRegion.x * sourceBands.length; skipInteger(iis, skipY); processImageUpdate(bi, 0, i, destinationRegion.width, 1, 1, 1, destBands); processImageProgress(100.0F*i/destinationRegion.height); } } else for (int i = 0, n = dsx; i < destinationRegion.height; i++) { for (int j = 0; j < destinationRegion.width; j++) { for (int k = 0; k < numBands; k++) shortArray[n++] = (short)readInteger(iis); skipInteger(iis, skipX); } n += destinationRegion.x * sourceBands.length; skipInteger(iis, skipY); processImageUpdate(bi, 0, i, destinationRegion.width, 1, 1, 1, destBands); processImageProgress(100.0F*i/destinationRegion.height); } break; case DataBuffer.TYPE_INT: DataBufferInt ibuf = (DataBufferInt)raster.getDataBuffer(); int[] intArray = ibuf.getData(); skipInteger(iis, sourceRegion.y * width * numBands + sourceRegion.x); if (seleBand) { int[] data = new int[numBands]; for (int i = 0, n = dsx; i < destinationRegion.height; i++) { for (int j = 0; j < destinationRegion.width; j++) { for (int k = 0; k < numBands; k++) data[k] = readInteger(iis); for (int k = 0; k < sourceBands.length; k++) intArray[n+destBands[k]] = data[sourceBands[k]]; n += sourceBands.length; skipInteger(iis, skipX); } n += destinationRegion.x * sourceBands.length; skipInteger(iis, skipY); processImageUpdate(bi, 0, i, destinationRegion.width, 1, 1, 1, destBands); processImageProgress(100.0F*i/destinationRegion.height); } } else for (int i = 0, n = dsx; i < destinationRegion.height; i++) { for (int j = 0; j < destinationRegion.width; j++) { for (int k = 0; k < numBands; k++) intArray[n++] = readInteger(iis); skipInteger(iis, skipX); } n += destinationRegion.x * sourceBands.length; skipInteger(iis, skipY); processImageUpdate(bi, 0, i, destinationRegion.width, 1, 1, 1, destBands); processImageProgress(100.0F*i/destinationRegion.height); } break; } break; } if (abortRequested()) processReadAborted(); else processImageComplete(); return bi; } public boolean canReadRaster() { return true; } public Raster readRaster(int imageIndex, ImageReadParam param) throws IOException { BufferedImage bi = read(imageIndex, param); return bi.getData(); } public void reset() { super.reset(); iis = null; gotHeader = false; System.gc(); } /** Returns true if file variant is raw format, false if ASCII. */ private boolean isRaw(int v) { return (v >= PBM_RAW); } /** Reads the comments. */ private void readComments(ImageInputStream stream, PNMMetadata metadata) throws IOException { String line = null; int pos = -1; stream.mark(); while ((line = stream.readLine()) != null && (pos = line.indexOf("#")) >= 0) { metadata.addComment(line.substring(pos + 1).trim()); } stream.reset(); } /** Reads the next integer. */ private int readInteger(ImageInputStream stream) throws IOException { boolean foundDigit = false; while (aLine == null) { aLine = stream.readLine(); if (aLine == null) return 0; int pos = aLine.indexOf("#"); if (pos == 0) aLine = null; else if (pos > 0) aLine = aLine.substring(0, pos - 1); if (aLine != null) token = new StringTokenizer(aLine); } while (token.hasMoreTokens()) { String s = token.nextToken(); try { return new Integer(s).intValue(); } catch (NumberFormatException e) { continue; } } if (!foundDigit) { aLine = null; return readInteger(stream); } return 0; } private void skipInteger(ImageInputStream stream, int num) throws IOException { for (int i = 0; i < num; i++) readInteger(stream); } } jai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/pnm/I18N.java0000664000175100017510000000420510203036165027543 0ustar tilletille/* * $RCSfile: I18N.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.1 $ * $Date: 2005-02-11 05:01:40 $ * $State: Exp $ */ package com.sun.media.imageioimpl.plugins.pnm; import com.sun.media.imageioimpl.common.I18NImpl; final class I18N extends I18NImpl { static String getString(String key) { return getString("com.sun.media.imageioimpl.plugins.pnm.I18N", key); } } jai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/bmp/0000775000175100017510000000000011650556211026212 5ustar tilletillejai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/bmp/BMPImageReaderSpi.java0000664000175100017510000001067310413303155032235 0ustar tilletille/* * $RCSfile: BMPImageReaderSpi.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.3 $ * $Date: 2006-03-31 19:43:38 $ * $State: Exp $ */ package com.sun.media.imageioimpl.plugins.bmp; import java.util.Locale; import javax.imageio.spi.ImageReaderSpi; import javax.imageio.stream.ImageInputStream; import javax.imageio.spi.IIORegistry; import javax.imageio.spi.ServiceRegistry; import java.io.IOException; import javax.imageio.ImageReader; import javax.imageio.IIOException; import com.sun.media.imageioimpl.common.PackageUtil; import com.sun.media.imageioimpl.common.ImageUtil; public class BMPImageReaderSpi extends ImageReaderSpi { private static String [] writerSpiNames = {"com.sun.media.imageioimpl.plugins.bmp.BMPImageWriterSpi"}; private static String[] formatNames = {"bmp", "BMP"}; private static String[] extensions = {"bmp"}; private static String[] mimeTypes = { "image/bmp", "image/x-bmp", "image/x-windows-bmp" }; private boolean registered = false; public BMPImageReaderSpi() { super(PackageUtil.getVendor(), PackageUtil.getVersion(), formatNames, extensions, mimeTypes, "com.sun.media.imageioimpl.plugins.bmp.BMPImageReader", STANDARD_INPUT_TYPE, writerSpiNames, false, null, null, null, null, true, BMPMetadata.nativeMetadataFormatName, "com.sun.media.imageioimpl.plugins.bmp.BMPMetadataFormat", null, null); } public void onRegistration(ServiceRegistry registry, Class category) { if (registered) { return; } registered = true; // By JDK 1.7, the BMPImageReader will have been in JDK core for // atleast two FCS releases, so we can set JIIO's to lower priority // With JDK 1.8, we can entirely de-register the JIIO one ImageUtil.processOnRegistration(registry, category, "BMP", this, 8, 7); // JDK version 1.8, 1.7 } public String getDescription(Locale locale) { String desc = PackageUtil.getSpecificationTitle() + " BMP Image Reader"; return desc; } public boolean canDecodeInput(Object source) throws IOException { if (!(source instanceof ImageInputStream)) { return false; } ImageInputStream stream = (ImageInputStream)source; byte[] b = new byte[2]; stream.mark(); stream.readFully(b); stream.reset(); return (b[0] == 0x42) && (b[1] == 0x4d); } public ImageReader createReaderInstance(Object extension) throws IIOException { return new BMPImageReader(this); } } jai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/bmp/BMPImageWriterSpi.java0000664000175100017510000001156510413303155032310 0ustar tilletille/* * $RCSfile: BMPImageWriterSpi.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.3 $ * $Date: 2006-03-31 19:43:38 $ * $State: Exp $ */ package com.sun.media.imageioimpl.plugins.bmp; import java.awt.image.DataBuffer; import java.awt.image.SampleModel; import java.awt.image.SinglePixelPackedSampleModel; import javax.imageio.spi.ImageWriterSpi; import javax.imageio.spi.ServiceRegistry; import javax.imageio.spi.IIORegistry; import javax.imageio.ImageWriter; import javax.imageio.ImageTypeSpecifier; import javax.imageio.IIOException; import java.util.Locale; import com.sun.media.imageio.plugins.bmp.BMPImageWriteParam; import com.sun.media.imageioimpl.common.PackageUtil; import com.sun.media.imageioimpl.common.ImageUtil; public class BMPImageWriterSpi extends ImageWriterSpi { private static String [] readerSpiNames = {"com.sun.media.imageioimpl.plugins.bmp.BMPImageReaderSpi"}; private static String[] formatNames = {"bmp", "BMP"}; private static String[] extensions = {"bmp"}; private static String[] mimeTypes = { "image/bmp", "image/x-bmp", "image/x-windows-bmp" }; private boolean registered = false; public BMPImageWriterSpi() { super(PackageUtil.getVendor(), PackageUtil.getVersion(), formatNames, extensions, mimeTypes, "com.sun.media.imageioimpl.plugins.bmp.BMPImageWriter", STANDARD_OUTPUT_TYPE, readerSpiNames, false, null, null, null, null, true, BMPMetadata.nativeMetadataFormatName, "com.sun.media.imageioimpl.plugins.bmp.BMPMetadataFormat", null, null); } public String getDescription(Locale locale) { String desc = PackageUtil.getSpecificationTitle() + " BMP Image Writer"; return desc; } public void onRegistration(ServiceRegistry registry, Class category) { if (registered) { return; } registered = true; // By JDK 1.7, the BMPImageWriter will have been in JDK core for // atleast two FCS releases, so we can set JIIO's to lower priority // With JDK 1.8, we can entirely de-register the JIIO one ImageUtil.processOnRegistration(registry, category, "BMP", this, 8, 7); // JDK version 1.8, 1.7 } public boolean canEncodeImage(ImageTypeSpecifier type) { int dataType= type.getSampleModel().getDataType(); if (dataType < DataBuffer.TYPE_BYTE || dataType > DataBuffer.TYPE_INT) return false; SampleModel sm = type.getSampleModel(); int numBands = sm.getNumBands(); if (!(numBands == 1 || numBands == 3)) return false; if (numBands == 1 && dataType != DataBuffer.TYPE_BYTE) return false; if (dataType > DataBuffer.TYPE_BYTE && !(sm instanceof SinglePixelPackedSampleModel)) return false; return true; } public ImageWriter createWriterInstance(Object extension) throws IIOException { return new BMPImageWriter(this); } } jai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/bmp/BMPMetadata.java0000664000175100017510000014003210422263535031134 0ustar tilletille/* * $RCSfile: BMPMetadata.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.2 $ * $Date: 2006-04-21 23:14:37 $ * $State: Exp $ */ package com.sun.media.imageioimpl.plugins.bmp; import java.io.UnsupportedEncodingException; import java.awt.image.ColorModel; import java.awt.image.DirectColorModel; import java.awt.image.IndexColorModel; import java.awt.image.SampleModel; import java.util.ArrayList; import java.util.Arrays; import java.util.Iterator; import java.util.List; import java.util.StringTokenizer; import javax.imageio.ImageTypeSpecifier; import javax.imageio.ImageWriteParam; import javax.imageio.metadata.IIOInvalidTreeException; import javax.imageio.metadata.IIOMetadata; import javax.imageio.metadata.IIOMetadataNode; import javax.imageio.metadata.IIOMetadataFormat; import javax.imageio.metadata.IIOMetadataFormatImpl; import org.w3c.dom.Node; import com.sun.media.imageio.plugins.bmp.BMPImageWriteParam; import com.sun.media.imageioimpl.common.ImageUtil; public class BMPMetadata extends IIOMetadata implements Cloneable, BMPConstants { public static final String nativeMetadataFormatName = "com_sun_media_imageio_plugins_bmp_image_1.0"; // Fields for Image Descriptor public String bmpVersion; public int width ; public int height; public short bitsPerPixel; public int compression; public int imageSize; // Fields for PixelsPerMeter public int xPixelsPerMeter; public int yPixelsPerMeter; public int colorsUsed; public int colorsImportant; // Fields for BI_BITFIELDS compression(Mask) public int redMask; public int greenMask; public int blueMask; public int alphaMask; public int colorSpace; // Fields for CIE XYZ for the LCS_CALIBRATED_RGB color space public double redX; public double redY; public double redZ; public double greenX; public double greenY; public double greenZ; public double blueX; public double blueY; public double blueZ; // Fields for Gamma values for the LCS_CALIBRATED_RGB color space public int gammaRed; public int gammaGreen; public int gammaBlue; public int intent; // Fields for the Palette and Entries public byte[] palette = null; public int paletteSize; public int red; public int green; public int blue; // Fields from CommentExtension // List of String public List comments = null; // new ArrayList(); public BMPMetadata() { super(true, nativeMetadataFormatName, "com.sun.media.imageioimpl.bmp.BMPMetadataFormat", null, null); } public BMPMetadata(IIOMetadata metadata) throws IIOInvalidTreeException { this(); if(metadata != null) { List formats = Arrays.asList(metadata.getMetadataFormatNames()); if(formats.contains(nativeMetadataFormatName)) { // Initialize from native image metadata format. setFromTree(nativeMetadataFormatName, metadata.getAsTree(nativeMetadataFormatName)); } else if(metadata.isStandardMetadataFormatSupported()) { // Initialize from standard metadata form of the input tree. String format = IIOMetadataFormatImpl.standardMetadataFormatName; setFromTree(format, metadata.getAsTree(format)); } } } public boolean isReadOnly() { return false; } public Object clone() { BMPMetadata metadata; try { metadata = (BMPMetadata)super.clone(); } catch (CloneNotSupportedException e) { return null; } return metadata; } public Node getAsTree(String formatName) { if (formatName.equals(nativeMetadataFormatName)) { return getNativeTree(); } else if (formatName.equals (IIOMetadataFormatImpl.standardMetadataFormatName)) { return getStandardTree(); } else { throw new IllegalArgumentException(I18N.getString("BMPMetadata0")); } } private Node getNativeTree() { IIOMetadataNode root = new IIOMetadataNode(nativeMetadataFormatName); addChildNode(root, "BMPVersion", bmpVersion); addChildNode(root, "Width", new Integer(width)); addChildNode(root, "Height", new Integer(height)); addChildNode(root, "BitsPerPixel", new Short(bitsPerPixel)); addChildNode(root, "Compression", new Integer(compression)); addChildNode(root, "ImageSize", new Integer(imageSize)); IIOMetadataNode node; if(xPixelsPerMeter > 0 && yPixelsPerMeter > 0) { node = addChildNode(root, "PixelsPerMeter", null); addChildNode(node, "X", new Integer(xPixelsPerMeter)); addChildNode(node, "Y", new Integer(yPixelsPerMeter)); } addChildNode(root, "ColorsUsed", new Integer(colorsUsed)); addChildNode(root, "ColorsImportant", new Integer(colorsImportant)); int version = 0; for (int i = 0; i < bmpVersion.length(); i++) if (Character.isDigit(bmpVersion.charAt(i))) version = bmpVersion.charAt(i) -'0'; if (version >= 4) { node = addChildNode(root, "Mask", null); addChildNode(node, "Red", new Integer(redMask)); addChildNode(node, "Green", new Integer(greenMask)); addChildNode(node, "Blue", new Integer(blueMask)); addChildNode(node, "Alpha", new Integer(alphaMask)); addChildNode(root, "ColorSpaceType", new Integer(colorSpace)); node = addChildNode(root, "CIEXYZEndpoints", null); addXYZPoints(node, "Red", redX, redY, redZ); addXYZPoints(node, "Green", greenX, greenY, greenZ); addXYZPoints(node, "Blue", blueX, blueY, blueZ); node = addChildNode(root, "Gamma", null); addChildNode(node, "Red", new Integer(gammaRed)); addChildNode(node, "Green", new Integer(gammaGreen)); addChildNode(node, "Blue", new Integer(gammaBlue)); node = addChildNode(root, "Intent", new Integer(intent)); } // Palette if ((palette != null) && (paletteSize > 0)) { node = addChildNode(root, "Palette", null); boolean isVersion2 = bmpVersion != null && bmpVersion.equals(VERSION_2); for (int i = 0, j = 0; i < paletteSize; i++) { IIOMetadataNode entry = addChildNode(node, "PaletteEntry", null); blue = palette[j++] & 0xff; green = palette[j++] & 0xff; red = palette[j++] & 0xff; addChildNode(entry, "Red", new Integer(red)); addChildNode(entry, "Green", new Integer(green)); addChildNode(entry, "Blue", new Integer(blue)); if(!isVersion2) j++; // skip reserved entry } } return root; } // Standard tree node methods protected IIOMetadataNode getStandardChromaNode() { IIOMetadataNode node = new IIOMetadataNode("Chroma"); IIOMetadataNode subNode = new IIOMetadataNode("ColorSpaceType"); String colorSpaceType; if (((palette != null) && (paletteSize > 0)) || (redMask != 0 || greenMask != 0 || blueMask != 0) || bitsPerPixel > 8) { colorSpaceType = "RGB"; } else { colorSpaceType = "GRAY"; } subNode.setAttribute("name", colorSpaceType); node.appendChild(subNode); subNode = new IIOMetadataNode("NumChannels"); String numChannels; if (((palette != null) && (paletteSize > 0)) || (redMask != 0 || greenMask != 0 || blueMask != 0) || bitsPerPixel > 8) { if(alphaMask != 0) { numChannels = "4"; } else { numChannels = "3"; } } else { numChannels = "1"; } subNode.setAttribute("value", numChannels); node.appendChild(subNode); if(gammaRed != 0 && gammaGreen != 0 && gammaBlue != 0) { subNode = new IIOMetadataNode("Gamma"); Double gamma = new Double((gammaRed+gammaGreen+gammaBlue)/3.0); subNode.setAttribute("value", gamma.toString()); node.appendChild(subNode); } if(numChannels.equals("1") && (palette == null || paletteSize == 0)) { subNode = new IIOMetadataNode("BlackIsZero"); subNode.setAttribute("value", "TRUE"); node.appendChild(subNode); } if ((palette != null) && (paletteSize > 0)) { subNode = new IIOMetadataNode("Palette"); boolean isVersion2 = bmpVersion != null && bmpVersion.equals(VERSION_2); for (int i = 0, j = 0; i < paletteSize; i++) { IIOMetadataNode subNode1 = new IIOMetadataNode("PaletteEntry"); subNode1.setAttribute("index", ""+i); subNode1.setAttribute("blue", "" + (palette[j++]&0xff)); subNode1.setAttribute("green", "" + (palette[j++]&0xff)); subNode1.setAttribute("red", "" + (palette[j++]&0xff)); if(!isVersion2) j++; // skip reserved entry subNode.appendChild(subNode1); } node.appendChild(subNode); } return node; } protected IIOMetadataNode getStandardCompressionNode() { IIOMetadataNode node = new IIOMetadataNode("Compression"); // CompressionTypeName IIOMetadataNode subNode = new IIOMetadataNode("CompressionTypeName"); subNode.setAttribute("value", compressionTypeNames[compression]); node.appendChild(subNode); subNode = new IIOMetadataNode("Lossless"); subNode.setAttribute("value", compression == BI_JPEG ? "FALSE" : "TRUE"); node.appendChild(subNode); return node; } protected IIOMetadataNode getStandardDataNode() { IIOMetadataNode node = new IIOMetadataNode("Data"); String sampleFormat = (palette != null) && (paletteSize > 0) ? "Index" : "UnsignedIntegral"; IIOMetadataNode subNode = new IIOMetadataNode("SampleFormat"); subNode.setAttribute("value", sampleFormat); node.appendChild(subNode); String bits = ""; if(redMask != 0 || greenMask != 0 || blueMask != 0) { bits = countBits(redMask) + " " + countBits(greenMask) + " " + countBits(blueMask); if(alphaMask != 0) { bits += " " + countBits(alphaMask); } } else if(palette != null && paletteSize > 0) { for(int i = 1; i <= 3; i++) { bits += bitsPerPixel; if(i != 3) { bits += " "; } } } else { if (bitsPerPixel == 1) { bits = "1"; } else if (bitsPerPixel == 4) { bits = "4"; } else if (bitsPerPixel == 8) { bits = "8"; } else if (bitsPerPixel == 16) { bits = "5 6 5"; } else if (bitsPerPixel == 24) { bits = "8 8 8"; } else if ( bitsPerPixel == 32) { bits = "8 8 8 8"; } } if(!bits.equals("")) { subNode = new IIOMetadataNode("BitsPerSample"); subNode.setAttribute("value", bits); node.appendChild(subNode); } return node; } protected IIOMetadataNode getStandardDimensionNode() { if (yPixelsPerMeter > 0 && xPixelsPerMeter > 0) { IIOMetadataNode node = new IIOMetadataNode("Dimension"); float ratio = (float)yPixelsPerMeter / (float)xPixelsPerMeter; IIOMetadataNode subNode = new IIOMetadataNode("PixelAspectRatio"); subNode.setAttribute("value", "" + ratio); node.appendChild(subNode); subNode = new IIOMetadataNode("HorizontalPixelSize"); subNode.setAttribute("value", "" + (1000.0F / xPixelsPerMeter)); node.appendChild(subNode); subNode = new IIOMetadataNode("VerticalPixelSize"); subNode.setAttribute("value", "" + (1000.0F / yPixelsPerMeter)); node.appendChild(subNode); // Emit HorizontalPhysicalPixelSpacing and // VerticalPhysicalPixelSpacing for historical reasonse: // HorizontalPixelSize and VerticalPixelSize should have // been used in the first place. subNode = new IIOMetadataNode("HorizontalPhysicalPixelSpacing"); subNode.setAttribute("value", "" + (1000.0F / xPixelsPerMeter)); node.appendChild(subNode); subNode = new IIOMetadataNode("VerticalPhysicalPixelSpacing"); subNode.setAttribute("value", "" + (1000.0F / yPixelsPerMeter)); node.appendChild(subNode); return node; } return null; } protected IIOMetadataNode getStandardDocumentNode() { if(bmpVersion != null) { IIOMetadataNode node = new IIOMetadataNode("Document"); IIOMetadataNode subNode = new IIOMetadataNode("FormatVersion"); subNode.setAttribute("value", bmpVersion); node.appendChild(subNode); return node; } return null; } protected IIOMetadataNode getStandardTextNode() { if(comments != null) { IIOMetadataNode node = new IIOMetadataNode("Text"); Iterator iter = comments.iterator(); while(iter.hasNext()) { String comment = (String)iter.next(); IIOMetadataNode subNode = new IIOMetadataNode("TextEntry"); subNode.setAttribute("keyword", "comment"); subNode.setAttribute("value", comment); node.appendChild(subNode); } return node; } return null; } protected IIOMetadataNode getStandardTransparencyNode() { IIOMetadataNode node = new IIOMetadataNode("Transparency"); IIOMetadataNode subNode = new IIOMetadataNode("Alpha"); String alpha; if(alphaMask != 0) { alpha = "nonpremultiplied"; } else { alpha = "none"; } subNode.setAttribute("value", alpha); node.appendChild(subNode); return node; } // Shorthand for throwing an IIOInvalidTreeException private void fatal(Node node, String reason) throws IIOInvalidTreeException { throw new IIOInvalidTreeException(reason, node); } // Get an integer-valued attribute private int getIntAttribute(Node node, String name, int defaultValue, boolean required) throws IIOInvalidTreeException { String value = getAttribute(node, name, null, required); if (value == null) { return defaultValue; } return Integer.parseInt(value); } // Get a double-valued attribute private double getDoubleAttribute(Node node, String name, double defaultValue, boolean required) throws IIOInvalidTreeException { String value = getAttribute(node, name, null, required); if (value == null) { return defaultValue; } return Double.parseDouble(value); } // Get a required integer-valued attribute private int getIntAttribute(Node node, String name) throws IIOInvalidTreeException { return getIntAttribute(node, name, -1, true); } // Get a required double-valued attribute private double getDoubleAttribute(Node node, String name) throws IIOInvalidTreeException { return getDoubleAttribute(node, name, -1.0F, true); } // Get a String-valued attribute private String getAttribute(Node node, String name, String defaultValue, boolean required) throws IIOInvalidTreeException { Node attr = node.getAttributes().getNamedItem(name); if (attr == null) { if (!required) { return defaultValue; } else { fatal(node, "Required attribute " + name + " not present!"); } } return attr.getNodeValue(); } // Get a required String-valued attribute private String getAttribute(Node node, String name) throws IIOInvalidTreeException { return getAttribute(node, name, null, true); } void initialize(ColorModel cm, SampleModel sm, ImageWriteParam param) { // bmpVersion and compression. if(param != null) { bmpVersion = BMPConstants.VERSION_3; if(param.getCompressionMode() == ImageWriteParam.MODE_EXPLICIT) { String compressionType = param.getCompressionType(); compression = BMPImageWriter.getCompressionType(compressionType); } } else { bmpVersion = BMPConstants.VERSION_3; compression = BMPImageWriter.getPreferredCompressionType(cm, sm); } // width and height width = sm.getWidth(); height = sm.getHeight(); // bitsPerPixel bitsPerPixel = (short)cm.getPixelSize(); // mask if(cm instanceof DirectColorModel) { DirectColorModel dcm = (DirectColorModel)cm; redMask = dcm.getRedMask(); greenMask = dcm.getGreenMask(); blueMask = dcm.getBlueMask(); alphaMask = dcm.getAlphaMask(); } // palette and paletteSize if(cm instanceof IndexColorModel) { IndexColorModel icm = (IndexColorModel)cm; paletteSize = icm.getMapSize(); byte[] r = new byte[paletteSize]; byte[] g = new byte[paletteSize]; byte[] b = new byte[paletteSize]; icm.getReds(r); icm.getGreens(g); icm.getBlues(b); boolean isVersion2 = bmpVersion != null && bmpVersion.equals(VERSION_2); palette = new byte[(isVersion2 ? 3 : 4)*paletteSize]; for(int i = 0, j = 0; i < paletteSize; i++) { palette[j++] = b[i]; palette[j++] = g[i]; palette[j++] = r[i]; if(!isVersion2) j++; // skip reserved entry } } } public void mergeTree(String formatName, Node root) throws IIOInvalidTreeException { if (formatName.equals(nativeMetadataFormatName)) { if (root == null) { throw new IllegalArgumentException("root == null!"); } mergeNativeTree(root); } else if (formatName.equals (IIOMetadataFormatImpl.standardMetadataFormatName)) { if (root == null) { throw new IllegalArgumentException("root == null!"); } mergeStandardTree(root); } else { throw new IllegalArgumentException("Not a recognized format!"); } } private void mergeNativeTree(Node root) throws IIOInvalidTreeException { Node node = root; if (!node.getNodeName().equals(nativeMetadataFormatName)) { fatal(node, "Root must be " + nativeMetadataFormatName); } byte[] r = null, g = null, b = null; int maxIndex = -1; node = node.getFirstChild(); while (node != null) { String name = node.getNodeName(); if (name.equals("BMPVersion")) { String value = getStringValue(node); if(value != null) bmpVersion = value; } else if (name.equals("Width")) { Integer value = getIntegerValue(node); if(value != null) width = value.intValue(); } else if (name.equals("Height")) { Integer value = getIntegerValue(node); if(value != null) height = value.intValue(); } else if (name.equals("BitsPerPixel")) { Short value = getShortValue(node); if(value != null) bitsPerPixel = value.shortValue(); } else if (name.equals("Compression")) { Integer value = getIntegerValue(node); if(value != null) compression = value.intValue(); } else if (name.equals("ImageSize")) { Integer value = getIntegerValue(node); if(value != null) imageSize = value.intValue(); } else if (name.equals("PixelsPerMeter")) { Node subNode = node.getFirstChild(); while (subNode != null) { String subName = subNode.getNodeName(); if(subName.equals("X")) { Integer value = getIntegerValue(subNode); if(value != null) xPixelsPerMeter = value.intValue(); } else if(subName.equals("Y")) { Integer value = getIntegerValue(subNode); if(value != null) yPixelsPerMeter = value.intValue(); } subNode = subNode.getNextSibling(); } } else if (name.equals("ColorsUsed")) { Integer value = getIntegerValue(node); if(value != null) colorsUsed = value.intValue(); } else if (name.equals("ColorsImportant")) { Integer value = getIntegerValue(node); if(value != null) colorsImportant = value.intValue(); } else if (name.equals("Mask")) { Node subNode = node.getFirstChild(); while (subNode != null) { String subName = subNode.getNodeName(); if(subName.equals("Red")) { Integer value = getIntegerValue(subNode); if(value != null) redMask = value.intValue(); } else if(subName.equals("Green")) { Integer value = getIntegerValue(subNode); if(value != null) greenMask = value.intValue(); } else if(subName.equals("Blue")) { Integer value = getIntegerValue(subNode); if(value != null) blueMask = value.intValue(); } else if(subName.equals("Alpha")) { Integer value = getIntegerValue(subNode); if(value != null) alphaMask = value.intValue(); } subNode = subNode.getNextSibling(); } } else if (name.equals("ColorSpace")) { Integer value = getIntegerValue(node); if(value != null) colorSpace = value.intValue(); } else if (name.equals("CIEXYZEndpoints")) { Node subNode = node.getFirstChild(); while (subNode != null) { String subName = subNode.getNodeName(); if(subName.equals("Red")) { Node subNode1 = subNode.getFirstChild(); while (subNode1 != null) { String subName1 = subNode1.getNodeName(); if(subName1.equals("X")) { Double value = getDoubleValue(subNode1); if(value != null) redX = value.doubleValue(); } else if(subName1.equals("Y")) { Double value = getDoubleValue(subNode1); if(value != null) redY = value.doubleValue(); } else if(subName1.equals("Z")) { Double value = getDoubleValue(subNode1); if(value != null) redZ = value.doubleValue(); } subNode1 = subNode1.getNextSibling(); } } else if(subName.equals("Green")) { Node subNode1 = subNode.getFirstChild(); while (subNode1 != null) { String subName1 = subNode1.getNodeName(); if(subName1.equals("X")) { Double value = getDoubleValue(subNode1); if(value != null) greenX = value.doubleValue(); } else if(subName1.equals("Y")) { Double value = getDoubleValue(subNode1); if(value != null) greenY = value.doubleValue(); } else if(subName1.equals("Z")) { Double value = getDoubleValue(subNode1); if(value != null) greenZ = value.doubleValue(); } subNode1 = subNode1.getNextSibling(); } } else if(subName.equals("Blue")) { Node subNode1 = subNode.getFirstChild(); while (subNode1 != null) { String subName1 = subNode1.getNodeName(); if(subName1.equals("X")) { Double value = getDoubleValue(subNode1); if(value != null) blueX = value.doubleValue(); } else if(subName1.equals("Y")) { Double value = getDoubleValue(subNode1); if(value != null) blueY = value.doubleValue(); } else if(subName1.equals("Z")) { Double value = getDoubleValue(subNode1); if(value != null) blueZ = value.doubleValue(); } subNode1 = subNode1.getNextSibling(); } } subNode = subNode.getNextSibling(); } } else if (name.equals("Gamma")) { Node subNode = node.getFirstChild(); while (subNode != null) { String subName = subNode.getNodeName(); if(subName.equals("Red")) { Integer value = getIntegerValue(subNode); if(value != null) gammaRed = value.intValue(); } else if(subName.equals("Green")) { Integer value = getIntegerValue(subNode); if(value != null) gammaGreen = value.intValue(); } else if(subName.equals("Blue")) { Integer value = getIntegerValue(subNode); if(value != null) gammaBlue = value.intValue(); } subNode = subNode.getNextSibling(); } } else if (name.equals("Intent")) { Integer value = getIntegerValue(node); if(value != null) intent = value.intValue(); } else if (name.equals("Palette")) { paletteSize = getIntAttribute(node, "sizeOfPalette"); r = new byte[paletteSize]; g = new byte[paletteSize]; b = new byte[paletteSize]; maxIndex = -1; Node paletteEntry = node.getFirstChild(); if (paletteEntry == null) { fatal(node, "Palette has no entries!"); } int numPaletteEntries = 0; while (paletteEntry != null) { if (!paletteEntry.getNodeName().equals("PaletteEntry")) { fatal(node, "Only a PaletteEntry may be a child of a Palette!"); } int index = -1; Node subNode = paletteEntry.getFirstChild(); while (subNode != null) { String subName = subNode.getNodeName(); if(subName.equals("Index")) { Integer value = getIntegerValue(subNode); if(value != null) index = value.intValue(); if (index < 0 || index > paletteSize - 1) { fatal(node, "Bad value for PaletteEntry attribute index!"); } } else if(subName.equals("Red")) { Integer value = getIntegerValue(subNode); if(value != null) red = value.intValue(); } else if(subName.equals("Green")) { Integer value = getIntegerValue(subNode); if(value != null) green = value.intValue(); } else if(subName.equals("Blue")) { Integer value = getIntegerValue(subNode); if(value != null) blue = value.intValue(); } subNode = subNode.getNextSibling(); } if(index == -1) { index = numPaletteEntries; } if (index > maxIndex) { maxIndex = index; } r[index] = (byte)red; g[index] = (byte)green; b[index] = (byte)blue; numPaletteEntries++; paletteEntry = paletteEntry.getNextSibling(); } } else if (name.equals("CommentExtensions")) { // CommentExtension Node commentExtension = node.getFirstChild(); if (commentExtension == null) { fatal(node, "CommentExtensions has no entries!"); } if(comments == null) { comments = new ArrayList(); } while (commentExtension != null) { if (!commentExtension.getNodeName().equals("CommentExtension")) { fatal(node, "Only a CommentExtension may be a child of a CommentExtensions!"); } comments.add(getAttribute(commentExtension, "value")); commentExtension = commentExtension.getNextSibling(); } } else { fatal(node, "Unknown child of root node!"); } node = node.getNextSibling(); } if(r != null && g != null && b != null) { boolean isVersion2 = bmpVersion != null && bmpVersion.equals(VERSION_2); int numEntries = maxIndex + 1; palette = new byte[(isVersion2 ? 3 : 4)*numEntries]; for(int i = 0, j = 0; i < numEntries; i++) { palette[j++] = b[i]; palette[j++] = g[i]; palette[j++] = r[i]; if(!isVersion2) j++; // skip reserved entry } } } private void mergeStandardTree(Node root) throws IIOInvalidTreeException { Node node = root; if (!node.getNodeName() .equals(IIOMetadataFormatImpl.standardMetadataFormatName)) { fatal(node, "Root must be " + IIOMetadataFormatImpl.standardMetadataFormatName); } String colorSpaceType = null; int numChannels = 0; int[] bitsPerSample = null; boolean hasAlpha = false; byte[] r = null, g = null, b = null; int maxIndex = -1; node = node.getFirstChild(); while(node != null) { String name = node.getNodeName(); if (name.equals("Chroma")) { Node child = node.getFirstChild(); while (child != null) { String childName = child.getNodeName(); if (childName.equals("ColorSpaceType")) { colorSpaceType = getAttribute(child, "name"); } else if (childName.equals("NumChannels")) { numChannels = getIntAttribute(child, "value"); } else if (childName.equals("Gamma")) { gammaRed = gammaGreen = gammaBlue = (int)(getDoubleAttribute(child, "value") + 0.5); } else if (childName.equals("Palette")) { r = new byte[256]; g = new byte[256]; b = new byte[256]; maxIndex = -1; Node paletteEntry = child.getFirstChild(); if (paletteEntry == null) { fatal(node, "Palette has no entries!"); } while (paletteEntry != null) { if (!paletteEntry.getNodeName().equals("PaletteEntry")) { fatal(node, "Only a PaletteEntry may be a child of a Palette!"); } int index = getIntAttribute(paletteEntry, "index"); if (index < 0 || index > 255) { fatal(node, "Bad value for PaletteEntry attribute index!"); } if (index > maxIndex) { maxIndex = index; } r[index] = (byte)getIntAttribute(paletteEntry, "red"); g[index] = (byte)getIntAttribute(paletteEntry, "green"); b[index] = (byte)getIntAttribute(paletteEntry, "blue"); paletteEntry = paletteEntry.getNextSibling(); } } child = child.getNextSibling(); } } else if (name.equals("Compression")) { Node child = node.getFirstChild(); while(child != null) { String childName = child.getNodeName(); if (childName.equals("CompressionTypeName")) { String compressionName = getAttribute(child, "value"); compression = BMPImageWriter.getCompressionType(compressionName); } child = child.getNextSibling(); } } else if (name.equals("Data")) { Node child = node.getFirstChild(); while(child != null) { String childName = child.getNodeName(); if (childName.equals("BitsPerSample")) { List bps = new ArrayList(4); String s = getAttribute(child, "value"); StringTokenizer t = new StringTokenizer(s); while(t.hasMoreTokens()) { bps.add(Integer.valueOf(t.nextToken())); } bitsPerSample = new int[bps.size()]; for(int i = 0; i < bitsPerSample.length; i++) { bitsPerSample[i] = ((Integer)bps.get(i)).intValue(); } break; } child = child.getNextSibling(); } } else if (name.equals("Dimension")) { boolean gotWidth = false; boolean gotHeight = false; boolean gotAspectRatio = false; boolean gotSpaceX = false; boolean gotSpaceY = false; double width = -1.0F; double height = -1.0F; double aspectRatio = -1.0F; double spaceX = -1.0F; double spaceY = -1.0F; Node child = node.getFirstChild(); while (child != null) { String childName = child.getNodeName(); if (childName.equals("PixelAspectRatio")) { aspectRatio = getDoubleAttribute(child, "value"); gotAspectRatio = true; } else if (childName.equals("HorizontalPixelSize")) { width = getDoubleAttribute(child, "value"); gotWidth = true; } else if (childName.equals("VerticalPixelSize")) { height = getDoubleAttribute(child, "value"); gotHeight = true; } else if (childName.equals("HorizontalPhysicalPixelSpacing")) { spaceX = getDoubleAttribute(child, "value"); gotSpaceX = true; } else if (childName.equals("VerticalPhysicalPixelSpacing")) { spaceY = getDoubleAttribute(child, "value"); gotSpaceY = true; // } else if (childName.equals("ImageOrientation")) { // } else if (childName.equals("HorizontalPosition")) { // } else if (childName.equals("VerticalPosition")) { // } else if (childName.equals("HorizontalPixelOffset")) { // } else if (childName.equals("VerticalPixelOffset")) { } child = child.getNextSibling(); } // Use PhysicalPixelSpacing if PixelSize not available. if(!(gotWidth || gotHeight) && (gotSpaceX || gotSpaceY)) { width = spaceX; gotWidth = gotSpaceX; height = spaceY; gotHeight = gotSpaceY; } // Round floating point values to obtain int resolution. if (gotWidth && gotHeight) { xPixelsPerMeter = (int)(1000.0/width + 0.5); yPixelsPerMeter = (int)(1000.0/height + 0.5); } else if (gotAspectRatio && aspectRatio != 0.0) { if(gotWidth) { xPixelsPerMeter = (int)(1000.0/width + 0.5); yPixelsPerMeter = (int)(aspectRatio*(1000.0/width) + 0.5); } else if(gotHeight) { xPixelsPerMeter = (int)(1000.0/height/aspectRatio + 0.5); yPixelsPerMeter = (int)(1000.0/height + 0.5); } } } else if (name.equals("Document")) { Node child = node.getFirstChild(); while(child != null) { String childName = child.getNodeName(); if (childName.equals("FormatVersion")) { bmpVersion = getAttribute(child, "value"); break; } child = child.getNextSibling(); } } else if (name.equals("Text")) { Node child = node.getFirstChild(); while(child != null) { String childName = child.getNodeName(); if (childName.equals("TextEntry")) { if(comments == null) { comments = new ArrayList(); } comments.add(getAttribute(child, "value")); } child = child.getNextSibling(); } } else if (name.equals("Transparency")) { Node child = node.getFirstChild(); while(child != null) { String childName = child.getNodeName(); if (childName.equals("Alpha")) { hasAlpha = !getAttribute(child, "value").equals("none"); break; } child = child.getNextSibling(); } } else { // XXX Ignore it. } node = node.getNextSibling(); } // Set bitsPerPixel. if(bitsPerSample != null) { if(palette != null && paletteSize > 0) { bitsPerPixel = (short)bitsPerSample[0]; } else { bitsPerPixel = 0; for(int i = 0; i < bitsPerSample.length; i++) { bitsPerPixel += bitsPerSample[i]; } } } else if(palette != null) { bitsPerPixel = 8; } else if(numChannels == 1) { bitsPerPixel = 8; } else if(numChannels == 3) { bitsPerPixel = 24; } else if(numChannels == 4) { bitsPerPixel = 32; } else if(colorSpaceType.equals("GRAY")) { bitsPerPixel = 8; } else if(colorSpaceType.equals("RGB")) { bitsPerPixel = (short)(hasAlpha ? 32 : 24); } // Set RGB masks. if((bitsPerSample != null && bitsPerSample.length == 4) || bitsPerPixel >= 24) { redMask = 0x00ff0000; greenMask = 0x0000ff00; blueMask = 0x000000ff; } // Set alpha mask. if((bitsPerSample != null && bitsPerSample.length == 4) || bitsPerPixel > 24) { alphaMask = 0xff000000; } // Set palette if(r != null && g != null && b != null) { boolean isVersion2 = bmpVersion != null && bmpVersion.equals(VERSION_2); paletteSize = maxIndex + 1; palette = new byte[(isVersion2 ? 3 : 4)*paletteSize]; for(int i = 0, j = 0; i < paletteSize; i++) { palette[j++] = b[i]; palette[j++] = g[i]; palette[j++] = r[i]; if(!isVersion2) j++; // skip reserved entry } } } public void reset() { // Fields for Image Descriptor bmpVersion = null; width = 0; height = 0; bitsPerPixel = 0; compression = 0; imageSize = 0; // Fields for PixelsPerMeter xPixelsPerMeter = 0; yPixelsPerMeter = 0; colorsUsed = 0; colorsImportant = 0; // Fields for BI_BITFIELDS compression(Mask) redMask = 0; greenMask = 0; blueMask = 0; alphaMask = 0; colorSpace = 0; // Fields for CIE XYZ for the LCS_CALIBRATED_RGB color space redX = 0; redY = 0; redZ = 0; greenX = 0; greenY = 0; greenZ = 0; blueX = 0; blueY = 0; blueZ = 0; // Fields for Gamma values for the LCS_CALIBRATED_RGB color space gammaRed = 0; gammaGreen = 0; gammaBlue = 0; intent = 0; // Fields for the Palette and Entries palette = null; paletteSize = 0; red = 0; green = 0; blue = 0; // Fields from CommentExtension comments = null; } private String countBits(int num) { int count = 0; while(num != 0) { if ((num & 1) == 1) count++; num >>>= 1; } return count == 0 ? "0" : "" + count; } private void addXYZPoints(IIOMetadataNode root, String name, double x, double y, double z) { IIOMetadataNode node = addChildNode(root, name, null); addChildNode(node, "X", new Double(x)); addChildNode(node, "Y", new Double(y)); addChildNode(node, "Z", new Double(z)); } private IIOMetadataNode addChildNode(IIOMetadataNode root, String name, Object object) { IIOMetadataNode child = new IIOMetadataNode(name); if (object != null) { child.setUserObject(object); child.setNodeValue(ImageUtil.convertObjectToString(object)); } root.appendChild(child); return child; } private Object getObjectValue(Node node) { Object tmp = node.getNodeValue(); if(tmp == null && node instanceof IIOMetadataNode) { tmp = ((IIOMetadataNode)node).getUserObject(); } return tmp; } private String getStringValue(Node node) { Object tmp = getObjectValue(node); return tmp instanceof String ? (String)tmp : null; } private Byte getByteValue(Node node) { Object tmp = getObjectValue(node); Byte value = null; if(tmp instanceof String) { value = Byte.valueOf((String)tmp); } else if(tmp instanceof Byte) { value = (Byte)tmp; } return value; } private Short getShortValue(Node node) { Object tmp = getObjectValue(node); Short value = null; if(tmp instanceof String) { value = Short.valueOf((String)tmp); } else if(tmp instanceof Short) { value = (Short)tmp; } return value; } private Integer getIntegerValue(Node node) { Object tmp = getObjectValue(node); Integer value = null; if(tmp instanceof String) { value = Integer.valueOf((String)tmp); } else if(tmp instanceof Integer) { value = (Integer)tmp; } else if(tmp instanceof Byte) { value = new Integer(((Byte)tmp).byteValue() & 0xff); } return value; } private Double getDoubleValue(Node node) { Object tmp = getObjectValue(node); Double value = null; if(tmp instanceof String) { value = Double.valueOf((String)tmp); } else if(tmp instanceof Double) { value = (Double)tmp; } return value; } } jai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/bmp/BMPImageWriter.java0000664000175100017510000014713110420012052031622 0ustar tilletille/* * $RCSfile: BMPImageWriter.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.2 $ * $Date: 2006-04-14 21:29:14 $ * $State: Exp $ */ package com.sun.media.imageioimpl.plugins.bmp; import java.awt.Point; import java.awt.Rectangle; import java.awt.image.ColorModel; import java.awt.image.ComponentSampleModel; import java.awt.image.DataBuffer; import java.awt.image.DataBufferByte; import java.awt.image.DataBufferInt; import java.awt.image.DataBufferShort; import java.awt.image.DataBufferUShort; import java.awt.image.DirectColorModel; import java.awt.image.IndexColorModel; import java.awt.image.MultiPixelPackedSampleModel; import java.awt.image.BandedSampleModel; import java.awt.image.Raster; import java.awt.image.RenderedImage; import java.awt.image.SampleModel; import java.awt.image.SinglePixelPackedSampleModel; import java.awt.image.WritableRaster; import java.awt.image.BufferedImage; import java.io.IOException; import java.io.ByteArrayOutputStream; import java.nio.ByteOrder; import java.util.Iterator; import javax.imageio.IIOImage; import javax.imageio.IIOException; import javax.imageio.ImageIO; import javax.imageio.ImageTypeSpecifier; import javax.imageio.ImageWriteParam; import javax.imageio.ImageWriter; import javax.imageio.metadata.IIOMetadata; import javax.imageio.metadata.IIOMetadataNode; import javax.imageio.metadata.IIOMetadataFormatImpl; import javax.imageio.metadata.IIOInvalidTreeException; import javax.imageio.spi.ImageWriterSpi; import javax.imageio.stream.ImageOutputStream; import javax.imageio.event.IIOWriteProgressListener; import javax.imageio.event.IIOWriteWarningListener; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import com.sun.media.imageio.plugins.bmp.BMPImageWriteParam; import com.sun.media.imageioimpl.common.ImageUtil; /** * The Java Image IO plugin writer for encoding a binary RenderedImage into * a BMP format. * * The encoding process may clip, subsample using the parameters * specified in the ImageWriteParam. * * @see com.sun.media.imageio.plugins.bmp.BMPImageWriteParam */ public class BMPImageWriter extends ImageWriter implements BMPConstants { /** The output stream to write into */ private ImageOutputStream stream = null; private ByteArrayOutputStream embedded_stream = null; private int compressionType; private boolean isTopDown; private int w, h; private int compImageSize = 0; private int[] bitMasks; private int[] bitPos; private byte[] bpixels; private short[] spixels; private int[] ipixels; /** Constructs BMPImageWriter based on the provided * ImageWriterSpi. */ public BMPImageWriter(ImageWriterSpi originator) { super(originator); } public void setOutput(Object output) { super.setOutput(output); // validates output if (output != null) { if (!(output instanceof ImageOutputStream)) throw new IllegalArgumentException(I18N.getString("BMPImageWriter0")); this.stream = (ImageOutputStream)output; stream.setByteOrder(ByteOrder.LITTLE_ENDIAN); } else this.stream = null; } public ImageWriteParam getDefaultWriteParam() { return new BMPImageWriteParam(); } public IIOMetadata getDefaultStreamMetadata(ImageWriteParam param) { return null; } public IIOMetadata getDefaultImageMetadata(ImageTypeSpecifier imageType, ImageWriteParam param) { BMPMetadata meta = new BMPMetadata(); meta.initialize(imageType.getColorModel(), imageType.getSampleModel(), param); return meta; } public IIOMetadata convertStreamMetadata(IIOMetadata inData, ImageWriteParam param) { return null; } public IIOMetadata convertImageMetadata(IIOMetadata inData, ImageTypeSpecifier imageType, ImageWriteParam param) { // Check arguments. if(inData == null) { throw new IllegalArgumentException("inData == null!"); } if(imageType == null) { throw new IllegalArgumentException("imageType == null!"); } BMPMetadata outData = null; // Obtain a BMPMetadata object. if(inData instanceof BMPMetadata) { // Clone the input metadata. outData = (BMPMetadata)((BMPMetadata)inData).clone(); } else { try { outData = new BMPMetadata(inData); } catch(IIOInvalidTreeException e) { // XXX Warning outData = new BMPMetadata(); } } // Update the metadata per the image type and param. outData.initialize(imageType.getColorModel(), imageType.getSampleModel(), param); return outData; } public boolean canWriteRasters() { return true; } public void write(IIOMetadata streamMetadata, IIOImage image, ImageWriteParam param) throws IOException { if (stream == null) { throw new IllegalStateException(I18N.getString("BMPImageWriter7")); } if (image == null) { throw new IllegalArgumentException(I18N.getString("BMPImageWriter8")); } clearAbortRequest(); processImageStarted(0); if (param == null) param = getDefaultWriteParam(); BMPImageWriteParam bmpParam = (BMPImageWriteParam)param; // Default is using 24 bits per pixel. int bitsPerPixel = 24; boolean isPalette = false; int paletteEntries = 0; IndexColorModel icm = null; RenderedImage input = null; Raster inputRaster = null; boolean writeRaster = image.hasRaster(); Rectangle sourceRegion = param.getSourceRegion(); SampleModel sampleModel = null; ColorModel colorModel = null; compImageSize = 0; if (writeRaster) { inputRaster = image.getRaster(); sampleModel = inputRaster.getSampleModel(); colorModel = ImageUtil.createColorModel(null, sampleModel); if (sourceRegion == null) sourceRegion = inputRaster.getBounds(); else sourceRegion = sourceRegion.intersection(inputRaster.getBounds()); } else { input = image.getRenderedImage(); sampleModel = input.getSampleModel(); colorModel = input.getColorModel(); Rectangle rect = new Rectangle(input.getMinX(), input.getMinY(), input.getWidth(), input.getHeight()); if (sourceRegion == null) sourceRegion = rect; else sourceRegion = sourceRegion.intersection(rect); } IIOMetadata imageMetadata = image.getMetadata(); BMPMetadata bmpImageMetadata = null; ImageTypeSpecifier imageType = new ImageTypeSpecifier(colorModel, sampleModel); if(imageMetadata != null) { // Convert metadata. bmpImageMetadata = (BMPMetadata)convertImageMetadata(imageMetadata, imageType, param); } else { // Use default. bmpImageMetadata = (BMPMetadata)getDefaultImageMetadata(imageType, param); } if (sourceRegion.isEmpty()) throw new RuntimeException(I18N.getString("BMPImageWrite0")); int scaleX = param.getSourceXSubsampling(); int scaleY = param.getSourceYSubsampling(); int xOffset = param.getSubsamplingXOffset(); int yOffset = param.getSubsamplingYOffset(); // cache the data type; int dataType = sampleModel.getDataType(); sourceRegion.translate(xOffset, yOffset); sourceRegion.width -= xOffset; sourceRegion.height -= yOffset; int minX = sourceRegion.x / scaleX; int minY = sourceRegion.y / scaleY; w = (sourceRegion.width + scaleX - 1) / scaleX; h = (sourceRegion.height + scaleY - 1) / scaleY; xOffset = sourceRegion.x % scaleX; yOffset = sourceRegion.y % scaleY; Rectangle destinationRegion = new Rectangle(minX, minY, w, h); boolean noTransform = destinationRegion.equals(sourceRegion); // Raw data can only handle bytes, everything greater must be ASCII. int[] sourceBands = param.getSourceBands(); boolean noSubband = true; int numBands = sampleModel.getNumBands(); if (sourceBands != null) { sampleModel = sampleModel.createSubsetSampleModel(sourceBands); colorModel = null; noSubband = false; numBands = sampleModel.getNumBands(); } else { sourceBands = new int[numBands]; for (int i = 0; i < numBands; i++) sourceBands[i] = i; } int[] bandOffsets = null; boolean bgrOrder = true; if (sampleModel instanceof ComponentSampleModel) { bandOffsets = ((ComponentSampleModel)sampleModel).getBandOffsets(); if (sampleModel instanceof BandedSampleModel) { // for images with BandedSampleModel we can not work // with raster directly and must use writePixels() bgrOrder = false; } else { // we can work with raster directly only in case of // BGR component order. // In any other case we must use writePixels() for (int i = 0; i < bandOffsets.length; i++) { bgrOrder &= (bandOffsets[i] == (bandOffsets.length - i - 1)); } } } else { if (sampleModel instanceof SinglePixelPackedSampleModel) { // BugId 4892214: we can not work with raster directly // if image have different color order than RGB. // We should use writePixels() for such images. int[] bitOffsets = ((SinglePixelPackedSampleModel)sampleModel).getBitOffsets(); for (int i=0; i bitOffsets[i+1]; } } } if (bandOffsets == null) { // we will use getPixels() to extract pixel data for writePixels() // Please note that getPixels() provides rgb bands order. bandOffsets = new int[numBands]; for (int i = 0; i < numBands; i++) bandOffsets[i] = i; } noTransform &= bgrOrder; int sampleSize[] = sampleModel.getSampleSize(); //XXX: check more // Number of bytes that a scanline for the image written out will have. int destScanlineBytes = w * numBands; switch(bmpParam.getCompressionMode()) { case ImageWriteParam.MODE_EXPLICIT: compressionType = getCompressionType(bmpParam.getCompressionType()); break; case ImageWriteParam.MODE_COPY_FROM_METADATA: compressionType = bmpImageMetadata.compression; break; case ImageWriteParam.MODE_DEFAULT: compressionType = getPreferredCompressionType(colorModel, sampleModel); break; default: // ImageWriteParam.MODE_DISABLED: compressionType = BI_RGB; } if (!canEncodeImage(compressionType, colorModel, sampleModel)) { if (param.getCompressionMode() == ImageWriteParam.MODE_EXPLICIT) { throw new IIOException("Image can not be encoded with " + "compression type " + compressionTypeNames[compressionType]); } else { // Set to something appropriate compressionType = getPreferredCompressionType(colorModel, sampleModel); } } byte r[] = null, g[] = null, b[] = null, a[] = null; if (compressionType == BMPConstants.BI_BITFIELDS) { bitsPerPixel = DataBuffer.getDataTypeSize(sampleModel.getDataType()); if (bitsPerPixel != 16 && bitsPerPixel != 32) { // we should use 32bpp images in case of BI_BITFIELD // compression to avoid color conversion artefacts bitsPerPixel = 32; // Setting this flag to false ensures that generic // writePixels() will be used to store image data noTransform = false; } destScanlineBytes = w * bitsPerPixel + 7 >> 3; isPalette = true; paletteEntries = 3; r = new byte[paletteEntries]; g = new byte[paletteEntries]; b = new byte[paletteEntries]; a = new byte[paletteEntries]; int rmask = 0x00ff0000; int gmask = 0x0000ff00; int bmask = 0x000000ff; if (bitsPerPixel == 16) { /* NB: canEncodeImage() ensures we have image of * either USHORT_565_RGB or USHORT_555_RGB type here. * Technically, it should work for other direct color * model types but it might be non compatible with win98 * and friends. */ if (colorModel instanceof DirectColorModel) { DirectColorModel dcm = (DirectColorModel)colorModel; rmask = dcm.getRedMask(); gmask = dcm.getGreenMask(); bmask = dcm.getBlueMask(); } else { // it is unlikely, but if it happens, we should throw // an exception related to unsupported image format throw new IOException("Image can not be encoded with " + "compression type " + compressionTypeNames[compressionType]); } } writeMaskToPalette(rmask, 0, r, g, b, a); writeMaskToPalette(gmask, 1, r, g, b, a); writeMaskToPalette(bmask, 2, r, g, b, a); if (!noTransform) { // prepare info for writePixels procedure bitMasks = new int[3]; bitMasks[0] = rmask; bitMasks[1] = gmask; bitMasks[2] = bmask; bitPos = new int[3]; bitPos[0] = firstLowBit(rmask); bitPos[1] = firstLowBit(gmask); bitPos[2] = firstLowBit(bmask); } if (colorModel instanceof IndexColorModel) { icm = (IndexColorModel)colorModel; } } else { // handle BI_RGB compression if (colorModel instanceof IndexColorModel) { isPalette = true; icm = (IndexColorModel)colorModel; paletteEntries = icm.getMapSize(); if (paletteEntries <= 2) { bitsPerPixel = 1; destScanlineBytes = w + 7 >> 3; } else if (paletteEntries <= 16) { bitsPerPixel = 4; destScanlineBytes = w + 1 >> 1; } else if (paletteEntries <= 256) { bitsPerPixel = 8; } else { // Cannot be written as a Palette image. So write out as // 24 bit image. bitsPerPixel = 24; isPalette = false; paletteEntries = 0; destScanlineBytes = w * 3; } if (isPalette == true) { r = new byte[paletteEntries]; g = new byte[paletteEntries]; b = new byte[paletteEntries]; icm.getReds(r); icm.getGreens(g); icm.getBlues(b); } } else { // Grey scale images if (numBands == 1) { isPalette = true; paletteEntries = 256; bitsPerPixel = sampleSize[0]; destScanlineBytes = (w * bitsPerPixel + 7 >> 3); r = new byte[256]; g = new byte[256]; b = new byte[256]; for (int i = 0; i < 256; i++) { r[i] = (byte)i; g[i] = (byte)i; b[i] = (byte)i; } } else { if (sampleModel instanceof SinglePixelPackedSampleModel && noSubband) { /* NB: the actual pixel size can be smaller than * size of used DataBuffer element. * For example: in case of TYPE_INT_RGB actual pixel * size is 24 bits, but size of DataBuffere element * is 32 bits */ int[] sample_sizes = sampleModel.getSampleSize(); bitsPerPixel = 0; for (int i=0; i < sample_sizes.length; i++) { bitsPerPixel += sample_sizes[i]; } bitsPerPixel = roundBpp(bitsPerPixel); if (bitsPerPixel != DataBuffer.getDataTypeSize(sampleModel.getDataType())) { noTransform = false; } destScanlineBytes = w * bitsPerPixel + 7 >> 3; } } } } // actual writing of image data int fileSize = 0; int offset = 0; int headerSize = 0; int imageSize = 0; int xPelsPerMeter = bmpImageMetadata.xPixelsPerMeter; int yPelsPerMeter = bmpImageMetadata.yPixelsPerMeter; int colorsUsed = bmpImageMetadata.colorsUsed > 0 ? bmpImageMetadata.colorsUsed : paletteEntries; int colorsImportant = paletteEntries; // Calculate padding for each scanline int padding = destScanlineBytes % 4; if (padding != 0) { padding = 4 - padding; } // FileHeader is 14 bytes, BitmapHeader is 40 bytes, // add palette size and that is where the data will begin offset = 54 + paletteEntries * 4; imageSize = (destScanlineBytes + padding) * h; fileSize = imageSize + offset; headerSize = 40; long headPos = stream.getStreamPosition(); if(param instanceof BMPImageWriteParam) { isTopDown = ((BMPImageWriteParam)param).isTopDown(); // topDown = true is only allowed for RGB and BITFIELDS compression // types by the BMP specification if (compressionType != BI_RGB && compressionType != BI_BITFIELDS) isTopDown = false; } else { isTopDown = false; } writeFileHeader(fileSize, offset); writeInfoHeader(headerSize, bitsPerPixel); // compression stream.writeInt(compressionType); // imageSize stream.writeInt(imageSize); // xPelsPerMeter stream.writeInt(xPelsPerMeter); // yPelsPerMeter stream.writeInt(yPelsPerMeter); // Colors Used stream.writeInt(colorsUsed); // Colors Important stream.writeInt(colorsImportant); // palette if (isPalette == true) { // write palette if (compressionType == BMPConstants.BI_BITFIELDS) { // write masks for red, green and blue components. for (int i=0; i<3; i++) { int mask = (a[i]&0xFF) + ((r[i]&0xFF)*0x100) + ((g[i]&0xFF)* 0x10000) + ((b[i]&0xFF)*0x1000000); stream.writeInt(mask); } } else { for (int i=0; i maxBandOffset) maxBandOffset = bandOffsets[i]; int[] pixel = new int[maxBandOffset + 1]; int destScanlineLength = destScanlineBytes; if (noTransform && noSubband) { destScanlineLength = destScanlineBytes / (DataBuffer.getDataTypeSize(dataType)>>3); } for (int i = 0; i < h; i++) { if (abortRequested()) { break; } int row = minY + i; if (!isTopDown) row = minY + h - i -1; // Get the pixels Raster src = inputRaster; Rectangle srcRect = new Rectangle(minX * scaleX + xOffset, row * scaleY + yOffset, (w - 1)* scaleX + 1, 1); if (!writeRaster) src = input.getData(srcRect); if (noTransform && noSubband) { SampleModel sm = src.getSampleModel(); int pos = 0; int startX = srcRect.x - src.getSampleModelTranslateX(); int startY = srcRect.y - src.getSampleModelTranslateY(); if (sm instanceof ComponentSampleModel) { ComponentSampleModel csm = (ComponentSampleModel)sm; pos = csm.getOffset(startX, startY, 0); for(int nb=1; nb < csm.getNumBands(); nb++) { if (pos > csm.getOffset(startX, startY, nb)) { pos = csm.getOffset(startX, startY, nb); } } } else if (sm instanceof MultiPixelPackedSampleModel) { MultiPixelPackedSampleModel mppsm = (MultiPixelPackedSampleModel)sm; pos = mppsm.getOffset(startX, startY); } else if (sm instanceof SinglePixelPackedSampleModel) { SinglePixelPackedSampleModel sppsm = (SinglePixelPackedSampleModel)sm; pos = sppsm.getOffset(startX, startY); } if (compressionType == BMPConstants.BI_RGB || compressionType == BMPConstants.BI_BITFIELDS){ switch(dataType) { case DataBuffer.TYPE_BYTE: byte[] bdata = ((DataBufferByte)src.getDataBuffer()).getData(); stream.write(bdata, pos, destScanlineLength); break; case DataBuffer.TYPE_SHORT: short[] sdata = ((DataBufferShort)src.getDataBuffer()).getData(); stream.writeShorts(sdata, pos, destScanlineLength); break; case DataBuffer.TYPE_USHORT: short[] usdata = ((DataBufferUShort)src.getDataBuffer()).getData(); stream.writeShorts(usdata, pos, destScanlineLength); break; case DataBuffer.TYPE_INT: int[] idata = ((DataBufferInt)src.getDataBuffer()).getData(); stream.writeInts(idata, pos, destScanlineLength); break; } for(int k=0; k>>= 1; } return count; } private class IIOWriteProgressAdapter implements IIOWriteProgressListener { public void imageComplete(ImageWriter source) { } public void imageProgress(ImageWriter source, float percentageDone) { } public void imageStarted(ImageWriter source, int imageIndex) { } public void thumbnailComplete(ImageWriter source) { } public void thumbnailProgress(ImageWriter source, float percentageDone) { } public void thumbnailStarted(ImageWriter source, int imageIndex, int thumbnailIndex) { } public void writeAborted(ImageWriter source) { } } /* * Returns preferred compression type for given image. * The default compression type is BI_RGB, but some image types can't be * encoded with using default compression without changing color resolution. * For example, BufferedImage.TYPE_USHORT_555_RGB and * BufferedImage.TYPE_USHORT_565_RGB may be encoded only by using the * BI_BITFIELDS compression type. * * NB: we probably need to extend this method if we encounter other image * types which can not be encoded with BI_RGB compression type. */ static int getPreferredCompressionType(ColorModel cm, SampleModel sm) { ImageTypeSpecifier imageType = new ImageTypeSpecifier(cm, sm); return getPreferredCompressionType(imageType); } static int getPreferredCompressionType(ImageTypeSpecifier imageType) { int biType = imageType.getBufferedImageType(); if (biType == BufferedImage.TYPE_USHORT_565_RGB || biType == BufferedImage.TYPE_USHORT_555_RGB) { return BI_BITFIELDS; } return BI_RGB; } /* * Check whether we can encode image of given type using compression method in question. * * For example, TYPE_USHORT_565_RGB can be encodeed with BI_BITFIELDS compression only. * * NB: method should be extended if other cases when we can not encode * with given compression will be discovered. */ protected boolean canEncodeImage(int compression, ColorModel cm, SampleModel sm) { ImageTypeSpecifier imgType = new ImageTypeSpecifier(cm, sm); return canEncodeImage(compression, imgType); } protected boolean canEncodeImage(int compression, ImageTypeSpecifier imgType) { ImageWriterSpi spi = this.getOriginatingProvider(); if (!spi.canEncodeImage(imgType)) { return false; } int bpp = imgType.getColorModel().getPixelSize(); if (compressionType == BI_RLE4 && bpp != 4) { // only 4bpp images can be encoded as BI_RLE4 return false; } if (compressionType == BI_RLE8 && bpp != 8) { // only 8bpp images can be encoded as BI_RLE8 return false; } if (bpp == 16) { /* * Technically we expect that we may be able to * encode only some of SinglePixelPackedSampleModel * images here. * * In addition we should take into account following: * * 1. BI_RGB case, according to the MSDN description: * * The bitmap has a maximum of 2^16 colors. If the * biCompression member of the BITMAPINFOHEADER is BI_RGB, * the bmiColors member of BITMAPINFO is NULL. Each WORD * in the bitmap array represents a single pixel. The * relative intensities of red, green, and blue are * represented with five bits for each color component. * * 2. BI_BITFIELDS case, according ot the MSDN description: * * Windows 95/98/Me: When the biCompression member is * BI_BITFIELDS, the system supports only the following * 16bpp color masks: A 5-5-5 16-bit image, where the blue * mask is 0x001F, the green mask is 0x03E0, and the red mask * is 0x7C00; and a 5-6-5 16-bit image, where the blue mask * is 0x001F, the green mask is 0x07E0, and the red mask is * 0xF800. */ boolean canUseRGB = false; boolean canUseBITFIELDS = false; SampleModel sm = imgType.getSampleModel(); if (sm instanceof SinglePixelPackedSampleModel) { int[] sizes = ((SinglePixelPackedSampleModel)sm).getSampleSize(); canUseRGB = true; canUseBITFIELDS = true; for (int i = 0; i < sizes.length; i++) { canUseRGB &= (sizes[i] == 5); canUseBITFIELDS &= ((sizes[i] == 5) || (i == 1 && sizes[i] == 6)); } } return (((compressionType == BI_RGB) && canUseRGB) || ((compressionType == BI_BITFIELDS) && canUseBITFIELDS)); } return true; } protected void writeMaskToPalette(int mask, int i, byte[] r, byte[]g, byte[] b, byte[]a) { b[i] = (byte)(0xff & (mask >> 24)); g[i] = (byte)(0xff & (mask >> 16)); r[i] = (byte)(0xff & (mask >> 8)); a[i] = (byte)(0xff & mask); } private int roundBpp(int x) { if (x <= 8) { return 8; } else if (x <= 16) { return 16; } if (x <= 24) { return 24; } else { return 32; } } } jai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/bmp/BMPImageReader.java0000664000175100017510000020234110420012052031543 0ustar tilletille/* * $RCSfile: BMPImageReader.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.2 $ * $Date: 2006-04-14 21:29:14 $ * $State: Exp $ */ package com.sun.media.imageioimpl.plugins.bmp; import java.awt.Point; import java.awt.Rectangle; import java.awt.Transparency; import java.awt.color.ColorSpace; import java.awt.color.ICC_ColorSpace; import java.awt.color.ICC_Profile; import java.awt.image.BufferedImage; import java.awt.image.ColorModel; import java.awt.image.ComponentColorModel; import java.awt.image.ComponentSampleModel; import java.awt.image.DataBuffer; import java.awt.image.DataBufferByte; import java.awt.image.DataBufferInt; import java.awt.image.DataBufferUShort; import java.awt.image.DirectColorModel; import java.awt.image.IndexColorModel; import java.awt.image.MultiPixelPackedSampleModel; import java.awt.image.PixelInterleavedSampleModel; import java.awt.image.Raster; import java.awt.image.SampleModel; import java.awt.image.SinglePixelPackedSampleModel; import java.awt.image.WritableRaster; import javax.imageio.IIOException; import javax.imageio.ImageIO; import javax.imageio.ImageReader; import javax.imageio.ImageReadParam; import javax.imageio.ImageTypeSpecifier; import javax.imageio.metadata.IIOMetadata; import javax.imageio.spi.ImageReaderSpi; import javax.imageio.stream.ImageInputStream; import javax.imageio.event.IIOReadProgressListener; import javax.imageio.event.IIOReadUpdateListener; import javax.imageio.event.IIOReadWarningListener; import java.io.*; import java.nio.*; import java.util.ArrayList; import java.util.Iterator; import java.util.StringTokenizer; import com.sun.media.imageioimpl.common.ImageUtil; /** This class is the Java Image IO plugin reader for BMP images. * It may subsample the image, clip the image, select sub-bands, * and shift the decoded image origin if the proper decoding parameter * are set in the provided ImageReadParam. * * This class supports Microsoft Windows Bitmap Version 3-5, * as well as OS/2 Bitmap Version 2.x (for single-image BMP file). */ public class BMPImageReader extends ImageReader implements BMPConstants { // BMP Image types private static final int VERSION_2_1_BIT = 0; private static final int VERSION_2_4_BIT = 1; private static final int VERSION_2_8_BIT = 2; private static final int VERSION_2_24_BIT = 3; private static final int VERSION_3_1_BIT = 4; private static final int VERSION_3_4_BIT = 5; private static final int VERSION_3_8_BIT = 6; private static final int VERSION_3_24_BIT = 7; private static final int VERSION_3_NT_16_BIT = 8; private static final int VERSION_3_NT_32_BIT = 9; private static final int VERSION_4_1_BIT = 10; private static final int VERSION_4_4_BIT = 11; private static final int VERSION_4_8_BIT = 12; private static final int VERSION_4_16_BIT = 13; private static final int VERSION_4_24_BIT = 14; private static final int VERSION_4_32_BIT = 15; private static final int VERSION_3_XP_EMBEDDED = 16; private static final int VERSION_4_XP_EMBEDDED = 17; private static final int VERSION_5_XP_EMBEDDED = 18; // BMP variables private long bitmapFileSize; private long bitmapOffset; private long compression; private long imageSize; private byte palette[]; private int imageType; private int numBands; private boolean isBottomUp; private int bitsPerPixel; private int redMask, greenMask, blueMask, alphaMask; private SampleModel sampleModel, originalSampleModel; private ColorModel colorModel, originalColorModel; /** The input stream where reads from */ private ImageInputStream iis = null; /** Indicates whether the header is read. */ private boolean gotHeader = false; /** The stream position where the image data starts. */ private long imageDataOffset; /** The original image width. */ private int width; /** The original image height. */ private int height; /** The destination region. */ private Rectangle destinationRegion; /** The source region. */ private Rectangle sourceRegion; /** The metadata from the stream. */ private BMPMetadata metadata; /** The destination image. */ private BufferedImage bi; /** Indicates whether subsampled, subregion is required, and offset is * defined */ private boolean noTransform = true; /** Indicates whether subband is selected. */ private boolean seleBand = false; /** The scaling factors. */ private int scaleX, scaleY; /** source and destination bands. */ private int[] sourceBands, destBands; /** Constructs BMPImageReader from the provided * ImageReaderSpi. */ public BMPImageReader(ImageReaderSpi originator) { super(originator); } /** Overrides the method defined in the superclass. */ public void setInput(Object input, boolean seekForwardOnly, boolean ignoreMetadata) { super.setInput(input, seekForwardOnly, ignoreMetadata); iis = (ImageInputStream) input; // Always works if(iis != null) iis.setByteOrder(ByteOrder.LITTLE_ENDIAN); resetHeaderInfo(); } /** Overrides the method defined in the superclass. */ public int getNumImages(boolean allowSearch) throws IOException { if (iis == null) { throw new IllegalStateException(I18N.getString("GetNumImages0")); } if (seekForwardOnly && allowSearch) { throw new IllegalStateException(I18N.getString("GetNumImages1")); } return 1; } public int getWidth(int imageIndex) throws IOException { checkIndex(imageIndex); readHeader(); return width; } public int getHeight(int imageIndex) throws IOException { checkIndex(imageIndex); readHeader(); return height; } private void checkIndex(int imageIndex) { if (imageIndex != 0) { throw new IndexOutOfBoundsException(I18N.getString("BMPImageReader0")); } } public void readHeader() throws IOException { if (gotHeader) { // Seek to where the image data starts, since that is where // the stream pointer should be after header is read iis.seek(imageDataOffset); return; } if (iis == null) { throw new IllegalStateException(I18N.getString("BMPImageReader5")); } int profileData = 0, profileSize = 0; this.metadata = new BMPMetadata(); iis.mark(); // read and check the magic marker byte[] marker = new byte[2]; iis.read(marker); if (marker[0] != 0x42 || marker[1] != 0x4d) throw new IllegalArgumentException(I18N.getString("BMPImageReader1")); // Read file size bitmapFileSize = iis.readUnsignedInt(); // skip the two reserved fields iis.skipBytes(4); // Offset to the bitmap from the beginning bitmapOffset = iis.readUnsignedInt(); // End File Header // Start BitmapCoreHeader long size = iis.readUnsignedInt(); if (size == 12) { width = iis.readShort(); height = iis.readShort(); } else { width = iis.readInt(); height = iis.readInt(); } metadata.width = width; metadata.height = height; int planes = iis.readUnsignedShort(); bitsPerPixel = iis.readUnsignedShort(); //metadata.colorPlane = planes; metadata.bitsPerPixel = (short)bitsPerPixel; // As BMP always has 3 rgb bands, except for Version 5, // which is bgra numBands = 3; if (size == 12) { // Windows 2.x and OS/2 1.x metadata.bmpVersion = VERSION_2; // Classify the image type if (bitsPerPixel == 1) { imageType = VERSION_2_1_BIT; } else if (bitsPerPixel == 4) { imageType = VERSION_2_4_BIT; } else if (bitsPerPixel == 8) { imageType = VERSION_2_8_BIT; } else if (bitsPerPixel == 24) { imageType = VERSION_2_24_BIT; } // Read in the palette int numberOfEntries = (int)((bitmapOffset - 14 - size) / 3); int sizeOfPalette = numberOfEntries*3; palette = new byte[sizeOfPalette]; iis.readFully(palette, 0, sizeOfPalette); metadata.palette = palette; metadata.paletteSize = numberOfEntries; } else { compression = iis.readUnsignedInt(); imageSize = iis.readUnsignedInt(); long xPelsPerMeter = iis.readInt(); long yPelsPerMeter = iis.readInt(); long colorsUsed = iis.readUnsignedInt(); long colorsImportant = iis.readUnsignedInt(); metadata.compression = (int)compression; metadata.imageSize = (int)imageSize; metadata.xPixelsPerMeter = (int)xPelsPerMeter; metadata.yPixelsPerMeter = (int)yPelsPerMeter; metadata.colorsUsed = (int)colorsUsed; metadata.colorsImportant = (int)colorsImportant; if (size == 40) { // Windows 3.x and Windows NT switch((int)compression) { case BI_JPEG: case BI_PNG: metadata.bmpVersion = VERSION_3; imageType = VERSION_3_XP_EMBEDDED; break; case BI_RGB: // No compression case BI_RLE8: // 8-bit RLE compression case BI_RLE4: // 4-bit RLE compression // Read in the palette int numberOfEntries = (int)((bitmapOffset-14-size) / 4); int sizeOfPalette = numberOfEntries * 4; palette = new byte[sizeOfPalette]; iis.readFully(palette, 0, sizeOfPalette); metadata.palette = palette; metadata.paletteSize = numberOfEntries; if (bitsPerPixel == 1) { imageType = VERSION_3_1_BIT; } else if (bitsPerPixel == 4) { imageType = VERSION_3_4_BIT; } else if (bitsPerPixel == 8) { imageType = VERSION_3_8_BIT; } else if (bitsPerPixel == 24) { imageType = VERSION_3_24_BIT; } else if (bitsPerPixel == 16) { imageType = VERSION_3_NT_16_BIT; redMask = 0x7C00; greenMask = 0x3E0; blueMask = (1 << 5) - 1;// 0x1F; metadata.redMask = redMask; metadata.greenMask = greenMask; metadata.blueMask = blueMask; } else if (bitsPerPixel == 32) { imageType = VERSION_3_NT_32_BIT; redMask = 0x00FF0000; greenMask = 0x0000FF00; blueMask = 0x000000FF; metadata.redMask = redMask; metadata.greenMask = greenMask; metadata.blueMask = blueMask; } metadata.bmpVersion = VERSION_3; break; case BI_BITFIELDS: if (bitsPerPixel == 16) { imageType = VERSION_3_NT_16_BIT; } else if (bitsPerPixel == 32) { imageType = VERSION_3_NT_32_BIT; } // BitsField encoding redMask = (int)iis.readUnsignedInt(); greenMask = (int)iis.readUnsignedInt(); blueMask = (int)iis.readUnsignedInt(); metadata.redMask = redMask; metadata.greenMask = greenMask; metadata.blueMask = blueMask; if (colorsUsed != 0) { // there is a palette sizeOfPalette = (int)colorsUsed*4; palette = new byte[sizeOfPalette]; iis.readFully(palette, 0, sizeOfPalette); metadata.palette = palette; metadata.paletteSize = (int)colorsUsed; } metadata.bmpVersion = VERSION_3_NT; break; default: throw new RuntimeException(I18N.getString("BMPImageReader2")); } } else if (size == 108 || size == 124) { // Windows 4.x BMP if (size == 108) metadata.bmpVersion = VERSION_4; else if (size == 124) metadata.bmpVersion = VERSION_5; // rgb masks, valid only if comp is BI_BITFIELDS redMask = (int)iis.readUnsignedInt(); greenMask = (int)iis.readUnsignedInt(); blueMask = (int)iis.readUnsignedInt(); // Only supported for 32bpp BI_RGB argb alphaMask = (int)iis.readUnsignedInt(); long csType = iis.readUnsignedInt(); int redX = iis.readInt(); int redY = iis.readInt(); int redZ = iis.readInt(); int greenX = iis.readInt(); int greenY = iis.readInt(); int greenZ = iis.readInt(); int blueX = iis.readInt(); int blueY = iis.readInt(); int blueZ = iis.readInt(); long gammaRed = iis.readUnsignedInt(); long gammaGreen = iis.readUnsignedInt(); long gammaBlue = iis.readUnsignedInt(); if (size == 124) { metadata.intent = iis.readInt(); profileData = iis.readInt(); profileSize = iis.readInt(); iis.skipBytes(4); } metadata.colorSpace = (int)csType; if (csType == LCS_CALIBRATED_RGB) { // All the new fields are valid only for this case metadata.redX = redX; metadata.redY = redY; metadata.redZ = redZ; metadata.greenX = greenX; metadata.greenY = greenY; metadata.greenZ = greenZ; metadata.blueX = blueX; metadata.blueY = blueY; metadata.blueZ = blueZ; metadata.gammaRed = (int)gammaRed; metadata.gammaGreen = (int)gammaGreen; metadata.gammaBlue = (int)gammaBlue; } // Read in the palette int numberOfEntries = (int)((bitmapOffset-14-size) / 4); int sizeOfPalette = numberOfEntries*4; palette = new byte[sizeOfPalette]; iis.readFully(palette, 0, sizeOfPalette); metadata.palette = palette; metadata.paletteSize = numberOfEntries; switch ((int)compression) { case BI_JPEG: case BI_PNG: if (size == 108) { imageType = VERSION_4_XP_EMBEDDED; } else if (size == 124) { imageType = VERSION_5_XP_EMBEDDED; } break; default: if (bitsPerPixel == 1) { imageType = VERSION_4_1_BIT; } else if (bitsPerPixel == 4) { imageType = VERSION_4_4_BIT; } else if (bitsPerPixel == 8) { imageType = VERSION_4_8_BIT; } else if (bitsPerPixel == 16) { imageType = VERSION_4_16_BIT; if ((int)compression == BI_RGB) { redMask = 0x7C00; greenMask = 0x3E0; blueMask = 0x1F; } } else if (bitsPerPixel == 24) { imageType = VERSION_4_24_BIT; } else if (bitsPerPixel == 32) { imageType = VERSION_4_32_BIT; if ((int)compression == BI_RGB) { redMask = 0x00FF0000; greenMask = 0x0000FF00; blueMask = 0x000000FF; } } metadata.redMask = redMask; metadata.greenMask = greenMask; metadata.blueMask = blueMask; metadata.alphaMask = alphaMask; } } else { throw new RuntimeException(I18N.getString("BMPImageReader3")); } } if (height > 0) { // bottom up image isBottomUp = true; } else { // top down image isBottomUp = false; height = Math.abs(height); } // Reset Image Layout so there's only one tile. //Define the color space ColorSpace colorSpace = ColorSpace.getInstance(ColorSpace.CS_sRGB); if (metadata.colorSpace == PROFILE_LINKED || metadata.colorSpace == PROFILE_EMBEDDED) { iis.mark(); iis.skipBytes(profileData - size); byte[] profile = new byte[profileSize]; iis.readFully(profile, 0, profileSize); iis.reset(); try { if (metadata.colorSpace == PROFILE_LINKED) colorSpace = new ICC_ColorSpace(ICC_Profile.getInstance(new String(profile))); else colorSpace = new ICC_ColorSpace(ICC_Profile.getInstance(profile)); } catch (Exception e) { colorSpace = ColorSpace.getInstance(ColorSpace.CS_sRGB); } } if (bitsPerPixel == 0 || compression == BI_JPEG || compression == BI_PNG ) { // the colorModel and sampleModel will be initialzed // by the reader of embedded image colorModel = null; sampleModel = null; } else if (bitsPerPixel == 1 || bitsPerPixel == 4 || bitsPerPixel == 8) { // When number of bitsPerPixel is <= 8, we use IndexColorModel. numBands = 1; if (bitsPerPixel == 8) { int[] bandOffsets = new int[numBands]; for (int i = 0; i < numBands; i++) { bandOffsets[i] = numBands -1 -i; } sampleModel = new PixelInterleavedSampleModel(DataBuffer.TYPE_BYTE, width, height, numBands, numBands * width, bandOffsets); } else { // 1 and 4 bit pixels can be stored in a packed format. sampleModel = new MultiPixelPackedSampleModel(DataBuffer.TYPE_BYTE, width, height, bitsPerPixel); } // Create IndexColorModel from the palette. byte r[], g[], b[]; if (imageType == VERSION_2_1_BIT || imageType == VERSION_2_4_BIT || imageType == VERSION_2_8_BIT) { size = palette.length/3; if (size > 256) { size = 256; } int off; r = new byte[(int)size]; g = new byte[(int)size]; b = new byte[(int)size]; for (int i=0; i<(int)size; i++) { off = 3 * i; b[i] = palette[off]; g[i] = palette[off+1]; r[i] = palette[off+2]; } } else { size = palette.length/4; if (size > 256) { size = 256; } int off; r = new byte[(int)size]; g = new byte[(int)size]; b = new byte[(int)size]; for (int i=0; i> 3; srcOff[j] = 7 - (x & 7); destPos[j] = i >> 3; destOff[j] = 7 - (i & 7); } int k = destinationRegion.y * lineStride; if (isBottomUp) k += (destinationRegion.height - 1) * lineStride; for (int j = 0, y = sourceRegion.y; j < destinationRegion.height; j++, y+=scaleY) { if (abortRequested()) break; iis.read(buf, 0, lineLength); for (int i = 0; i < destinationRegion.width; i++) { //get the bit and assign to the data buffer of the raster int v = (buf[srcPos[i]] >> srcOff[i]) & 1; bdata[k + destPos[i]] |= v << destOff[i]; } k += isBottomUp ? -lineStride : lineStride; iis.skipBytes(skipLength); processImageUpdate(bi, 0, j, destinationRegion.width, 1, 1, 1, new int[]{0}); processImageProgress(100.0F*j/destinationRegion.height); } } } // Method to read a 4 bit BMP image data private void read4Bit(byte[] bdata) throws IOException { int bytesPerScanline = (width + 1) / 2; // Padding bytes at the end of each scanline int padding = bytesPerScanline % 4; if (padding != 0) padding = 4 - padding; int lineLength = bytesPerScanline + padding; if (noTransform) { int j = isBottomUp ? (height -1) * bytesPerScanline : 0; for (int i=0; i> 1; srcOff[j] = (1 - (x & 1)) << 2; destPos[j] = i >> 1; destOff[j] = (1 - (i & 1)) << 2; } int k = destinationRegion.y * lineStride; if (isBottomUp) k += (destinationRegion.height - 1) * lineStride; for (int j = 0, y = sourceRegion.y; j < destinationRegion.height; j++, y+=scaleY) { if (abortRequested()) break; iis.read(buf, 0, lineLength); for (int i = 0; i < destinationRegion.width; i++) { //get the bit and assign to the data buffer of the raster int v = (buf[srcPos[i]] >> srcOff[i]) & 0x0F; bdata[k + destPos[i]] |= v << destOff[i]; } k += isBottomUp ? -lineStride : lineStride; iis.skipBytes(skipLength); processImageUpdate(bi, 0, j, destinationRegion.width, 1, 1, 1, new int[]{0}); processImageProgress(100.0F*j/destinationRegion.height); } } } // Method to read 8 bit BMP image data private void read8Bit(byte[] bdata) throws IOException { // Padding bytes at the end of each scanline int padding = width % 4; if (padding != 0) { padding = 4 - padding; } int lineLength = width + padding; if (noTransform) { int j = isBottomUp ? (height -1) * width : 0; for (int i=0; i= sourceRegion.y && lineNo < sourceRegion.y + sourceRegion.height) { if (noTransform) { int pos = lineNo * width; for(int i = 0; i < width; i++) bdata[pos++] = val[i]; processImageUpdate(bi, 0, lineNo, destinationRegion.width, 1, 1, 1, new int[]{0}); finished++; } else if ((lineNo - sourceRegion.y) % scaleY == 0) { int currentLine = (lineNo - sourceRegion.y) / scaleY + destinationRegion.y; int pos = currentLine * lineStride; pos += destinationRegion.x; for (int i = sourceRegion.x; i < sourceRegion.x + sourceRegion.width; i += scaleX) bdata[pos++] = val[i]; processImageUpdate(bi, 0, currentLine, destinationRegion.width, 1, 1, 1, new int[]{0}); finished++; } } processImageProgress(100.0F * finished / destinationRegion.height); lineNo += isBottomUp ? -1 : 1; l = 0; if (abortRequested()) { break; } // End-of-RLE marker if ((values[count-1] & 0xff) == 1) flag = true; break; case 2: // delta or vector marker int xoff = values[count++] & 0xff; int yoff = values[count] & 0xff; // Move to the position xoff, yoff down l += xoff + yoff*width; break; default: int end = values[count-1] & 0xff; for (int i=0; i= sourceRegion.y && lineNo < sourceRegion.y + sourceRegion.height) { if (noTransform) { int pos = lineNo * (width + 1 >> 1); for(int i = 0, j = 0; i < width >> 1; i++) bdata[pos++] = (byte)((val[j++] << 4) | val[j++]); if ((width & 1) == 1) bdata[pos] |= val[width - 1] << 4; processImageUpdate(bi, 0, lineNo, destinationRegion.width, 1, 1, 1, new int[]{0}); finished++; } else if ((lineNo - sourceRegion.y) % scaleY == 0) { int currentLine = (lineNo - sourceRegion.y) / scaleY + destinationRegion.y; int pos = currentLine * lineStride; pos += destinationRegion.x >> 1; int shift = (1 - (destinationRegion.x & 1)) << 2; for (int i = sourceRegion.x; i < sourceRegion.x + sourceRegion.width; i += scaleX) { bdata[pos] |= val[i] << shift; shift += 4; if (shift == 4) { pos++; } shift &= 7; } processImageUpdate(bi, 0, currentLine, destinationRegion.width, 1, 1, 1, new int[]{0}); finished++; } } processImageProgress(100.0F * finished / destinationRegion.height); lineNo += isBottomUp ? -1 : 1; l = 0; if (abortRequested()) { break; } // End-of-RLE marker if ((values[count-1] & 0xff) == 1) flag = true; break; case 2: // delta or vector marker int xoff = values[count++] & 0xFF; int yoff = values[count] & 0xFF; // Move to the position xoff, yoff down l += xoff + yoff*width; break; default: int end = values[count-1] & 0xFF; for (int i=0; i> 4 : (values[count++] & 0x0f)); } // When end is odd, the above for loop does not // increment count, so do it now. if ((end & 1) == 1) { count++; } // Whenever end pixels can fit into odd number of bytes, // an extra padding byte will be present, so skip that. if ((((int)Math.ceil(end/2)) & 1) ==1 ) { count++; } break; } } else { // Encoded mode int alternate[] = { (values[count] & 0xf0) >> 4, values[count] & 0x0f }; for (int i=0; (i < value) && (l < width); i++) { val[l++] = (byte)alternate[i & 1]; } count++; } // If End-of-RLE data, then exit the while loop if (flag) { break; } } } /** Decodes the jpeg/png image embedded in the bitmap using any jpeg * ImageIO-style plugin. * * @param bi The destination BufferedImage. * @param bmpParam The ImageReadParam for decoding this * BMP image. The parameters for subregion, band selection and * subsampling are used in decoding the jpeg image. */ private BufferedImage readEmbedded(int type, BufferedImage bi, ImageReadParam bmpParam) throws IOException { String format; switch(type) { case BI_JPEG: format = "JPEG"; break; case BI_PNG: format = "PNG"; break; default: throw new IOException("Unexpected compression type: " + type); } ImageReader reader = (ImageReader)ImageIO.getImageReadersByFormatName(format).next(); if (reader == null) { throw new RuntimeException(I18N.getString("BMPImageReader4") + " " + format); } // prepare input byte[] buff = new byte[(int)imageSize]; iis.read(buff); reader.setInput(ImageIO.createImageInputStream(new ByteArrayInputStream(buff))); if (bi == null) { ImageTypeSpecifier embType = (ImageTypeSpecifier)reader.getImageTypes(0).next(); bi = embType.createBufferedImage(destinationRegion.x + destinationRegion.width, destinationRegion.y + destinationRegion.height); } reader.addIIOReadProgressListener(new EmbeddedProgressAdapter() { public void imageProgress(ImageReader source, float percentageDone) { processImageProgress(percentageDone); } }); reader.addIIOReadUpdateListener(new IIOReadUpdateListener() { public void imageUpdate(ImageReader source, BufferedImage theImage, int minX, int minY, int width, int height, int periodX, int periodY, int[] bands) { processImageUpdate(theImage, minX, minY, width, height, periodX, periodY, bands); } public void passComplete(ImageReader source, BufferedImage theImage) { processPassComplete(theImage); } public void passStarted(ImageReader source, BufferedImage theImage, int pass, int minPass, int maxPass, int minX, int minY, int periodX, int periodY, int[] bands) { processPassStarted(theImage, pass, minPass, maxPass, minX, minY, periodX, periodY, bands); } public void thumbnailPassComplete(ImageReader source, BufferedImage thumb) {} public void thumbnailPassStarted(ImageReader source, BufferedImage thumb, int pass, int minPass, int maxPass, int minX, int minY, int periodX, int periodY, int[] bands) {} public void thumbnailUpdate(ImageReader source, BufferedImage theThumbnail, int minX, int minY, int width, int height, int periodX, int periodY, int[] bands) {} }); reader.addIIOReadWarningListener(new IIOReadWarningListener() { public void warningOccurred(ImageReader source, String warning) { processWarningOccurred(warning); } }); ImageReadParam param = reader.getDefaultReadParam(); param.setDestination(bi); param.setDestinationBands(bmpParam.getDestinationBands()); param.setDestinationOffset(bmpParam.getDestinationOffset()); param.setSourceBands(bmpParam.getSourceBands()); param.setSourceRegion(bmpParam.getSourceRegion()); param.setSourceSubsampling(bmpParam.getSourceXSubsampling(), bmpParam.getSourceYSubsampling(), bmpParam.getSubsamplingXOffset(), bmpParam.getSubsamplingYOffset()); reader.read(0, param); return bi; } private class EmbeddedProgressAdapter implements IIOReadProgressListener { public void imageComplete(ImageReader src) {} public void imageProgress(ImageReader src, float percentageDone) {} public void imageStarted(ImageReader src, int imageIndex) {} public void thumbnailComplete(ImageReader src) {} public void thumbnailProgress(ImageReader src, float percentageDone) {} public void thumbnailStarted(ImageReader src, int iIdx, int tIdx) {} public void sequenceComplete(ImageReader src) {} public void sequenceStarted(ImageReader src, int minIndex) {} public void readAborted(ImageReader src) {} } } ././@LongLink0000000000000000000000000000015500000000000011566 Lustar rootrootjai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/bmp/BMPMetadataFormatResources.javajai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/bmp/BMPMetadataFormatResour0000664000175100017510000000653310420012052032554 0ustar tilletille/* * $RCSfile: BMPMetadataFormatResources.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.2 $ * $Date: 2006-04-14 21:29:14 $ * $State: Exp $ */ package com.sun.media.imageioimpl.plugins.bmp; import java.util.ListResourceBundle; import javax.imageio.metadata.IIOMetadataFormat; import javax.imageio.metadata.IIOMetadataFormatImpl; public class BMPMetadataFormatResources extends ListResourceBundle { public BMPMetadataFormatResources() {} protected Object[][] getContents() { return new Object[][] { // Node name, followed by description { "BMPVersion", "BMP version string" }, { "Width", "The width of the image" }, { "Height","The height of the image" }, { "BitsPerPixel", "" }, { "PixelsPerMeter", "Resolution in pixels per unit distance" }, { "X", "Pixels Per Meter along X" }, { "Y", "Pixels Per Meter along Y" }, { "ColorsUsed", "Number of color indexes in the color table actually used" }, { "ColorsImportant", "Number of color indexes considered important for display" }, { "Mask", "Color masks; present for BI_BITFIELDS compression only"}, { "Intent", "Rendering intent" }, { "Palette", "The color palette" }, { "Red", "Red Mask/Color Palette" }, { "Green", "Green Mask/Color Palette/Gamma" }, { "Blue", "Blue Mask/Color Palette/Gamma" }, { "Alpha", "Alpha Mask/Color Palette/Gamma" }, { "ColorSpaceType", "Color Space Type" }, { "X", "The X coordinate of a point in XYZ color space" }, { "Y", "The Y coordinate of a point in XYZ color space" }, { "Z", "The Z coordinate of a point in XYZ color space" }, }; } } jai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/bmp/BMPMetadataFormat.java0000664000175100017510000002104710420012052032271 0ustar tilletille/* * $RCSfile: BMPMetadataFormat.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.2 $ * $Date: 2006-04-14 21:29:14 $ * $State: Exp $ */ package com.sun.media.imageioimpl.plugins.bmp; import java.util.Arrays; import javax.imageio.ImageTypeSpecifier; import javax.imageio.metadata.IIOMetadataFormat; import javax.imageio.metadata.IIOMetadataFormatImpl; public class BMPMetadataFormat extends IIOMetadataFormatImpl { private static IIOMetadataFormat instance = null; private BMPMetadataFormat() { super(BMPMetadata.nativeMetadataFormatName, CHILD_POLICY_SOME); // root -> ImageDescriptor addElement("ImageDescriptor", BMPMetadata.nativeMetadataFormatName, CHILD_POLICY_EMPTY); addAttribute("ImageDescriptor", "bmpVersion", DATATYPE_STRING, true, null); addAttribute("ImageDescriptor", "width", DATATYPE_INTEGER, true, null, "0", "65535", true, true); addAttribute("ImageDescriptor", "height", DATATYPE_INTEGER, true, null, "1", "65535", true, true); addAttribute("ImageDescriptor", "bitsPerPixel", DATATYPE_INTEGER, true, null, "1", "65535", true, true); addAttribute("ImageDescriptor", "compression", DATATYPE_INTEGER, false, null); addAttribute("ImageDescriptor", "imageSize", DATATYPE_INTEGER, true, null, "1", "65535", true, true); addElement("PixelsPerMeter", BMPMetadata.nativeMetadataFormatName, CHILD_POLICY_EMPTY); addAttribute("PixelsPerMeter", "X", DATATYPE_INTEGER, false, null, "1", "65535", true, true); addAttribute("PixelsPerMeter", "Y", DATATYPE_INTEGER, false, null, "1", "65535", true, true); addElement("ColorsUsed", BMPMetadata.nativeMetadataFormatName, CHILD_POLICY_EMPTY); addAttribute("ColorsUsed", "value", DATATYPE_INTEGER, true, null, "0", "65535", true, true); addElement("ColorsImportant", BMPMetadata.nativeMetadataFormatName, CHILD_POLICY_EMPTY); addAttribute("ColorsImportant", "value", DATATYPE_INTEGER, false, null, "0", "65535", true, true); addElement("BI_BITFIELDS_Mask", BMPMetadata.nativeMetadataFormatName, CHILD_POLICY_EMPTY); addAttribute("BI_BITFIELDS_Mask", "red", DATATYPE_INTEGER, false, null, "0", "65535", true, true); addAttribute("BI_BITFIELDS_Mask", "green", DATATYPE_INTEGER, false, null, "0", "65535", true, true); addAttribute("BI_BITFIELDS_Mask", "blue", DATATYPE_INTEGER, false, null, "0", "65535", true, true); addElement("ColorSpace", BMPMetadata.nativeMetadataFormatName, CHILD_POLICY_EMPTY); addAttribute("ColorSpace", "value", DATATYPE_INTEGER, false, null, "0", "65535", true, true); addElement("LCS_CALIBRATED_RGB", BMPMetadata.nativeMetadataFormatName, CHILD_POLICY_EMPTY); /// Should the max value be 1.7976931348623157e+308 ? addAttribute("LCS_CALIBRATED_RGB", "redX", DATATYPE_DOUBLE, false, null, "0", "65535", true, true); addAttribute("LCS_CALIBRATED_RGB", "redY", DATATYPE_DOUBLE, false, null, "0", "65535", true, true); addAttribute("LCS_CALIBRATED_RGB", "redZ", DATATYPE_DOUBLE, false, null, "0", "65535", true, true); addAttribute("LCS_CALIBRATED_RGB", "greenX", DATATYPE_DOUBLE, false, null, "0", "65535", true, true); addAttribute("LCS_CALIBRATED_RGB", "greenY", DATATYPE_DOUBLE, false, null, "0", "65535", true, true); addAttribute("LCS_CALIBRATED_RGB", "greenZ", DATATYPE_DOUBLE, false, null, "0", "65535", true, true); addAttribute("LCS_CALIBRATED_RGB", "blueX", DATATYPE_DOUBLE, false, null, "0", "65535", true, true); addAttribute("LCS_CALIBRATED_RGB", "blueY", DATATYPE_DOUBLE, false, null, "0", "65535", true, true); addAttribute("LCS_CALIBRATED_RGB", "blueZ", DATATYPE_DOUBLE, false, null, "0", "65535", true, true); addElement("LCS_CALIBRATED_RGB_GAMMA", BMPMetadata.nativeMetadataFormatName, CHILD_POLICY_EMPTY); addAttribute("LCS_CALIBRATED_RGB_GAMMA","red", DATATYPE_INTEGER, false, null, "0", "65535", true, true); addAttribute("LCS_CALIBRATED_RGB_GAMMA","green", DATATYPE_INTEGER, false, null, "0", "65535", true, true); addAttribute("LCS_CALIBRATED_RGB_GAMMA","blue", DATATYPE_INTEGER, false, null, "0", "65535", true, true); addElement("Intent", BMPMetadata.nativeMetadataFormatName, CHILD_POLICY_EMPTY); addAttribute("Intent", "value", DATATYPE_INTEGER, false, null, "0", "65535", true, true); // root -> Palette addElement("Palette", BMPMetadata.nativeMetadataFormatName, 2, 256); addAttribute("Palette", "sizeOfPalette", DATATYPE_INTEGER, true, null); addBooleanAttribute("Palette", "sortFlag", false, false); // root -> Palette -> PaletteEntry addElement("PaletteEntry", "Palette", CHILD_POLICY_EMPTY); addAttribute("PaletteEntry", "index", DATATYPE_INTEGER, true, null, "0", "255", true, true); addAttribute("PaletteEntry", "red", DATATYPE_INTEGER, true, null, "0", "255", true, true); addAttribute("PaletteEntry", "green", DATATYPE_INTEGER, true, null, "0", "255", true, true); addAttribute("PaletteEntry", "blue", DATATYPE_INTEGER, true, null, "0", "255", true, true); // root -> CommentExtensions addElement("CommentExtensions", BMPMetadata.nativeMetadataFormatName, 1, Integer.MAX_VALUE); // root -> CommentExtensions -> CommentExtension addElement("CommentExtension", "CommentExtensions", CHILD_POLICY_EMPTY); addAttribute("CommentExtension", "value", DATATYPE_STRING, true, null); } public boolean canNodeAppear(String elementName, ImageTypeSpecifier imageType) { return true; } public static synchronized IIOMetadataFormat getInstance() { if (instance == null) { instance = new BMPMetadataFormat(); } return instance; } } jai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/bmp/properties0000664000175100017510000000222010203036165030317 0ustar tilletille# # $RCSfile: properties,v $ # # Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved. # # Use is subject to license terms. # # $Revision: 1.1 $ # $Date: 2005-02-11 05:01:26 $ # $State: Exp $ # # Internationalization file for com.sun.media.imageioimpl.plugins.bmp BMPImageReader0=Only one image exists in the stream. BMPImageReader1=Invalid magic value for BMP file. BMPImageReader2=Invalid compression specified in BMP stream. BMPImageReader3=New BMP version not implemented yet. BMPImageReader4=No ImageIO-style reader is found for BMPImageReader5=Input has not been set. BMPImageWriter0=Output is not an ImageOutputStream. BMPImageWriter1=The image region to be encoded is empty. BMPImageWriter2=Only 1 or 3 band image is encoded. BMPImageWriter3=The maximum pixel size should be 32. BMPImageWriter4=Only version 3 is supported. BMPImageWriter5=No ImageIO-style writer is found for BMPImageWriter6=Compression type BI_BITFIELDS should be used for 16 bpp or 32 bpp or 32 bpp images only. BMPImageWriter7=Output has not been set. BMPImageWriter8=Image is null! BMPMetadata0=The provided metadata format isn't recognized. BMPMetadata1=Metadata is read-only. jai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/bmp/I18N.java0000664000175100017510000000420510203036165027527 0ustar tilletille/* * $RCSfile: I18N.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.1 $ * $Date: 2005-02-11 05:01:26 $ * $State: Exp $ */ package com.sun.media.imageioimpl.plugins.bmp; import com.sun.media.imageioimpl.common.I18NImpl; final class I18N extends I18NImpl { static String getString(String key) { return getString("com.sun.media.imageioimpl.plugins.bmp.I18N", key); } } jai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/bmp/BMPConstants.java0000664000175100017510000000550710203036165031371 0ustar tilletille/* * $RCSfile: BMPConstants.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.1 $ * $Date: 2005-02-11 05:01:24 $ * $State: Exp $ */ package com.sun.media.imageioimpl.plugins.bmp; public interface BMPConstants { // bmp versions static final String VERSION_2 = "BMP v. 2.x"; static final String VERSION_3 = "BMP v. 3.x"; static final String VERSION_3_NT = "BMP v. 3.x NT"; static final String VERSION_4 = "BMP v. 4.x"; static final String VERSION_5 = "BMP v. 5.x"; // Color space types static final int LCS_CALIBRATED_RGB = 0; static final int LCS_sRGB = 1; static final int LCS_WINDOWS_COLOR_SPACE = 2; static final int PROFILE_LINKED = 3; static final int PROFILE_EMBEDDED = 4; // Compression Types static final int BI_RGB = 0; static final int BI_RLE8 = 1; static final int BI_RLE4 = 2; static final int BI_BITFIELDS = 3; static final int BI_JPEG = 4; static final int BI_PNG = 5; static final String[] compressionTypeNames = {"BI_RGB", "BI_RLE8", "BI_RLE4", "BI_BITFIELDS", "BI_JPEG", "BI_PNG"}; } jai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/wbmp/0000775000175100017510000000000011650556207026406 5ustar tilletillejai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/wbmp/WBMPMetadata.java0000664000175100017510000001347110407644152031461 0ustar tilletille/* * $RCSfile: WBMPMetadata.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.2 $ * $Date: 2006-03-21 00:27:22 $ * $State: Exp $ */ package com.sun.media.imageioimpl.plugins.wbmp; import java.io.UnsupportedEncodingException; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import javax.imageio.ImageTypeSpecifier; import javax.imageio.metadata.IIOMetadata; import javax.imageio.metadata.IIOMetadataNode; import javax.imageio.metadata.IIOMetadataFormat; import javax.imageio.metadata.IIOMetadataFormatImpl; import org.w3c.dom.Node; import com.sun.media.imageioimpl.common.ImageUtil; public class WBMPMetadata extends IIOMetadata { public static final String nativeMetadataFormatName = "com_sun_media_imageio_plugins_wbmp_image_1.0"; public int wbmpType; public int width; public int height; public WBMPMetadata() { super(true, nativeMetadataFormatName, "com.sun.media.imageioimpl.plugins.wbmp.WBMPMetadataFormat", null, null); } public boolean isReadOnly() { return true; } public Node getAsTree(String formatName) { if (formatName.equals(nativeMetadataFormatName)) { return getNativeTree(); } else if (formatName.equals (IIOMetadataFormatImpl.standardMetadataFormatName)) { return getStandardTree(); } else { throw new IllegalArgumentException(I18N.getString("WBMPMetadata0")); } } private Node getNativeTree() { IIOMetadataNode root = new IIOMetadataNode(nativeMetadataFormatName); addChildNode(root, "WBMPType", new Integer(wbmpType)); addChildNode(root, "Width", new Integer(width)); addChildNode(root, "Height", new Integer(height)); return root; } public void setFromTree(String formatName, Node root) { throw new IllegalStateException(I18N.getString("WBMPMetadata1")); } public void mergeTree(String formatName, Node root) { throw new IllegalStateException(I18N.getString("WBMPMetadata1")); } public void reset() { throw new IllegalStateException(I18N.getString("WBMPMetadata1")); } private IIOMetadataNode addChildNode(IIOMetadataNode root, String name, Object object) { IIOMetadataNode child = new IIOMetadataNode(name); if (object != null) { child.setUserObject(object); child.setNodeValue(ImageUtil.convertObjectToString(object)); } root.appendChild(child); return child; } protected IIOMetadataNode getStandardChromaNode() { IIOMetadataNode node = new IIOMetadataNode("Chroma"); IIOMetadataNode subNode = new IIOMetadataNode("ColorSpaceType"); subNode.setAttribute("name", "GRAY"); node.appendChild(subNode); subNode = new IIOMetadataNode("NumChannels"); subNode.setAttribute("value", "1"); node.appendChild(subNode); subNode = new IIOMetadataNode("BlackIsZero"); subNode.setAttribute("value", "TRUE"); node.appendChild(subNode); return node; } protected IIOMetadataNode getStandardDataNode() { IIOMetadataNode node = new IIOMetadataNode("Data"); IIOMetadataNode subNode = new IIOMetadataNode("SampleFormat"); subNode.setAttribute("value", "UnsignedIntegral"); node.appendChild(subNode); subNode = new IIOMetadataNode("BitsPerSample"); subNode.setAttribute("value", "1"); node.appendChild(subNode); return node; } protected IIOMetadataNode getStandardDimensionNode() { IIOMetadataNode dimension_node = new IIOMetadataNode("Dimension"); IIOMetadataNode node = null; // scratch node // PixelAspectRatio not in image node = new IIOMetadataNode("ImageOrientation"); node.setAttribute("value", "Normal"); dimension_node.appendChild(node); return dimension_node; } } ././@LongLink0000000000000000000000000000014600000000000011566 Lustar rootrootjai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/wbmp/WBMPMetadataFormat.javajai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/wbmp/WBMPMetadataFormat.jav0000664000175100017510000000636510203036165032466 0ustar tilletille/* * $RCSfile: WBMPMetadataFormat.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.1 $ * $Date: 2005-02-11 05:01:52 $ * $State: Exp $ */ package com.sun.media.imageioimpl.plugins.wbmp; import java.util.Arrays; import javax.imageio.ImageTypeSpecifier; import javax.imageio.metadata.IIOMetadataFormat; import javax.imageio.metadata.IIOMetadataFormatImpl; class WBMPMetadataFormat extends IIOMetadataFormatImpl { private static IIOMetadataFormat instance = null; private WBMPMetadataFormat() { super(WBMPMetadata.nativeMetadataFormatName, CHILD_POLICY_SOME); // root -> ImageDescriptor addElement("ImageDescriptor", WBMPMetadata.nativeMetadataFormatName, CHILD_POLICY_EMPTY); addAttribute("ImageDescriptor", "WBMPType", DATATYPE_INTEGER, true, "0"); addAttribute("ImageDescriptor", "Width", DATATYPE_INTEGER, true, null, "0", "65535", true, true); addAttribute("ImageDescriptor", "Height", DATATYPE_INTEGER, true, null, "1", "65535", true, true); } public boolean canNodeAppear(String elementName, ImageTypeSpecifier imageType) { return true; } public static synchronized IIOMetadataFormat getInstance() { if (instance == null) { instance = new WBMPMetadataFormat(); } return instance; } } jai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/wbmp/WBMPImageReader.java0000664000175100017510000002641510422020422032071 0ustar tilletille/* * $RCSfile: WBMPImageReader.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.2 $ * $Date: 2006-04-21 00:02:26 $ * $State: Exp $ */ package com.sun.media.imageioimpl.plugins.wbmp; import java.awt.Rectangle; import java.awt.image.BufferedImage; import java.awt.image.DataBufferByte; import java.awt.image.MultiPixelPackedSampleModel; import java.awt.image.Raster; import java.awt.image.WritableRaster; import javax.imageio.IIOException; import javax.imageio.ImageReader; import javax.imageio.ImageReadParam; import javax.imageio.ImageTypeSpecifier; import javax.imageio.metadata.IIOMetadata; import javax.imageio.spi.ImageReaderSpi; import javax.imageio.stream.ImageInputStream; import java.io.*; import java.util.ArrayList; import java.util.Iterator; import com.sun.media.imageioimpl.common.ImageUtil; /** This class is the Java Image IO plugin reader for WBMP images. * It may subsample the image, clip the image, * and shift the decoded image origin if the proper decoding parameter * are set in the provided WBMPImageReadParam. */ public class WBMPImageReader extends ImageReader { /** The input stream where reads from */ private ImageInputStream iis = null; /** Indicates whether the header is read. */ private boolean gotHeader = false; /** The stream position where the image data starts. */ private long imageDataOffset; /** The original image width. */ private int width; /** The original image height. */ private int height; private int wbmpType; private WBMPMetadata metadata; /** Constructs WBMPImageReader from the provided * ImageReaderSpi. */ public WBMPImageReader(ImageReaderSpi originator) { super(originator); } /** Overrides the method defined in the superclass. */ public void setInput(Object input, boolean seekForwardOnly, boolean ignoreMetadata) { super.setInput(input, seekForwardOnly, ignoreMetadata); iis = (ImageInputStream) input; // Always works gotHeader = false; } /** Overrides the method defined in the superclass. */ public int getNumImages(boolean allowSearch) throws IOException { if (iis == null) { throw new IllegalStateException(I18N.getString("GetNumImages0")); } if (seekForwardOnly && allowSearch) { throw new IllegalStateException(I18N.getString("GetNumImages1")); } return 1; } public int getWidth(int imageIndex) throws IOException { checkIndex(imageIndex); readHeader(); return width; } public int getHeight(int imageIndex) throws IOException { checkIndex(imageIndex); readHeader(); return height; } public boolean isRandomAccessEasy(int imageIndex) throws IOException { checkIndex(imageIndex); return true; } private void checkIndex(int imageIndex) { if (imageIndex != 0) { throw new IndexOutOfBoundsException(I18N.getString("WBMPImageReader0")); } } public void readHeader() throws IOException { if (gotHeader) { // Seek to where the image data starts, since that is where // the stream pointer should be after header is read iis.seek(imageDataOffset); return; } if (iis == null) { throw new IllegalStateException(I18N.getString("WBMPImageReader1")); } metadata = new WBMPMetadata(); wbmpType = iis.readByte(); // TypeField byte fixHeaderField = iis.readByte(); // check for valid wbmp image if (fixHeaderField != 0 || !isValidWbmpType(wbmpType)) { throw new IIOException(I18N.getString("WBMPImageReader2")); } metadata.wbmpType = wbmpType; // Read image width width = ImageUtil.readMultiByteInteger(iis); metadata.width = width; // Read image height height = ImageUtil.readMultiByteInteger(iis); metadata.height = height; gotHeader = true; // Store the stream position where the image data starts imageDataOffset = iis.getStreamPosition(); } public Iterator getImageTypes(int imageIndex) throws IOException { checkIndex(imageIndex); readHeader(); BufferedImage bi = new BufferedImage(1, 1, BufferedImage.TYPE_BYTE_BINARY); ArrayList list = new ArrayList(1); list.add(new ImageTypeSpecifier(bi)); return list.iterator(); } public ImageReadParam getDefaultReadParam() { return new ImageReadParam(); } public IIOMetadata getImageMetadata(int imageIndex) throws IOException { checkIndex(imageIndex); if (metadata == null) { readHeader(); } return metadata; } public IIOMetadata getStreamMetadata() throws IOException { return null; } public BufferedImage read(int imageIndex, ImageReadParam param) throws IOException { if (iis == null) { throw new IllegalStateException(I18N.getString("WBMPImageReader1")); } checkIndex(imageIndex); clearAbortRequest(); processImageStarted(imageIndex); if (param == null) param = getDefaultReadParam(); //read header readHeader(); Rectangle sourceRegion = new Rectangle(0, 0, 0, 0); Rectangle destinationRegion = new Rectangle(0, 0, 0, 0); computeRegions(param, this.width, this.height, param.getDestination(), sourceRegion, destinationRegion); int scaleX = param.getSourceXSubsampling(); int scaleY = param.getSourceYSubsampling(); int xOffset = param.getSubsamplingXOffset(); int yOffset = param.getSubsamplingYOffset(); // If the destination is provided, then use it. Otherwise, create new one BufferedImage bi = param.getDestination(); if (bi == null) bi = new BufferedImage(destinationRegion.x + destinationRegion.width, destinationRegion.y + destinationRegion.height, BufferedImage.TYPE_BYTE_BINARY); boolean noTransform = destinationRegion.equals(new Rectangle(0, 0, width, height)) && destinationRegion.equals(new Rectangle(0, 0, bi.getWidth(), bi.getHeight())); // Get the image data. WritableRaster tile = bi.getWritableTile(0, 0); // Get the SampleModel. MultiPixelPackedSampleModel sm = (MultiPixelPackedSampleModel)bi.getSampleModel(); if (noTransform) { if (abortRequested()) { processReadAborted(); return bi; } // If noTransform is necessary, read the data. iis.read(((DataBufferByte)tile.getDataBuffer()).getData(), 0, height*sm.getScanlineStride()); processImageUpdate(bi, 0, 0, width, height, 1, 1, new int[]{0}); processImageProgress(100.0F); } else { int len = (this.width + 7) / 8; byte[] buf = new byte[len]; byte[] data = ((DataBufferByte)tile.getDataBuffer()).getData(); int lineStride = sm.getScanlineStride(); iis.skipBytes(len * sourceRegion.y); int skipLength = len * (scaleY - 1); // cache the values to avoid duplicated computation int[] srcOff = new int[destinationRegion.width]; int[] destOff = new int[destinationRegion.width]; int[] srcPos = new int[destinationRegion.width]; int[] destPos = new int[destinationRegion.width]; for (int i = destinationRegion.x, x = sourceRegion.x, j = 0; i < destinationRegion.x + destinationRegion.width; i++, j++, x += scaleX) { srcPos[j] = x >> 3; srcOff[j] = 7 - (x & 7); destPos[j] = i >> 3; destOff[j] = 7 - (i & 7); } for (int j = 0, y = sourceRegion.y, k = destinationRegion.y * lineStride; j < destinationRegion.height; j++, y+=scaleY) { if (abortRequested()) break; iis.read(buf, 0, len); for (int i = 0; i < destinationRegion.width; i++) { //get the bit and assign to the data buffer of the raster int v = (buf[srcPos[i]] >> srcOff[i]) & 1; data[k + destPos[i]] |= v << destOff[i]; } k += lineStride; iis.skipBytes(skipLength); processImageUpdate(bi, 0, j, destinationRegion.width, 1, 1, 1, new int[]{0}); processImageProgress(100.0F*j/destinationRegion.height); } } if (abortRequested()) processReadAborted(); else processImageComplete(); return bi; } public boolean canReadRaster() { return true; } public Raster readRaster(int imageIndex, ImageReadParam param) throws IOException { BufferedImage bi = read(imageIndex, param); return bi.getData(); } public void reset() { super.reset(); iis = null; gotHeader = false; } /* * This method verifies that given byte is valid wbmp type marker. * At the moment only 0x0 marker is described by wbmp spec. */ boolean isValidWbmpType(int type) { return type == 0; } } ././@LongLink0000000000000000000000000000014600000000000011566 Lustar rootrootjai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/wbmp/WBMPImageReaderSpi.javajai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/wbmp/WBMPImageReaderSpi.jav0000664000175100017510000001200210422020455032375 0ustar tilletille/* * $RCSfile: WBMPImageReaderSpi.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.3 $ * $Date: 2006-04-21 00:02:53 $ * $State: Exp $ */ package com.sun.media.imageioimpl.plugins.wbmp; import java.util.Locale; import javax.imageio.spi.ImageReaderSpi; import javax.imageio.stream.ImageInputStream; import javax.imageio.spi.IIORegistry; import javax.imageio.spi.ServiceRegistry; import java.io.IOException; import javax.imageio.ImageReader; import javax.imageio.IIOException; import com.sun.media.imageioimpl.common.PackageUtil; import com.sun.media.imageioimpl.common.ImageUtil; public class WBMPImageReaderSpi extends ImageReaderSpi { private static String [] writerSpiNames = {"com.sun.media.imageioimpl.plugins.wbmp.WBMPImageWriterSpi"}; private static String[] formatNames = {"wbmp", "WBMP"}; private static String[] entensions = {"wbmp"}; private static String[] mimeType = {"image/vnd.wap.wbmp"}; private boolean registered = false; public WBMPImageReaderSpi() { super(PackageUtil.getVendor(), PackageUtil.getVersion(), formatNames, entensions, mimeType, "com.sun.media.imageioimpl.plugins.wbmp.WBMPImageReader", STANDARD_INPUT_TYPE, writerSpiNames, true, null, null, null, null, true, WBMPMetadata.nativeMetadataFormatName, "com.sun.media.imageioimpl.plugins.wbmp.WBMPMetadataFormat", null, null); } public void onRegistration(ServiceRegistry registry, Class category) { if (registered) { return; } registered = true; // By JDK 1.7, the WBMPImageReader will have been in JDK core for // atleast two FCS releases, so we can set JIIO's to lower priority // With JDK 1.8, we can entirely de-register the JIIO one ImageUtil.processOnRegistration(registry, category, "WBMP", this, 8, 7); // JDK version 1.8, 1.7 } public String getDescription(Locale locale) { String desc = PackageUtil.getSpecificationTitle() + " WBMP Image Reader"; return desc; } public boolean canDecodeInput(Object source) throws IOException { if (!(source instanceof ImageInputStream)) { return false; } ImageInputStream stream = (ImageInputStream)source; stream.mark(); int type = stream.readByte(); // TypeField byte fixHeaderField = stream.readByte(); int width = ImageUtil.readMultiByteInteger(stream); int height = ImageUtil.readMultiByteInteger(stream); long remainingBytes = stream.length() - stream.getStreamPosition(); stream.reset(); // check WBMP "header" if (type != 0 || fixHeaderField != 0) { // while WBMP reader does not support ext WBMP headers return false; } // check image dimension if (width <= 0 || height <= 0) { return false; } long scanSize = (width / 8) + ((width % 8) == 0 ? 0 : 1); return (remainingBytes == scanSize * height); } public ImageReader createReaderInstance(Object extension) throws IIOException { return new WBMPImageReader(this); } } jai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/wbmp/WBMPImageWriter.java0000664000175100017510000002774110203036165032156 0ustar tilletille/* * $RCSfile: WBMPImageWriter.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.1 $ * $Date: 2005-02-11 05:01:52 $ * $State: Exp $ */ package com.sun.media.imageioimpl.plugins.wbmp; import java.awt.Point; import java.awt.Rectangle; import java.awt.image.ColorModel; import java.awt.image.DataBuffer; import java.awt.image.DataBufferByte; import java.awt.image.IndexColorModel; import java.awt.image.MultiPixelPackedSampleModel; import java.awt.image.Raster; import java.awt.image.RenderedImage; import java.awt.image.SampleModel; import java.awt.image.WritableRaster; import java.io.IOException; import javax.imageio.IIOImage; import javax.imageio.IIOException; import javax.imageio.ImageTypeSpecifier; import javax.imageio.ImageWriteParam; import javax.imageio.ImageWriter; import javax.imageio.metadata.IIOMetadata; import javax.imageio.metadata.IIOMetadataFormatImpl; import javax.imageio.metadata.IIOInvalidTreeException; import javax.imageio.spi.ImageWriterSpi; import javax.imageio.stream.ImageOutputStream; /** * The Java Image IO plugin writer for encoding a binary RenderedImage into * a WBMP format. * * The encoding process may clip, subsample using the parameters * specified in the ImageWriteParam. * * @see com.sun.media.imageio.plugins.WBMPImageWriteParam */ public class WBMPImageWriter extends ImageWriter { /** The output stream to write into */ private ImageOutputStream stream = null; // Get the number of bits required to represent an int. private static int getNumBits(int intValue) { int numBits = 32; int mask = 0x80000000; while(mask != 0 && (intValue & mask) == 0) { numBits--; mask >>>= 1; } return numBits; } // Convert an int value to WBMP multi-byte format. private static byte[] intToMultiByte(int intValue) { int numBitsLeft = getNumBits(intValue); byte[] multiBytes = new byte[(numBitsLeft + 6)/7]; int maxIndex = multiBytes.length - 1; for(int b = 0; b <= maxIndex; b++) { multiBytes[b] = (byte)((intValue >>> ((maxIndex - b)*7))&0x7f); if(b != maxIndex) { multiBytes[b] |= (byte)0x80; } } return multiBytes; } /** Constructs WBMPImageWriter based on the provided * ImageWriterSpi. */ public WBMPImageWriter(ImageWriterSpi originator) { super(originator); } public void setOutput(Object output) { super.setOutput(output); // validates output if (output != null) { if (!(output instanceof ImageOutputStream)) throw new IllegalArgumentException(I18N.getString("WBMPImageWriter")); this.stream = (ImageOutputStream)output; } else this.stream = null; } public IIOMetadata getDefaultStreamMetadata(ImageWriteParam param) { return null; } public IIOMetadata getDefaultImageMetadata(ImageTypeSpecifier imageType, ImageWriteParam param) { WBMPMetadata meta = new WBMPMetadata(); meta.wbmpType = 0; // default wbmp level return meta; } public IIOMetadata convertStreamMetadata(IIOMetadata inData, ImageWriteParam param) { return null; } public IIOMetadata convertImageMetadata(IIOMetadata metadata, ImageTypeSpecifier type, ImageWriteParam param) { return null; } public boolean canWriteRasters() { return true; } public void write(IIOMetadata streamMetadata, IIOImage image, ImageWriteParam param) throws IOException { if (stream == null) { throw new IllegalStateException(I18N.getString("WBMPImageWriter3")); } if (image == null) { throw new IllegalArgumentException(I18N.getString("WBMPImageWriter4")); } clearAbortRequest(); processImageStarted(0); if (param == null) param = getDefaultWriteParam(); RenderedImage input = null; Raster inputRaster = null; boolean writeRaster = image.hasRaster(); Rectangle sourceRegion = param.getSourceRegion(); SampleModel sampleModel = null; if (writeRaster) { inputRaster = image.getRaster(); sampleModel = inputRaster.getSampleModel(); } else { input = image.getRenderedImage(); sampleModel = input.getSampleModel(); inputRaster = input.getData(); } checkSampleModel(sampleModel); if (sourceRegion == null) sourceRegion = inputRaster.getBounds(); else sourceRegion = sourceRegion.intersection(inputRaster.getBounds()); if (sourceRegion.isEmpty()) throw new RuntimeException(I18N.getString("WBMPImageWriter1")); int scaleX = param.getSourceXSubsampling(); int scaleY = param.getSourceYSubsampling(); int xOffset = param.getSubsamplingXOffset(); int yOffset = param.getSubsamplingYOffset(); sourceRegion.translate(xOffset, yOffset); sourceRegion.width -= xOffset; sourceRegion.height -= yOffset; int minX = sourceRegion.x / scaleX; int minY = sourceRegion.y / scaleY; int w = (sourceRegion.width + scaleX - 1) / scaleX; int h = (sourceRegion.height + scaleY - 1) / scaleY; Rectangle destinationRegion = new Rectangle(minX, minY, w, h); sampleModel = sampleModel.createCompatibleSampleModel(w, h); SampleModel destSM= sampleModel; // If the data are not formatted nominally then reformat. if(sampleModel.getDataType() != DataBuffer.TYPE_BYTE || !(sampleModel instanceof MultiPixelPackedSampleModel) || ((MultiPixelPackedSampleModel)sampleModel).getDataBitOffset() != 0) { destSM = new MultiPixelPackedSampleModel(DataBuffer.TYPE_BYTE, w, h, 1, w + 7 >> 3, 0); } if (!destinationRegion.equals(sourceRegion)) { if (scaleX == 1 && scaleY == 1) inputRaster = inputRaster.createChild(inputRaster.getMinX(), inputRaster.getMinY(), w, h, minX, minY, null); else { WritableRaster ras = Raster.createWritableRaster(destSM, new Point(minX, minY)); byte[] data = ((DataBufferByte)ras.getDataBuffer()).getData(); for(int j = minY, y = sourceRegion.y, k = 0; j < minY + h; j++, y += scaleY) { for (int i = 0, x = sourceRegion.x; i > 3)] |= v << (7 - (i & 7)); } k += w + 7 >> 3; } inputRaster = ras; } } // If the data are not formatted nominally then reformat. if(!destSM.equals(inputRaster.getSampleModel())) { WritableRaster raster = Raster.createWritableRaster(destSM, new Point(inputRaster.getMinX(), inputRaster.getMinY())); raster.setRect(inputRaster); inputRaster = raster; } // Check whether the image is white-is-zero. boolean isWhiteZero = false; if(!writeRaster && input.getColorModel() instanceof IndexColorModel) { IndexColorModel icm = (IndexColorModel)input.getColorModel(); isWhiteZero = icm.getRed(0) > icm.getRed(1); } // Get the line stride, bytes per row, and data array. int lineStride = ((MultiPixelPackedSampleModel)destSM).getScanlineStride(); int bytesPerRow = (w + 7)/8; byte[] bdata = ((DataBufferByte)inputRaster.getDataBuffer()).getData(); // Write WBMP header. stream.write(0); // TypeField stream.write(0); // FixHeaderField stream.write(intToMultiByte(w)); // width stream.write(intToMultiByte(h)); // height // Write the data. if(!isWhiteZero && lineStride == bytesPerRow) { // Write the entire image. stream.write(bdata, 0, h * bytesPerRow); processImageProgress(100.0F); } else { // Write the image row-by-row. int offset = 0; if(!isWhiteZero) { // Black-is-zero for(int row = 0; row < h; row++) { if (abortRequested()) break; stream.write(bdata, offset, bytesPerRow); offset += lineStride; processImageProgress(100.0F * row / h); } } else { // White-is-zero: need to invert data. byte[] inverted = new byte[bytesPerRow]; for(int row = 0; row < h; row++) { if (abortRequested()) break; for(int col = 0; col < bytesPerRow; col++) { inverted[col] = (byte)(~(bdata[col+offset])); } stream.write(inverted, 0, bytesPerRow); offset += lineStride; processImageProgress(100.0F * row / h); } } } if (abortRequested()) processWriteAborted(); else { processImageComplete(); stream.flushBefore(stream.getStreamPosition()); } } public void reset() { super.reset(); stream = null; } private void checkSampleModel(SampleModel sm) { int type = sm.getDataType(); if (type < DataBuffer.TYPE_BYTE || type > DataBuffer.TYPE_INT || sm.getNumBands() != 1 || sm.getSampleSize(0) != 1) throw new IllegalArgumentException(I18N.getString("WBMPImageWriter2")); } } ././@LongLink0000000000000000000000000000014600000000000011566 Lustar rootrootjai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/wbmp/WBMPImageWriterSpi.javajai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/wbmp/WBMPImageWriterSpi.jav0000664000175100017510000001065710413303155032466 0ustar tilletille/* * $RCSfile: WBMPImageWriterSpi.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.2 $ * $Date: 2006-03-31 19:43:41 $ * $State: Exp $ */ package com.sun.media.imageioimpl.plugins.wbmp; import javax.imageio.spi.ImageWriterSpi; import javax.imageio.spi.ServiceRegistry; import javax.imageio.spi.IIORegistry; import javax.imageio.ImageWriter; import javax.imageio.ImageTypeSpecifier; import javax.imageio.IIOException; import java.awt.image.ColorModel; import java.awt.image.IndexColorModel; import java.awt.image.MultiPixelPackedSampleModel; import java.awt.image.SampleModel; import java.util.Locale; import com.sun.media.imageioimpl.common.PackageUtil; import com.sun.media.imageioimpl.common.ImageUtil; public class WBMPImageWriterSpi extends ImageWriterSpi { private static String [] readerSpiNames = {"com.sun.media.imageioimpl.plugins.wbmp.WBMPImageReaderSpi"}; private static String[] formatNames = {"wbmp", "WBMP"}; private static String[] entensions = {"wbmp"}; private static String[] mimeType = {"image/vnd.wap.wbmp"}; private boolean registered = false; public WBMPImageWriterSpi() { super(PackageUtil.getVendor(), PackageUtil.getVersion(), formatNames, entensions, mimeType, "com.sun.media.imageioimpl.plugins.wbmp.WBMPImageWriter", STANDARD_OUTPUT_TYPE, readerSpiNames, true, null, null, null, null, true, WBMPMetadata.nativeMetadataFormatName, "com.sun.media.imageioimpl.plugins.wbmp.WBMPMetadataFormat", null, null); } public String getDescription(Locale locale) { String desc = PackageUtil.getSpecificationTitle() + " WBMP Image Writer"; return desc; } public void onRegistration(ServiceRegistry registry, Class category) { if (registered) { return; } registered = true; // By JDK 1.7, the WBMPImageWriter will have been in JDK core for // atleast two FCS releases, so we can set JIIO's to lower priority // With JDK 1.8, we can entirely de-register the JIIO one ImageUtil.processOnRegistration(registry, category, "WBMP", this, 8, 7); // JDK version 1.8, 1.7 } public boolean canEncodeImage(ImageTypeSpecifier type) { SampleModel sm = type.getSampleModel(); if (!(sm instanceof MultiPixelPackedSampleModel)) return false; if (sm.getSampleSize(0) != 1) return false; return true; } public ImageWriter createWriterInstance(Object extension) throws IIOException { return new WBMPImageWriter(this); } } jai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/wbmp/properties0000664000175100017510000000136710203036165030521 0ustar tilletille# # $RCSfile: properties,v $ # # Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved. # # Use is subject to license terms. # # $Revision: 1.1 $ # $Date: 2005-02-11 05:01:52 $ # $State: Exp $ # # Internationalization file for com.sun.media.imageioimpl.plugins.wbmp WBMPImageReader0=Only one image exists in the stream. WBMPImageReader1=Input has not been set. WBMPImageReader2=Bad WBMP header. WBMPImageWriter0=Output is not an ImageOutputStream. WBMPImageWriter1=The image region to be encoded is empty. WBMPImageWriter2=Only integral single-band bilevel image is supported. WBMPImageWriter3=Output has not been set. WBMPImageWriter4=Image is null! WBMPMetadata0=The provided metadata format isn't recognized. WBMPMetadata1=Metadata is read-only. jai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/wbmp/I18N.java0000664000175100017510000000420710203036165027720 0ustar tilletille/* * $RCSfile: I18N.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.1 $ * $Date: 2005-02-11 05:01:51 $ * $State: Exp $ */ package com.sun.media.imageioimpl.plugins.wbmp; import com.sun.media.imageioimpl.common.I18NImpl; final class I18N extends I18NImpl { static String getString(String key) { return getString("com.sun.media.imageioimpl.plugins.wbmp.I18N", key); } } jai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/tiff/0000775000175100017510000000000011650556210026363 5ustar tilletille././@LongLink0000000000000000000000000000014500000000000011565 Lustar rootrootjai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/tiff/TIFFLSBCompressor.javajai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/tiff/TIFFLSBCompressor.java0000664000175100017510000000622310203036165032372 0ustar tilletille/* * $RCSfile: TIFFLSBCompressor.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.1 $ * $Date: 2005-02-11 05:01:47 $ * $State: Exp $ */ package com.sun.media.imageioimpl.plugins.tiff; import com.sun.media.imageio.plugins.tiff.BaselineTIFFTagSet; import com.sun.media.imageio.plugins.tiff.TIFFCompressor; import java.io.IOException; /** * Uncompressed data with LSB-to-MSB fill order. */ public class TIFFLSBCompressor extends TIFFCompressor { public TIFFLSBCompressor() { super("", BaselineTIFFTagSet.COMPRESSION_NONE, true); } public int encode(byte[] b, int off, int width, int height, int[] bitsPerSample, int scanlineStride) throws IOException { int bitsPerPixel = 0; for (int i = 0; i < bitsPerSample.length; i++) { bitsPerPixel += bitsPerSample[i]; } int bytesPerRow = (bitsPerPixel*width + 7)/8; byte[] compData = new byte[bytesPerRow]; byte[] flipTable = TIFFFaxDecompressor.flipTable; for (int row = 0; row < height; row++) { System.arraycopy(b, off, compData, 0, bytesPerRow); for(int j = 0; j < bytesPerRow; j++) { compData[j] = flipTable[compData[j]&0xff]; } stream.write(compData, 0, bytesPerRow); off += scanlineStride; } return height*bytesPerRow; } } ././@LongLink0000000000000000000000000000015400000000000011565 Lustar rootrootjai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/tiff/TIFFCodecLibT6Compressor.javajai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/tiff/TIFFCodecLibT6Compress0000664000175100017510000001310010367517672032361 0ustar tilletille/* * $RCSfile: TIFFCodecLibT6Compressor.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.2 $ * $Date: 2006-01-30 23:22:34 $ * $State: Exp $ */ package com.sun.media.imageioimpl.plugins.tiff; public class TIFFCodecLibT6Compressor extends TIFFT6Compressor { private static final boolean DEBUG = false; // XXX 'false' for release!!! Object encoder; public TIFFCodecLibT6Compressor() { super(); try { com.sun.medialib.codec.g4fax.Encoder encoder = new com.sun.medialib.codec.g4fax.Encoder(); this.encoder = encoder; } catch(Throwable t) { throw new RuntimeException("CodecLib not available"); } } /** * Encode a buffer of data using CCITT T.6 Compression also known as * Group 4 facsimile compression. * * @param data The row of data to compress. * @param lineStride Byte step between the same sample in different rows. * @param colOffset Bit offset within first data[rowOffset]. * @param width Number of bits in the row. * @param height Number of rows in the buffer. * @param compData The compressed data. * * @return The number of bytes saved in the compressed data array. */ public synchronized final int encodeT6(byte[] data, int lineStride, int colOffset, int width, int height, byte[] compData) { // Defer to superclass if bit offset is not byte-aligned. if(colOffset % 8 != 0) { return super.encodeT6(data, lineStride, colOffset, width, height, compData); } // Set image to data if possible; otherwise copy. int bytesPerRow = (width + 7)/8; byte[] image = null; if(colOffset == 0 && bytesPerRow == lineStride) { image = data; } else { image = new byte[bytesPerRow*height]; int dataOffset = colOffset / 8; int imageOffset = 0; for(int row = 0; row < height; row++) { System.arraycopy(data, dataOffset, image, imageOffset, bytesPerRow); dataOffset += lineStride; imageOffset += bytesPerRow; } } // Attempt the codecLib encoder. com.sun.medialib.codec.g4fax.Encoder clibEncoder = (com.sun.medialib.codec.g4fax.Encoder)encoder; //System.out.println("Using codecLib G4 encoder"); // Set encoding flags. int encodingFlags = inverseFill ? com.sun.medialib.codec.g4fax.Constants.G4FAX_LSB2MSB : 0; int result = com.sun.medialib.codec.g4fax.Constants.G4FAX_FAILURE; try { if(DEBUG) { System.out.println("Using MediaLib G4 encoder"); } result = clibEncoder.encode(compData, image, width, height, encodingFlags); } catch(Throwable t) { if(DEBUG) { System.out.println("MediaLib G4 encoder failed: "+t); } // XXX Should write a warning to listeners here. result = com.sun.medialib.codec.g4fax.Constants.G4FAX_FAILURE; } // If the codecLib encoder failed, try the superclass. if(result == com.sun.medialib.codec.g4fax.Constants.G4FAX_FAILURE) { if(DEBUG) { System.out.println("Falling back to Java G4 encoder"); } result = super.encodeT6(data, lineStride, colOffset, width, height, compData); } return result; } } ././@LongLink0000000000000000000000000000015100000000000011562 Lustar rootrootjai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/tiff/TIFFYCbCrDecompressor.javajai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/tiff/TIFFYCbCrDecompressor.0000664000175100017510000004452710447042614032402 0ustar tilletille/* * $RCSfile: TIFFYCbCrDecompressor.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.3 $ * $Date: 2006-06-23 19:48:28 $ * $State: Exp $ */ package com.sun.media.imageioimpl.plugins.tiff; import java.awt.Rectangle; import java.awt.image.BufferedImage; import java.awt.image.ColorModel; import java.awt.image.DataBufferByte; import java.io.ByteArrayInputStream; import java.io.EOFException; import java.io.IOException; import javax.imageio.ImageReader; import javax.imageio.metadata.IIOMetadata; import javax.imageio.stream.MemoryCacheImageInputStream; import javax.imageio.stream.ImageInputStream; import com.sun.media.imageio.plugins.tiff.BaselineTIFFTagSet; import com.sun.media.imageio.plugins.tiff.TIFFDecompressor; import com.sun.media.imageio.plugins.tiff.TIFFField; public class TIFFYCbCrDecompressor extends TIFFDecompressor { private static final boolean debug = false; // Store constants in S15.16 format private static final int FRAC_BITS = 16; private static final float FRAC_SCALE = (float)(1 << FRAC_BITS); private float LumaRed = 0.299f; private float LumaGreen = 0.587f; private float LumaBlue = 0.114f; private float referenceBlackY = 0.0f; private float referenceWhiteY = 255.0f; private float referenceBlackCb = 128.0f; private float referenceWhiteCb = 255.0f; private float referenceBlackCr = 128.0f; private float referenceWhiteCr = 255.0f; private float codingRangeY = 255.0f; private int[] iYTab = new int[256]; private int[] iCbTab = new int[256]; private int[] iCrTab = new int[256]; private int[] iGYTab = new int[256]; private int[] iGCbTab = new int[256]; private int[] iGCrTab = new int[256]; private int chromaSubsampleH = 2; private int chromaSubsampleV = 2; private boolean colorConvert; private TIFFDecompressor decompressor; private BufferedImage tmpImage; // // If 'decompressor' is not null then it reads the data from the // actual stream first and passes the result on to YCrCr decompression // and possibly color conversion. // public TIFFYCbCrDecompressor(TIFFDecompressor decompressor, boolean colorConvert) { this.decompressor = decompressor; this.colorConvert = colorConvert; } private void warning(String message) { if(this.reader instanceof TIFFImageReader) { ((TIFFImageReader)reader).forwardWarningMessage(message); } } // // "Chained" decompressor methods. // public void setReader(ImageReader reader) { if(decompressor != null) { decompressor.setReader(reader); } super.setReader(reader); } public void setMetadata(IIOMetadata metadata) { if(decompressor != null) { decompressor.setMetadata(metadata); } super.setMetadata(metadata); } public void setPhotometricInterpretation(int photometricInterpretation) { if(decompressor != null) { decompressor.setPhotometricInterpretation(photometricInterpretation); } super.setPhotometricInterpretation(photometricInterpretation); } public void setCompression(int compression) { if(decompressor != null) { decompressor.setCompression(compression); } super.setCompression(compression); } public void setPlanar(boolean planar) { if(decompressor != null) { decompressor.setPlanar(planar); } super.setPlanar(planar); } public void setSamplesPerPixel(int samplesPerPixel) { if(decompressor != null) { decompressor.setSamplesPerPixel(samplesPerPixel); } super.setSamplesPerPixel(samplesPerPixel); } public void setBitsPerSample(int[] bitsPerSample) { if(decompressor != null) { decompressor.setBitsPerSample(bitsPerSample); } super.setBitsPerSample(bitsPerSample); } public void setSampleFormat(int[] sampleFormat) { if(decompressor != null) { decompressor.setSampleFormat(sampleFormat); } super.setSampleFormat(sampleFormat); } public void setExtraSamples(int[] extraSamples) { if(decompressor != null) { decompressor.setExtraSamples(extraSamples); } super.setExtraSamples(extraSamples); } public void setColorMap(char[] colorMap) { if(decompressor != null) { decompressor.setColorMap(colorMap); } super.setColorMap(colorMap); } public void setStream(ImageInputStream stream) { if(decompressor != null) { decompressor.setStream(stream); } else { super.setStream(stream); } } public void setOffset(long offset) { if(decompressor != null) { decompressor.setOffset(offset); } super.setOffset(offset); } public void setByteCount(int byteCount) { if(decompressor != null) { decompressor.setByteCount(byteCount); } super.setByteCount(byteCount); } public void setSrcMinX(int srcMinX) { if(decompressor != null) { decompressor.setSrcMinX(srcMinX); } super.setSrcMinX(srcMinX); } public void setSrcMinY(int srcMinY) { if(decompressor != null) { decompressor.setSrcMinY(srcMinY); } super.setSrcMinY(srcMinY); } public void setSrcWidth(int srcWidth) { if(decompressor != null) { decompressor.setSrcWidth(srcWidth); } super.setSrcWidth(srcWidth); } public void setSrcHeight(int srcHeight) { if(decompressor != null) { decompressor.setSrcHeight(srcHeight); } super.setSrcHeight(srcHeight); } public void setSourceXOffset(int sourceXOffset) { if(decompressor != null) { decompressor.setSourceXOffset(sourceXOffset); } super.setSourceXOffset(sourceXOffset); } public void setDstXOffset(int dstXOffset) { if(decompressor != null) { decompressor.setDstXOffset(dstXOffset); } super.setDstXOffset(dstXOffset); } public void setSourceYOffset(int sourceYOffset) { if(decompressor != null) { decompressor.setSourceYOffset(sourceYOffset); } super.setSourceYOffset(sourceYOffset); } public void setDstYOffset(int dstYOffset) { if(decompressor != null) { decompressor.setDstYOffset(dstYOffset); } super.setDstYOffset(dstYOffset); } /* Should not need to override these mutators as subsampling should not be done by the wrapped decompressor. public void setSubsampleX(int subsampleX) { if(decompressor != null) { decompressor.setSubsampleX(subsampleX); } super.setSubsampleX(subsampleX); } public void setSubsampleY(int subsampleY) { if(decompressor != null) { decompressor.setSubsampleY(subsampleY); } super.setSubsampleY(subsampleY); } */ public void setSourceBands(int[] sourceBands) { if(decompressor != null) { decompressor.setSourceBands(sourceBands); } super.setSourceBands(sourceBands); } public void setDestinationBands(int[] destinationBands) { if(decompressor != null) { decompressor.setDestinationBands(destinationBands); } super.setDestinationBands(destinationBands); } public void setImage(BufferedImage image) { if(decompressor != null) { ColorModel cm = image.getColorModel(); tmpImage = new BufferedImage(cm, image.getRaster().createCompatibleWritableRaster(1, 1), cm.isAlphaPremultiplied(), null); decompressor.setImage(tmpImage); } super.setImage(image); } public void setDstMinX(int dstMinX) { if(decompressor != null) { decompressor.setDstMinX(dstMinX); } super.setDstMinX(dstMinX); } public void setDstMinY(int dstMinY) { if(decompressor != null) { decompressor.setDstMinY(dstMinY); } super.setDstMinY(dstMinY); } public void setDstWidth(int dstWidth) { if(decompressor != null) { decompressor.setDstWidth(dstWidth); } super.setDstWidth(dstWidth); } public void setDstHeight(int dstHeight) { if(decompressor != null) { decompressor.setDstHeight(dstHeight); } super.setDstHeight(dstHeight); } public void setActiveSrcMinX(int activeSrcMinX) { if(decompressor != null) { decompressor.setActiveSrcMinX(activeSrcMinX); } super.setActiveSrcMinX(activeSrcMinX); } public void setActiveSrcMinY(int activeSrcMinY) { if(decompressor != null) { decompressor.setActiveSrcMinY(activeSrcMinY); } super.setActiveSrcMinY(activeSrcMinY); } public void setActiveSrcWidth(int activeSrcWidth) { if(decompressor != null) { decompressor.setActiveSrcWidth(activeSrcWidth); } super.setActiveSrcWidth(activeSrcWidth); } public void setActiveSrcHeight(int activeSrcHeight) { if(decompressor != null) { decompressor.setActiveSrcHeight(activeSrcHeight); } super.setActiveSrcHeight(activeSrcHeight); } private byte clamp(int f) { if (f < 0) { return (byte)0; } else if (f > 255*65536) { return (byte)255; } else { return (byte)(f >> 16); } } public void beginDecoding() { if(decompressor != null) { decompressor.beginDecoding(); } TIFFImageMetadata tmetadata = (TIFFImageMetadata)metadata; TIFFField f; f = tmetadata.getTIFFField(BaselineTIFFTagSet.TAG_Y_CB_CR_SUBSAMPLING); if (f != null) { if (f.getCount() == 2) { this.chromaSubsampleH = f.getAsInt(0); this.chromaSubsampleV = f.getAsInt(1); if (chromaSubsampleH != 1 && chromaSubsampleH != 2 && chromaSubsampleH != 4) { warning("Y_CB_CR_SUBSAMPLING[0] has illegal value " + chromaSubsampleH + " (should be 1, 2, or 4), setting to 1"); chromaSubsampleH = 1; } if (chromaSubsampleV != 1 && chromaSubsampleV != 2 && chromaSubsampleV != 4) { warning("Y_CB_CR_SUBSAMPLING[1] has illegal value " + chromaSubsampleV + " (should be 1, 2, or 4), setting to 1"); chromaSubsampleV = 1; } } else { warning("Y_CB_CR_SUBSAMPLING count != 2, " + "assuming no subsampling"); } } f = tmetadata.getTIFFField(BaselineTIFFTagSet.TAG_Y_CB_CR_COEFFICIENTS); if (f != null) { if (f.getCount() == 3) { this.LumaRed = f.getAsFloat(0); this.LumaGreen = f.getAsFloat(1); this.LumaBlue = f.getAsFloat(2); } else { warning("Y_CB_CR_COEFFICIENTS count != 3, " + "assuming default values for CCIR 601-1"); } } f = tmetadata.getTIFFField(BaselineTIFFTagSet.TAG_REFERENCE_BLACK_WHITE); if (f != null) { if (f.getCount() == 6) { this.referenceBlackY = f.getAsFloat(0); this.referenceWhiteY = f.getAsFloat(1); this.referenceBlackCb = f.getAsFloat(2); this.referenceWhiteCb = f.getAsFloat(3); this.referenceBlackCr = f.getAsFloat(4); this.referenceWhiteCr = f.getAsFloat(5); } else { warning("REFERENCE_BLACK_WHITE count != 6, ignoring it"); } } else { warning("REFERENCE_BLACK_WHITE not found, assuming 0-255/128-255/128-255"); } this.colorConvert = true; float BCb = (2.0f - 2.0f*LumaBlue); float RCr = (2.0f - 2.0f*LumaRed); float GY = (1.0f - LumaBlue - LumaRed)/LumaGreen; float GCb = 2.0f*LumaBlue*(LumaBlue - 1.0f)/LumaGreen; float GCr = 2.0f*LumaRed*(LumaRed - 1.0f)/LumaGreen; for (int i = 0; i < 256; i++) { float fY = (i - referenceBlackY)*codingRangeY/ (referenceWhiteY - referenceBlackY); float fCb = (i - referenceBlackCb)*127.0f/ (referenceWhiteCb - referenceBlackCb); float fCr = (i - referenceBlackCr)*127.0f/ (referenceWhiteCr - referenceBlackCr); iYTab[i] = (int)(fY*FRAC_SCALE); iCbTab[i] = (int)(fCb*BCb*FRAC_SCALE); iCrTab[i] = (int)(fCr*RCr*FRAC_SCALE); iGYTab[i] = (int)(fY*GY*FRAC_SCALE); iGCbTab[i] = (int)(fCb*GCb*FRAC_SCALE); iGCrTab[i] = (int)(fCr*GCr*FRAC_SCALE); } } public void decodeRaw(byte[] buf, int dstOffset, int bitsPerPixel, int scanlineStride) throws IOException { byte[] rows = new byte[3*srcWidth*chromaSubsampleV]; int elementsPerPacket = chromaSubsampleH*chromaSubsampleV + 2; byte[] packet = new byte[elementsPerPacket]; if(decompressor != null) { int bytesPerRow = 3*srcWidth; byte[] tmpBuf = new byte[bytesPerRow*srcHeight]; decompressor.decodeRaw(tmpBuf, dstOffset, bitsPerPixel, bytesPerRow); ByteArrayInputStream byteStream = new ByteArrayInputStream(tmpBuf); stream = new MemoryCacheImageInputStream(byteStream); } else { stream.seek(offset); } for (int y = srcMinY; y < srcMinY + srcHeight; y += chromaSubsampleV) { // Decode chromaSubsampleV rows for (int x = srcMinX; x < srcMinX + srcWidth; x += chromaSubsampleH) { try { stream.readFully(packet); } catch (EOFException e) { System.out.println("e = " + e); return; } byte Cb = packet[elementsPerPacket - 2]; byte Cr = packet[elementsPerPacket - 1]; int iCb = 0, iCr = 0, iGCb = 0, iGCr = 0; if (colorConvert) { int Cbp = Cb & 0xff; int Crp = Cr & 0xff; iCb = iCbTab[Cbp]; iCr = iCrTab[Crp]; iGCb = iGCbTab[Cbp]; iGCr = iGCrTab[Crp]; } int yIndex = 0; for (int v = 0; v < chromaSubsampleV; v++) { int idx = dstOffset + 3*(x - srcMinX) + scanlineStride*(y - srcMinY + v); // Check if we reached the last scanline if (y + v >= srcMinY + srcHeight) { break; } for (int h = 0; h < chromaSubsampleH; h++) { if (x + h >= srcMinX + srcWidth) { break; } byte Y = packet[yIndex++]; if (colorConvert) { int Yp = Y & 0xff; int iY = iYTab[Yp]; int iGY = iGYTab[Yp]; int iR = iY + iCr; int iG = iGY + iGCb + iGCr; int iB = iY + iCb; byte r = clamp(iR); byte g = clamp(iG); byte b = clamp(iB); buf[idx] = r; buf[idx + 1] = g; buf[idx + 2] = b; } else { buf[idx] = Y; buf[idx + 1] = Cb; buf[idx + 2] = Cr; } idx += 3; } } } } } } ././@LongLink0000000000000000000000000000014500000000000011565 Lustar rootrootjai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/tiff/TIFFImageMetadata.javajai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/tiff/TIFFImageMetadata.java0000664000175100017510000020676210460255667032411 0ustar tilletille/* * $RCSfile: TIFFImageMetadata.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.11 $ * $Date: 2006-07-21 22:56:55 $ * $State: Exp $ */ package com.sun.media.imageioimpl.plugins.tiff; import java.awt.image.ColorModel; import java.awt.image.SampleModel; import java.io.IOException; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.StringTokenizer; import java.util.Vector; import javax.imageio.ImageTypeSpecifier; import javax.imageio.metadata.IIOMetadata; import javax.imageio.metadata.IIOInvalidTreeException; import javax.imageio.metadata.IIOMetadataFormatImpl; import javax.imageio.metadata.IIOMetadataNode; import javax.imageio.stream.ImageInputStream; import org.w3c.dom.NamedNodeMap; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import com.sun.media.imageio.plugins.tiff.BaselineTIFFTagSet; import com.sun.media.imageio.plugins.tiff.EXIFParentTIFFTagSet; import com.sun.media.imageio.plugins.tiff.TIFFField; import com.sun.media.imageio.plugins.tiff.TIFFTag; import com.sun.media.imageio.plugins.tiff.TIFFTagSet; public class TIFFImageMetadata extends IIOMetadata { // package scope public static final String nativeMetadataFormatName = "com_sun_media_imageio_plugins_tiff_image_1.0"; public static final String nativeMetadataFormatClassName = "com.sun.media.imageioimpl.plugins.tiff.TIFFImageMetadataFormat"; List tagSets; TIFFIFD rootIFD; public TIFFImageMetadata(List tagSets) { super(true, nativeMetadataFormatName, nativeMetadataFormatClassName, null, null); this.tagSets = tagSets; this.rootIFD = new TIFFIFD(tagSets); } public TIFFImageMetadata(TIFFIFD ifd) { super(true, nativeMetadataFormatName, nativeMetadataFormatClassName, null, null); this.tagSets = ifd.getTagSetList(); this.rootIFD = ifd; } public void initializeFromStream(ImageInputStream stream, boolean ignoreUnknownFields) throws IOException { rootIFD.initialize(stream, ignoreUnknownFields); } public void addShortOrLongField(int tagNumber, int value) { TIFFField field = new TIFFField(rootIFD.getTag(tagNumber), value); rootIFD.addTIFFField(field); } // public void initializeFromImageType(ImageTypeSpecifier imageType) { // SampleModel sampleModel = imageType.getSampleModel(); // ColorModel colorModel = imageType.getColorModel(); // int numBands = sampleModel.getNumBands(); // char[] bitsPerSample = new char[numBands]; // for (int i = 0; i < numBands; i++) { // bitsPerSample[i] = (char)(sampleModel.getSampleSize(i)); // } // TIFFField bitsPerSampleField = // new TIFFField(rootIFD.getTag(BaselineTIFFTagSet.TAG_BITS_PER_SAMPLE), // TIFFTag.TIFF_SHORT, // numBands, // bitsPerSample); // rootIFD.addTIFFField(bitsPerSampleField); // } public boolean isReadOnly() { return false; } private Node getIFDAsTree(TIFFIFD ifd, String parentTagName, int parentTagNumber) { IIOMetadataNode IFDRoot = new IIOMetadataNode("TIFFIFD"); if (parentTagNumber != 0) { IFDRoot.setAttribute("parentTagNumber", Integer.toString(parentTagNumber)); } if (parentTagName != null) { IFDRoot.setAttribute("parentTagName", parentTagName); } List tagSets = ifd.getTagSetList(); if (tagSets.size() > 0) { Iterator iter = tagSets.iterator(); String tagSetNames = ""; while (iter.hasNext()) { TIFFTagSet tagSet = (TIFFTagSet)iter.next(); tagSetNames += tagSet.getClass().getName(); if (iter.hasNext()) { tagSetNames += ","; } } IFDRoot.setAttribute("tagSets", tagSetNames); } Iterator iter = ifd.iterator(); while (iter.hasNext()) { TIFFField f = (TIFFField)iter.next(); int tagNumber = f.getTagNumber(); TIFFTag tag = TIFFIFD.getTag(tagNumber, tagSets); Node node = null; if (tag == null) { node = f.getAsNativeNode(); } else if (tag.isIFDPointer()) { TIFFIFD subIFD = (TIFFIFD)f.getData(); // Recurse node = getIFDAsTree(subIFD, tag.getName(), tag.getNumber()); } else { node = f.getAsNativeNode(); } if (node != null) { IFDRoot.appendChild(node); } } return IFDRoot; } public Node getAsTree(String formatName) { if (formatName.equals(nativeMetadataFormatName)) { return getNativeTree(); } else if (formatName.equals (IIOMetadataFormatImpl.standardMetadataFormatName)) { return getStandardTree(); } else { throw new IllegalArgumentException("Not a recognized format!"); } } private Node getNativeTree() { IIOMetadataNode root = new IIOMetadataNode(nativeMetadataFormatName); Node IFDNode = getIFDAsTree(rootIFD, null, 0); root.appendChild(IFDNode); return root; } private static final String[] colorSpaceNames = { "GRAY", // WhiteIsZero "GRAY", // BlackIsZero "RGB", // RGB "RGB", // PaletteColor "GRAY", // TransparencyMask "CMYK", // CMYK "YCbCr", // YCbCr "Lab", // CIELab "Lab", // ICCLab }; public IIOMetadataNode getStandardChromaNode() { IIOMetadataNode chroma_node = new IIOMetadataNode("Chroma"); IIOMetadataNode node = null; // scratch node TIFFField f; // Set the PhotometricInterpretation and the palette color flag. int photometricInterpretation = -1; boolean isPaletteColor = false; f = getTIFFField(BaselineTIFFTagSet.TAG_PHOTOMETRIC_INTERPRETATION); if (f != null) { photometricInterpretation = f.getAsInt(0); isPaletteColor = photometricInterpretation == BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_PALETTE_COLOR; } // Determine the number of channels. int numChannels = -1; if(isPaletteColor) { numChannels = 3; } else { f = getTIFFField(BaselineTIFFTagSet.TAG_SAMPLES_PER_PIXEL); if (f != null) { numChannels = f.getAsInt(0); } else { // f == null f = getTIFFField(BaselineTIFFTagSet.TAG_BITS_PER_SAMPLE); if(f != null) { numChannels = f.getCount(); } } } if(photometricInterpretation != -1) { if (photometricInterpretation >= 0 && photometricInterpretation < colorSpaceNames.length) { node = new IIOMetadataNode("ColorSpaceType"); String csName; if(photometricInterpretation == BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_CMYK && numChannels == 3) { csName = "CMY"; } else { csName = colorSpaceNames[photometricInterpretation]; } node.setAttribute("name", csName); chroma_node.appendChild(node); } node = new IIOMetadataNode("BlackIsZero"); node.setAttribute("value", (photometricInterpretation == BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_WHITE_IS_ZERO) ? "FALSE" : "TRUE"); chroma_node.appendChild(node); } if(numChannels != -1) { node = new IIOMetadataNode("NumChannels"); node.setAttribute("value", Integer.toString(numChannels)); chroma_node.appendChild(node); } f = getTIFFField(BaselineTIFFTagSet.TAG_COLOR_MAP); if (f != null) { // NOTE: The presence of hasAlpha is vestigial: there is // no way in TIFF to represent an alpha component in a palette // color image. See bug 5086341. boolean hasAlpha = false; node = new IIOMetadataNode("Palette"); int len = f.getCount()/(hasAlpha ? 4 : 3); for (int i = 0; i < len; i++) { IIOMetadataNode entry = new IIOMetadataNode("PaletteEntry"); entry.setAttribute("index", Integer.toString(i)); int r = (f.getAsInt(i)*255)/65535; int g = (f.getAsInt(len + i)*255)/65535; int b = (f.getAsInt(2*len + i)*255)/65535; entry.setAttribute("red", Integer.toString(r)); entry.setAttribute("green", Integer.toString(g)); entry.setAttribute("blue", Integer.toString(b)); if (hasAlpha) { int alpha = 0; entry.setAttribute("alpha", Integer.toString(alpha)); } node.appendChild(entry); } chroma_node.appendChild(node); } return chroma_node; } public IIOMetadataNode getStandardCompressionNode() { IIOMetadataNode compression_node = new IIOMetadataNode("Compression"); IIOMetadataNode node = null; // scratch node TIFFField f; f = getTIFFField(BaselineTIFFTagSet.TAG_COMPRESSION); if (f != null) { String compressionTypeName = null; int compression = f.getAsInt(0); boolean isLossless = true; // obligate initialization. if(compression == BaselineTIFFTagSet.COMPRESSION_NONE) { compressionTypeName = "None"; isLossless = true; } else { int[] compressionNumbers = TIFFImageWriter.compressionNumbers; for(int i = 0; i < compressionNumbers.length; i++) { if(compression == compressionNumbers[i]) { compressionTypeName = TIFFImageWriter.compressionTypes[i]; isLossless = TIFFImageWriter.isCompressionLossless[i]; break; } } } if (compressionTypeName != null) { node = new IIOMetadataNode("CompressionTypeName"); node.setAttribute("value", compressionTypeName); compression_node.appendChild(node); node = new IIOMetadataNode("Lossless"); node.setAttribute("value", isLossless ? "TRUE" : "FALSE"); compression_node.appendChild(node); } } node = new IIOMetadataNode("NumProgressiveScans"); node.setAttribute("value", "1"); compression_node.appendChild(node); return compression_node; } private String repeat(String s, int times) { if (times == 1) { return s; } StringBuffer sb = new StringBuffer((s.length() + 1)*times - 1); sb.append(s); for (int i = 1; i < times; i++) { sb.append(" "); sb.append(s); } return sb.toString(); } public IIOMetadataNode getStandardDataNode() { IIOMetadataNode data_node = new IIOMetadataNode("Data"); IIOMetadataNode node = null; // scratch node TIFFField f; boolean isPaletteColor = false; f = getTIFFField(BaselineTIFFTagSet.TAG_PHOTOMETRIC_INTERPRETATION); if (f != null) { isPaletteColor = f.getAsInt(0) == BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_PALETTE_COLOR; } f = getTIFFField(BaselineTIFFTagSet.TAG_PLANAR_CONFIGURATION); String planarConfiguration = "PixelInterleaved"; if (f != null && f.getAsInt(0) == BaselineTIFFTagSet.PLANAR_CONFIGURATION_PLANAR) { planarConfiguration = "PlaneInterleaved"; } node = new IIOMetadataNode("PlanarConfiguration"); node.setAttribute("value", planarConfiguration); data_node.appendChild(node); f = getTIFFField(BaselineTIFFTagSet.TAG_PHOTOMETRIC_INTERPRETATION); if (f != null) { int photometricInterpretation = f.getAsInt(0); String sampleFormat = "UnsignedIntegral"; if (photometricInterpretation == BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_PALETTE_COLOR) { sampleFormat = "Index"; } else { f = getTIFFField(BaselineTIFFTagSet.TAG_SAMPLE_FORMAT); if (f != null) { int format = f.getAsInt(0); if (format == BaselineTIFFTagSet.SAMPLE_FORMAT_SIGNED_INTEGER) { sampleFormat = "SignedIntegral"; } else if (format == BaselineTIFFTagSet.SAMPLE_FORMAT_UNSIGNED_INTEGER) { sampleFormat = "UnsignedIntegral"; } else if (format == BaselineTIFFTagSet.SAMPLE_FORMAT_FLOATING_POINT) { sampleFormat = "Real"; } else { sampleFormat = null; // don't know } } } if (sampleFormat != null) { node = new IIOMetadataNode("SampleFormat"); node.setAttribute("value", sampleFormat); data_node.appendChild(node); } } f = getTIFFField(BaselineTIFFTagSet.TAG_BITS_PER_SAMPLE); int[] bitsPerSample = null; if(f != null) { bitsPerSample = f.getAsInts(); } else { f = getTIFFField(BaselineTIFFTagSet.TAG_COMPRESSION); int compression = f != null ? f.getAsInt(0) : BaselineTIFFTagSet.COMPRESSION_NONE; if(getTIFFField(EXIFParentTIFFTagSet.TAG_EXIF_IFD_POINTER) != null || compression == BaselineTIFFTagSet.COMPRESSION_JPEG || compression == BaselineTIFFTagSet.COMPRESSION_OLD_JPEG || getTIFFField(BaselineTIFFTagSet.TAG_JPEG_INTERCHANGE_FORMAT) != null) { f = getTIFFField(BaselineTIFFTagSet.TAG_PHOTOMETRIC_INTERPRETATION); if(f != null && (f.getAsInt(0) == BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_WHITE_IS_ZERO || f.getAsInt(0) == BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_BLACK_IS_ZERO)) { bitsPerSample = new int[] {8}; } else { bitsPerSample = new int[] {8, 8, 8}; } } else { bitsPerSample = new int[] {1}; } } StringBuffer sb = new StringBuffer(); for (int i = 0; i < bitsPerSample.length; i++) { if (i > 0) { sb.append(" "); } sb.append(Integer.toString(bitsPerSample[i])); } node = new IIOMetadataNode("BitsPerSample"); if(isPaletteColor) { node.setAttribute("value", repeat(sb.toString(), 3)); } else { node.setAttribute("value", sb.toString()); } data_node.appendChild(node); // SampleMSB f = getTIFFField(BaselineTIFFTagSet.TAG_FILL_ORDER); int fillOrder = f != null ? f.getAsInt(0) : BaselineTIFFTagSet.FILL_ORDER_LEFT_TO_RIGHT; sb = new StringBuffer(); for (int i = 0; i < bitsPerSample.length; i++) { if (i > 0) { sb.append(" "); } int maxBitIndex = bitsPerSample[i] == 1 ? 7 : bitsPerSample[i] - 1; int msb = fillOrder == BaselineTIFFTagSet.FILL_ORDER_LEFT_TO_RIGHT ? maxBitIndex : 0; sb.append(Integer.toString(msb)); } node = new IIOMetadataNode("SampleMSB"); if(isPaletteColor) { node.setAttribute("value", repeat(sb.toString(), 3)); } else { node.setAttribute("value", sb.toString()); } data_node.appendChild(node); return data_node; } private static final String[] orientationNames = { null, "Normal", "FlipH", "Rotate180", "FlipV", "FlipHRotate90", "Rotate270", "FlipVRotate90", "Rotate90", }; public IIOMetadataNode getStandardDimensionNode() { IIOMetadataNode dimension_node = new IIOMetadataNode("Dimension"); IIOMetadataNode node = null; // scratch node TIFFField f; long[] xres = null; long[] yres = null; f = getTIFFField(BaselineTIFFTagSet.TAG_X_RESOLUTION); if (f != null) { xres = (long[])f.getAsRational(0).clone(); } f = getTIFFField(BaselineTIFFTagSet.TAG_Y_RESOLUTION); if (f != null) { yres = (long[])f.getAsRational(0).clone(); } if (xres != null && yres != null) { node = new IIOMetadataNode("PixelAspectRatio"); // Compute (1/xres)/(1/yres) // (xres_denom/xres_num)/(yres_denom/yres_num) = // (xres_denom/xres_num)*(yres_num/yres_denom) = // (xres_denom*yres_num)/(xres_num*yres_denom) float ratio = (float)((double)xres[1]*yres[0])/(xres[0]*yres[1]); node.setAttribute("value", Float.toString(ratio)); dimension_node.appendChild(node); } if (xres != null || yres != null) { // Get unit field. f = getTIFFField(BaselineTIFFTagSet.TAG_RESOLUTION_UNIT); // Set resolution unit. int resolutionUnit = f != null ? f.getAsInt(0) : BaselineTIFFTagSet.RESOLUTION_UNIT_INCH; // Have size if either centimeters or inches. boolean gotPixelSize = resolutionUnit != BaselineTIFFTagSet.RESOLUTION_UNIT_NONE; // Convert pixels/inch to pixels/centimeter. if (resolutionUnit == BaselineTIFFTagSet.RESOLUTION_UNIT_INCH) { // Divide xres by 2.54 if (xres != null) { xres[0] *= 100; xres[1] *= 254; } // Divide yres by 2.54 if (yres != null) { yres[0] *= 100; yres[1] *= 254; } } if (gotPixelSize) { if (xres != null) { float horizontalPixelSize = (float)(10.0*xres[1]/xres[0]); node = new IIOMetadataNode("HorizontalPixelSize"); node.setAttribute("value", Float.toString(horizontalPixelSize)); dimension_node.appendChild(node); } if (yres != null) { float verticalPixelSize = (float)(10.0*yres[1]/yres[0]); node = new IIOMetadataNode("VerticalPixelSize"); node.setAttribute("value", Float.toString(verticalPixelSize)); dimension_node.appendChild(node); } } } f = getTIFFField(BaselineTIFFTagSet.TAG_RESOLUTION_UNIT); int resolutionUnit = f != null ? f.getAsInt(0) : BaselineTIFFTagSet.RESOLUTION_UNIT_INCH; if(resolutionUnit == BaselineTIFFTagSet.RESOLUTION_UNIT_INCH || resolutionUnit == BaselineTIFFTagSet.RESOLUTION_UNIT_CENTIMETER) { f = getTIFFField(BaselineTIFFTagSet.TAG_X_POSITION); if(f != null) { long[] xpos = (long[])f.getAsRational(0); float xPosition = (float)xpos[0]/(float)xpos[1]; // Convert to millimeters. if(resolutionUnit == BaselineTIFFTagSet.RESOLUTION_UNIT_INCH) { xPosition *= 254F; } else { xPosition *= 10F; } node = new IIOMetadataNode("HorizontalPosition"); node.setAttribute("value", Float.toString(xPosition)); dimension_node.appendChild(node); } f = getTIFFField(BaselineTIFFTagSet.TAG_Y_POSITION); if(f != null) { long[] ypos = (long[])f.getAsRational(0); float yPosition = (float)ypos[0]/(float)ypos[1]; // Convert to millimeters. if(resolutionUnit == BaselineTIFFTagSet.RESOLUTION_UNIT_INCH) { yPosition *= 254F; } else { yPosition *= 10F; } node = new IIOMetadataNode("VerticalPosition"); node.setAttribute("value", Float.toString(yPosition)); dimension_node.appendChild(node); } } f = getTIFFField(BaselineTIFFTagSet.TAG_ORIENTATION); if (f != null) { int o = f.getAsInt(0); if (o >= 0 && o < orientationNames.length) { node = new IIOMetadataNode("ImageOrientation"); node.setAttribute("value", orientationNames[o]); dimension_node.appendChild(node); } } return dimension_node; } public IIOMetadataNode getStandardDocumentNode() { IIOMetadataNode document_node = new IIOMetadataNode("Document"); IIOMetadataNode node = null; // scratch node TIFFField f; node = new IIOMetadataNode("FormatVersion"); node.setAttribute("value", "6.0"); document_node.appendChild(node); f = getTIFFField(BaselineTIFFTagSet.TAG_NEW_SUBFILE_TYPE); if(f != null) { int newSubFileType = f.getAsInt(0); String value = null; if((newSubFileType & BaselineTIFFTagSet.NEW_SUBFILE_TYPE_TRANSPARENCY) != 0) { value = "TransparencyMask"; } else if((newSubFileType & BaselineTIFFTagSet.NEW_SUBFILE_TYPE_REDUCED_RESOLUTION) != 0) { value = "ReducedResolution"; } else if((newSubFileType & BaselineTIFFTagSet.NEW_SUBFILE_TYPE_SINGLE_PAGE) != 0) { value = "SinglePage"; } if(value != null) { node = new IIOMetadataNode("SubimageInterpretation"); node.setAttribute("value", value); document_node.appendChild(node); } } f = getTIFFField(BaselineTIFFTagSet.TAG_DATE_TIME); if (f != null) { String s = f.getAsString(0); // DateTime should be formatted as "YYYY:MM:DD hh:mm:ss". if(s.length() == 19) { node = new IIOMetadataNode("ImageCreationTime"); // Files with incorrect DateTime format have been // observed so anticipate an exception from substring() // and only add the node if the format is presumably // correct. boolean appendNode; try { node.setAttribute("year", s.substring(0, 4)); node.setAttribute("month", s.substring(5, 7)); node.setAttribute("day", s.substring(8, 10)); node.setAttribute("hour", s.substring(11, 13)); node.setAttribute("minute", s.substring(14, 16)); node.setAttribute("second", s.substring(17, 19)); appendNode = true; } catch(IndexOutOfBoundsException e) { appendNode = false; } if(appendNode) { document_node.appendChild(node); } } } return document_node; } public IIOMetadataNode getStandardTextNode() { IIOMetadataNode text_node = null; IIOMetadataNode node = null; // scratch node TIFFField f; int[] textFieldTagNumbers = new int[] { BaselineTIFFTagSet.TAG_DOCUMENT_NAME, BaselineTIFFTagSet.TAG_IMAGE_DESCRIPTION, BaselineTIFFTagSet.TAG_MAKE, BaselineTIFFTagSet.TAG_MODEL, BaselineTIFFTagSet.TAG_PAGE_NAME, BaselineTIFFTagSet.TAG_SOFTWARE, BaselineTIFFTagSet.TAG_ARTIST, BaselineTIFFTagSet.TAG_HOST_COMPUTER, BaselineTIFFTagSet.TAG_INK_NAMES, BaselineTIFFTagSet.TAG_COPYRIGHT }; for(int i = 0; i < textFieldTagNumbers.length; i++) { f = getTIFFField(textFieldTagNumbers[i]); if(f != null) { String value = f.getAsString(0); if(text_node == null) { text_node = new IIOMetadataNode("Text"); } node = new IIOMetadataNode("TextEntry"); node.setAttribute("keyword", f.getTag().getName()); node.setAttribute("value", value); text_node.appendChild(node); } } return text_node; } public IIOMetadataNode getStandardTransparencyNode() { IIOMetadataNode transparency_node = new IIOMetadataNode("Transparency"); IIOMetadataNode node = null; // scratch node TIFFField f; node = new IIOMetadataNode("Alpha"); String value = "none"; f = getTIFFField(BaselineTIFFTagSet.TAG_EXTRA_SAMPLES); if(f != null) { int[] extraSamples = f.getAsInts(); for(int i = 0; i < extraSamples.length; i++) { if(extraSamples[i] == BaselineTIFFTagSet.EXTRA_SAMPLES_ASSOCIATED_ALPHA) { value = "premultiplied"; break; } else if(extraSamples[i] == BaselineTIFFTagSet.EXTRA_SAMPLES_UNASSOCIATED_ALPHA) { value = "nonpremultiplied"; break; } } } node.setAttribute("value", value); transparency_node.appendChild(node); return transparency_node; } // Shorthand for throwing an IIOInvalidTreeException private static void fatal(Node node, String reason) throws IIOInvalidTreeException { throw new IIOInvalidTreeException(reason, node); } private int[] listToIntArray(String list) { StringTokenizer st = new StringTokenizer(list, " "); ArrayList intList = new ArrayList(); while (st.hasMoreTokens()) { String nextInteger = st.nextToken(); Integer nextInt = new Integer(nextInteger); intList.add(nextInt); } int[] intArray = new int[intList.size()]; for(int i = 0; i < intArray.length; i++) { intArray[i] = ((Integer)intList.get(i)).intValue(); } return intArray; } private char[] listToCharArray(String list) { StringTokenizer st = new StringTokenizer(list, " "); ArrayList intList = new ArrayList(); while (st.hasMoreTokens()) { String nextInteger = st.nextToken(); Integer nextInt = new Integer(nextInteger); intList.add(nextInt); } char[] charArray = new char[intList.size()]; for(int i = 0; i < charArray.length; i++) { charArray[i] = (char)((Integer)intList.get(i)).intValue(); } return charArray; } private void mergeStandardTree(Node root) throws IIOInvalidTreeException { TIFFField f; TIFFTag tag; Node node = root; if (!node.getNodeName() .equals(IIOMetadataFormatImpl.standardMetadataFormatName)) { fatal(node, "Root must be " + IIOMetadataFormatImpl.standardMetadataFormatName); } // Obtain the sample format and set the palette flag if appropriate. String sampleFormat = null; Node dataNode = getChildNode(root, "Data"); boolean isPaletteColor = false; if(dataNode != null) { Node sampleFormatNode = getChildNode(dataNode, "SampleFormat"); if(sampleFormatNode != null) { sampleFormat = getAttribute(sampleFormatNode, "value"); isPaletteColor = sampleFormat.equals("Index"); } } // If palette flag not set check for palette. if(!isPaletteColor) { Node chromaNode = getChildNode(root, "Chroma"); if(chromaNode != null && getChildNode(chromaNode, "Palette") != null) { isPaletteColor = true; } } node = node.getFirstChild(); while (node != null) { String name = node.getNodeName(); if (name.equals("Chroma")) { String colorSpaceType = null; String blackIsZero = null; boolean gotPalette = false; Node child = node.getFirstChild(); while (child != null) { String childName = child.getNodeName(); if (childName.equals("ColorSpaceType")) { colorSpaceType = getAttribute(child, "name"); } else if (childName.equals("NumChannels")) { tag = rootIFD.getTag(BaselineTIFFTagSet.TAG_SAMPLES_PER_PIXEL); int samplesPerPixel = isPaletteColor ? 1 : Integer.parseInt(getAttribute(child, "value")); f = new TIFFField(tag, samplesPerPixel); rootIFD.addTIFFField(f); } else if (childName.equals("BlackIsZero")) { blackIsZero = getAttribute(child, "value"); } else if (childName.equals("Palette")) { Node entry = child.getFirstChild(); HashMap palette = new HashMap(); int maxIndex = -1; while(entry != null) { String entryName = entry.getNodeName(); if(entryName.equals("PaletteEntry")) { String idx = getAttribute(entry, "index"); int id = Integer.parseInt(idx); if(id > maxIndex) { maxIndex = id; } char red = (char)Integer.parseInt(getAttribute(entry, "red")); char green = (char)Integer.parseInt(getAttribute(entry, "green")); char blue = (char)Integer.parseInt(getAttribute(entry, "blue")); palette.put(new Integer(id), new char[] {red, green, blue}); gotPalette = true; } entry = entry.getNextSibling(); } if(gotPalette) { int mapSize = maxIndex + 1; int paletteLength = 3*mapSize; char[] paletteEntries = new char[paletteLength]; Iterator paletteIter = palette.keySet().iterator(); while(paletteIter.hasNext()) { Integer index = (Integer)paletteIter.next(); char[] rgb = (char[])palette.get(index); int idx = index.intValue(); paletteEntries[idx] = (char)((rgb[0]*65535)/255); paletteEntries[mapSize + idx] = (char)((rgb[1]*65535)/255); paletteEntries[2*mapSize + idx] = (char)((rgb[2]*65535)/255); } tag = rootIFD.getTag(BaselineTIFFTagSet.TAG_COLOR_MAP); f = new TIFFField(tag, TIFFTag.TIFF_SHORT, paletteLength, paletteEntries); rootIFD.addTIFFField(f); } } child = child.getNextSibling(); } int photometricInterpretation = -1; if((colorSpaceType == null || colorSpaceType.equals("GRAY")) && blackIsZero != null && blackIsZero.equalsIgnoreCase("FALSE")) { photometricInterpretation = BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_WHITE_IS_ZERO; } else if(colorSpaceType != null) { if(colorSpaceType.equals("GRAY")) { boolean isTransparency = false; if(root instanceof IIOMetadataNode) { IIOMetadataNode iioRoot = (IIOMetadataNode)root; NodeList siNodeList = iioRoot.getElementsByTagName("SubimageInterpretation"); if(siNodeList.getLength() == 1) { Node siNode = siNodeList.item(0); String value = getAttribute(siNode, "value"); if(value.equals("TransparencyMask")) { isTransparency = true; } } } if(isTransparency) { photometricInterpretation = BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_TRANSPARENCY_MASK; } else { photometricInterpretation = BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_BLACK_IS_ZERO; } } else if(colorSpaceType.equals("RGB")) { photometricInterpretation = gotPalette ? BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_PALETTE_COLOR : BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_RGB; } else if(colorSpaceType.equals("YCbCr")) { photometricInterpretation = BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_Y_CB_CR; } else if(colorSpaceType.equals("CMYK")) { photometricInterpretation = BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_CMYK; } else if(colorSpaceType.equals("Lab")) { photometricInterpretation = BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_CIELAB; } } if(photometricInterpretation != -1) { tag = rootIFD.getTag(BaselineTIFFTagSet.TAG_PHOTOMETRIC_INTERPRETATION); f = new TIFFField(tag, photometricInterpretation); rootIFD.addTIFFField(f); } } else if (name.equals("Compression")) { Node child = node.getFirstChild(); while (child != null) { String childName = child.getNodeName(); if (childName.equals("CompressionTypeName")) { int compression = -1; String compressionTypeName = getAttribute(child, "value"); if(compressionTypeName.equalsIgnoreCase("None")) { compression = BaselineTIFFTagSet.COMPRESSION_NONE; } else { String[] compressionNames = TIFFImageWriter.compressionTypes; for(int i = 0; i < compressionNames.length; i++) { if(compressionNames[i].equalsIgnoreCase(compressionTypeName)) { compression = TIFFImageWriter.compressionNumbers[i]; break; } } } if(compression != -1) { tag = rootIFD.getTag(BaselineTIFFTagSet.TAG_COMPRESSION); f = new TIFFField(tag, compression); rootIFD.addTIFFField(f); // Lossless is irrelevant. } } child = child.getNextSibling(); } } else if (name.equals("Data")) { Node child = node.getFirstChild(); while (child != null) { String childName = child.getNodeName(); if (childName.equals("PlanarConfiguration")) { String pc = getAttribute(child, "value"); int planarConfiguration = -1; if(pc.equals("PixelInterleaved")) { planarConfiguration = BaselineTIFFTagSet.PLANAR_CONFIGURATION_CHUNKY; } else if(pc.equals("PlaneInterleaved")) { planarConfiguration = BaselineTIFFTagSet.PLANAR_CONFIGURATION_PLANAR; } if(planarConfiguration != -1) { tag = rootIFD.getTag(BaselineTIFFTagSet.TAG_PLANAR_CONFIGURATION); f = new TIFFField(tag, planarConfiguration); rootIFD.addTIFFField(f); } } else if (childName.equals("BitsPerSample")) { String bps = getAttribute(child, "value"); char[] bitsPerSample = listToCharArray(bps); tag = rootIFD.getTag(BaselineTIFFTagSet.TAG_BITS_PER_SAMPLE); if(isPaletteColor) { f = new TIFFField(tag, TIFFTag.TIFF_SHORT, 1, new char[] {bitsPerSample[0]}); } else { f = new TIFFField(tag, TIFFTag.TIFF_SHORT, bitsPerSample.length, bitsPerSample); } rootIFD.addTIFFField(f); } else if (childName.equals("SampleMSB")) { // Add FillOrder only if lsb-to-msb (right to left) // for all bands, i.e., SampleMSB is zero for all // channels. String sMSB = getAttribute(child, "value"); int[] sampleMSB = listToIntArray(sMSB); boolean isRightToLeft = true; for(int i = 0; i < sampleMSB.length; i++) { if(sampleMSB[i] != 0) { isRightToLeft = false; break; } } int fillOrder = isRightToLeft ? BaselineTIFFTagSet.FILL_ORDER_RIGHT_TO_LEFT : BaselineTIFFTagSet.FILL_ORDER_LEFT_TO_RIGHT; tag = rootIFD.getTag(BaselineTIFFTagSet.TAG_FILL_ORDER); f = new TIFFField(tag, fillOrder); rootIFD.addTIFFField(f); } child = child.getNextSibling(); } } else if (name.equals("Dimension")) { float pixelAspectRatio = -1.0f; boolean gotPixelAspectRatio = false; float horizontalPixelSize = -1.0f; boolean gotHorizontalPixelSize = false; float verticalPixelSize = -1.0f; boolean gotVerticalPixelSize = false; boolean sizeIsAbsolute = false; float horizontalPosition = -1.0f; boolean gotHorizontalPosition = false; float verticalPosition = -1.0f; boolean gotVerticalPosition = false; Node child = node.getFirstChild(); while (child != null) { String childName = child.getNodeName(); if (childName.equals("PixelAspectRatio")) { String par = getAttribute(child, "value"); pixelAspectRatio = Float.parseFloat(par); gotPixelAspectRatio = true; } else if (childName.equals("ImageOrientation")) { String orientation = getAttribute(child, "value"); for (int i = 0; i < orientationNames.length; i++) { if (orientation.equals(orientationNames[i])) { char[] oData = new char[1]; oData[0] = (char)i; f = new TIFFField( rootIFD.getTag(BaselineTIFFTagSet.TAG_ORIENTATION), TIFFTag.TIFF_SHORT, 1, oData); rootIFD.addTIFFField(f); break; } } } else if (childName.equals("HorizontalPixelSize")) { String hps = getAttribute(child, "value"); horizontalPixelSize = Float.parseFloat(hps); gotHorizontalPixelSize = true; } else if (childName.equals("VerticalPixelSize")) { String vps = getAttribute(child, "value"); verticalPixelSize = Float.parseFloat(vps); gotVerticalPixelSize = true; } else if (childName.equals("HorizontalPosition")) { String hp = getAttribute(child, "value"); horizontalPosition = Float.parseFloat(hp); gotHorizontalPosition = true; } else if (childName.equals("VerticalPosition")) { String vp = getAttribute(child, "value"); verticalPosition = Float.parseFloat(vp); gotVerticalPosition = true; } child = child.getNextSibling(); } sizeIsAbsolute = gotHorizontalPixelSize || gotVerticalPixelSize; // Fill in pixel size data from aspect ratio if (gotPixelAspectRatio) { if (gotHorizontalPixelSize && !gotVerticalPixelSize) { verticalPixelSize = horizontalPixelSize/pixelAspectRatio; gotVerticalPixelSize = true; } else if (gotVerticalPixelSize && !gotHorizontalPixelSize) { horizontalPixelSize = verticalPixelSize*pixelAspectRatio; gotHorizontalPixelSize = true; } else if (!gotHorizontalPixelSize && !gotVerticalPixelSize) { horizontalPixelSize = pixelAspectRatio; verticalPixelSize = 1.0f; gotHorizontalPixelSize = true; gotVerticalPixelSize = true; } } // Compute pixels/centimeter if (gotHorizontalPixelSize) { float xResolution = (sizeIsAbsolute ? 10.0f : 1.0f)/horizontalPixelSize; long[][] hData = new long[1][2]; hData[0] = new long[2]; hData[0][0] = (long)(xResolution*10000.0f); hData[0][1] = (long)10000; f = new TIFFField( rootIFD.getTag(BaselineTIFFTagSet.TAG_X_RESOLUTION), TIFFTag.TIFF_RATIONAL, 1, hData); rootIFD.addTIFFField(f); } if (gotVerticalPixelSize) { float yResolution = (sizeIsAbsolute ? 10.0f : 1.0f)/verticalPixelSize; long[][] vData = new long[1][2]; vData[0] = new long[2]; vData[0][0] = (long)(yResolution*10000.0f); vData[0][1] = (long)10000; f = new TIFFField( rootIFD.getTag(BaselineTIFFTagSet.TAG_Y_RESOLUTION), TIFFTag.TIFF_RATIONAL, 1, vData); rootIFD.addTIFFField(f); } // Emit ResolutionUnit tag char[] res = new char[1]; res[0] = (char)(sizeIsAbsolute ? BaselineTIFFTagSet.RESOLUTION_UNIT_CENTIMETER : BaselineTIFFTagSet.RESOLUTION_UNIT_NONE); f = new TIFFField( rootIFD.getTag(BaselineTIFFTagSet.TAG_RESOLUTION_UNIT), TIFFTag.TIFF_SHORT, 1, res); rootIFD.addTIFFField(f); // Position if(sizeIsAbsolute) { if(gotHorizontalPosition) { // Convert from millimeters to centimeters via // numerator multiplier = denominator/10. long[][] hData = new long[1][2]; hData[0][0] = (long)(horizontalPosition*10000.0f); hData[0][1] = (long)100000; f = new TIFFField( rootIFD.getTag(BaselineTIFFTagSet.TAG_X_POSITION), TIFFTag.TIFF_RATIONAL, 1, hData); rootIFD.addTIFFField(f); } if(gotVerticalPosition) { // Convert from millimeters to centimeters via // numerator multiplier = denominator/10. long[][] vData = new long[1][2]; vData[0][0] = (long)(verticalPosition*10000.0f); vData[0][1] = (long)100000; f = new TIFFField( rootIFD.getTag(BaselineTIFFTagSet.TAG_Y_POSITION), TIFFTag.TIFF_RATIONAL, 1, vData); rootIFD.addTIFFField(f); } } } else if (name.equals("Document")) { Node child = node.getFirstChild(); while (child != null) { String childName = child.getNodeName(); if (childName.equals("SubimageInterpretation")) { String si = getAttribute(child, "value"); int newSubFileType = -1; if(si.equals("TransparencyMask")) { newSubFileType = BaselineTIFFTagSet.NEW_SUBFILE_TYPE_TRANSPARENCY; } else if(si.equals("ReducedResolution")) { newSubFileType = BaselineTIFFTagSet.NEW_SUBFILE_TYPE_REDUCED_RESOLUTION; } else if(si.equals("SinglePage")) { newSubFileType = BaselineTIFFTagSet.NEW_SUBFILE_TYPE_SINGLE_PAGE; } if(newSubFileType != -1) { tag = rootIFD.getTag(BaselineTIFFTagSet.TAG_NEW_SUBFILE_TYPE); f = new TIFFField(tag, newSubFileType); rootIFD.addTIFFField(f); } } if (childName.equals("ImageCreationTime")) { String year = getAttribute(child, "year"); String month = getAttribute(child, "month"); String day = getAttribute(child, "day"); String hour = getAttribute(child, "hour"); String minute = getAttribute(child, "minute"); String second = getAttribute(child, "second"); StringBuffer sb = new StringBuffer(); sb.append(year); sb.append(":"); if(month.length() == 1) { sb.append("0"); } sb.append(month); sb.append(":"); if(day.length() == 1) { sb.append("0"); } sb.append(day); sb.append(" "); if(hour.length() == 1) { sb.append("0"); } sb.append(hour); sb.append(":"); if(minute.length() == 1) { sb.append("0"); } sb.append(minute); sb.append(":"); if(second.length() == 1) { sb.append("0"); } sb.append(second); String[] dt = new String[1]; dt[0] = sb.toString(); f = new TIFFField( rootIFD.getTag(BaselineTIFFTagSet.TAG_DATE_TIME), TIFFTag.TIFF_ASCII, 1, dt); rootIFD.addTIFFField(f); } child = child.getNextSibling(); } } else if (name.equals("Text")) { Node child = node.getFirstChild(); String theAuthor = null; String theDescription = null; String theTitle = null; while (child != null) { String childName = child.getNodeName(); if(childName.equals("TextEntry")) { int tagNumber = -1; NamedNodeMap childAttrs = child.getAttributes(); Node keywordNode = childAttrs.getNamedItem("keyword"); if(keywordNode != null) { String keyword = keywordNode.getNodeValue(); String value = getAttribute(child, "value"); if(!keyword.equals("") && !value.equals("")) { if(keyword.equalsIgnoreCase("DocumentName")) { tagNumber = BaselineTIFFTagSet.TAG_DOCUMENT_NAME; } else if(keyword.equalsIgnoreCase("ImageDescription")) { tagNumber = BaselineTIFFTagSet.TAG_IMAGE_DESCRIPTION; } else if(keyword.equalsIgnoreCase("Make")) { tagNumber = BaselineTIFFTagSet.TAG_MAKE; } else if(keyword.equalsIgnoreCase("Model")) { tagNumber = BaselineTIFFTagSet.TAG_MODEL; } else if(keyword.equalsIgnoreCase("PageName")) { tagNumber = BaselineTIFFTagSet.TAG_PAGE_NAME; } else if(keyword.equalsIgnoreCase("Software")) { tagNumber = BaselineTIFFTagSet.TAG_SOFTWARE; } else if(keyword.equalsIgnoreCase("Artist")) { tagNumber = BaselineTIFFTagSet.TAG_ARTIST; } else if(keyword.equalsIgnoreCase("HostComputer")) { tagNumber = BaselineTIFFTagSet.TAG_HOST_COMPUTER; } else if(keyword.equalsIgnoreCase("InkNames")) { tagNumber = BaselineTIFFTagSet.TAG_INK_NAMES; } else if(keyword.equalsIgnoreCase("Copyright")) { tagNumber = BaselineTIFFTagSet.TAG_COPYRIGHT; } else if(keyword.equalsIgnoreCase("author")) { theAuthor = value; } else if(keyword.equalsIgnoreCase("description")) { theDescription = value; } else if(keyword.equalsIgnoreCase("title")) { theTitle = value; } if(tagNumber != -1) { f = new TIFFField(rootIFD.getTag(tagNumber), TIFFTag.TIFF_ASCII, 1, new String[] {value}); rootIFD.addTIFFField(f); } } } } child = child.getNextSibling(); } // child != null if(theAuthor != null && getTIFFField(BaselineTIFFTagSet.TAG_ARTIST) == null) { f = new TIFFField(rootIFD.getTag(BaselineTIFFTagSet.TAG_ARTIST), TIFFTag.TIFF_ASCII, 1, new String[] {theAuthor}); rootIFD.addTIFFField(f); } if(theDescription != null && getTIFFField(BaselineTIFFTagSet.TAG_IMAGE_DESCRIPTION) == null) { f = new TIFFField(rootIFD.getTag(BaselineTIFFTagSet.TAG_IMAGE_DESCRIPTION), TIFFTag.TIFF_ASCII, 1, new String[] {theDescription}); rootIFD.addTIFFField(f); } if(theTitle != null && getTIFFField(BaselineTIFFTagSet.TAG_DOCUMENT_NAME) == null) { f = new TIFFField(rootIFD.getTag(BaselineTIFFTagSet.TAG_DOCUMENT_NAME), TIFFTag.TIFF_ASCII, 1, new String[] {theTitle}); rootIFD.addTIFFField(f); } } else if (name.equals("Transparency")) { Node child = node.getFirstChild(); while (child != null) { String childName = child.getNodeName(); if (childName.equals("Alpha")) { String alpha = getAttribute(child, "value"); f = null; if (alpha.equals("premultiplied")) { f = new TIFFField( rootIFD.getTag(BaselineTIFFTagSet.TAG_EXTRA_SAMPLES), BaselineTIFFTagSet.EXTRA_SAMPLES_ASSOCIATED_ALPHA); } else if (alpha.equals("nonpremultiplied")) { f = new TIFFField( rootIFD.getTag(BaselineTIFFTagSet.TAG_EXTRA_SAMPLES), BaselineTIFFTagSet.EXTRA_SAMPLES_UNASSOCIATED_ALPHA); } if (f != null) { rootIFD.addTIFFField(f); } } child = child.getNextSibling(); } } node = node.getNextSibling(); } // Set SampleFormat. if(sampleFormat != null) { // Derive the value. int sf = -1; if(sampleFormat.equals("SignedIntegral")) { sf = BaselineTIFFTagSet.SAMPLE_FORMAT_SIGNED_INTEGER; } else if(sampleFormat.equals("UnsignedIntegral")) { sf = BaselineTIFFTagSet.SAMPLE_FORMAT_UNSIGNED_INTEGER; } else if(sampleFormat.equals("Real")) { sf = BaselineTIFFTagSet.SAMPLE_FORMAT_FLOATING_POINT; } else if(sampleFormat.equals("Index")) { sf = BaselineTIFFTagSet.SAMPLE_FORMAT_UNSIGNED_INTEGER; } if(sf != -1) { // Derive the count. int count = 1; // Try SamplesPerPixel first. f = getTIFFField(BaselineTIFFTagSet.TAG_SAMPLES_PER_PIXEL); if(f != null) { count = f.getAsInt(0); } else { // Try BitsPerSample. f = getTIFFField(BaselineTIFFTagSet.TAG_BITS_PER_SAMPLE); if(f != null) { count = f.getCount(); } } char[] sampleFormatArray = new char[count]; Arrays.fill(sampleFormatArray, (char)sf); // Add SampleFormat. tag = rootIFD.getTag(BaselineTIFFTagSet.TAG_SAMPLE_FORMAT); f = new TIFFField(tag, TIFFTag.TIFF_SHORT, sampleFormatArray.length, sampleFormatArray); rootIFD.addTIFFField(f); } } } private static String getAttribute(Node node, String attrName) { NamedNodeMap attrs = node.getAttributes(); Node attr = attrs.getNamedItem(attrName); return attr != null ? attr.getNodeValue() : null; } private Node getChildNode(Node node, String childName) { Node childNode = null; if(node.hasChildNodes()) { NodeList childNodes = node.getChildNodes(); int length = childNodes.getLength(); for(int i = 0; i < length; i++) { Node item = childNodes.item(i); if(item.getNodeName().equals(childName)) { childNode = item; break; } } } return childNode; } public static TIFFIFD parseIFD(Node node) throws IIOInvalidTreeException { if (!node.getNodeName().equals("TIFFIFD")) { fatal(node, "Expected \"TIFFIFD\" node"); } String tagSetNames = getAttribute(node, "tagSets"); List tagSets = new ArrayList(5); if (tagSetNames != null) { StringTokenizer st = new StringTokenizer(tagSetNames, ","); while (st.hasMoreTokens()) { String className = st.nextToken(); Object o = null; try { Class setClass = Class.forName(className); Method getInstanceMethod = setClass.getMethod("getInstance", (Class[])null); o = getInstanceMethod.invoke(null, (Object[])null); } catch (NoSuchMethodException e) { throw new RuntimeException(e); } catch (IllegalAccessException e) { throw new RuntimeException(e); } catch (InvocationTargetException e) { throw new RuntimeException(e); } catch (ClassNotFoundException e) { throw new RuntimeException(e); } if (!(o instanceof TIFFTagSet)) { fatal(node, "Specified tag set class \"" + className + "\" is not an instance of TIFFTagSet"); } else { tagSets.add((TIFFTagSet)o); } } } TIFFIFD ifd = new TIFFIFD(tagSets); node = node.getFirstChild(); while (node != null) { String name = node.getNodeName(); TIFFField f = null; if (name.equals("TIFFIFD")) { TIFFIFD subIFD = parseIFD(node); String parentTagName = getAttribute(node, "parentTagName"); String parentTagNumber = getAttribute(node, "parentTagNumber"); TIFFTag tag = null; if(parentTagName != null) { tag = TIFFIFD.getTag(parentTagName, tagSets); } else if(parentTagNumber != null) { int tagNumber = Integer.valueOf(parentTagNumber).intValue(); tag = TIFFIFD.getTag(tagNumber, tagSets); } if(tag == null) { tag = new TIFFTag("unknown", 0, 0, null); } int type; if (tag.isDataTypeOK(TIFFTag.TIFF_IFD_POINTER)) { type = TIFFTag.TIFF_IFD_POINTER; } else { type = TIFFTag.TIFF_LONG; } f = new TIFFField(tag, type, 1, subIFD); } else if (name.equals("TIFFField")) { int number = Integer.parseInt(getAttribute(node, "number")); TIFFTagSet tagSet = null; Iterator iter = tagSets.iterator(); while (iter.hasNext()) { TIFFTagSet t = (TIFFTagSet)iter.next(); if (t.getTag(number) != null) { tagSet = t; break; } } f = TIFFField.createFromMetadataNode(tagSet, node); } else { fatal(node, "Expected either \"TIFFIFD\" or \"TIFFField\" node, got " + name); } ifd.addTIFFField(f); node = node.getNextSibling(); } return ifd; } private void mergeNativeTree(Node root) throws IIOInvalidTreeException { Node node = root; if (!node.getNodeName().equals(nativeMetadataFormatName)) { fatal(node, "Root must be " + nativeMetadataFormatName); } node = node.getFirstChild(); if (node == null || !node.getNodeName().equals("TIFFIFD")) { fatal(root, "Root must have \"TIFFIFD\" child"); } TIFFIFD ifd = parseIFD(node); List rootIFDTagSets = rootIFD.getTagSetList(); Iterator tagSetIter = ifd.getTagSetList().iterator(); while(tagSetIter.hasNext()) { Object o = tagSetIter.next(); if(o instanceof TIFFTagSet && !rootIFDTagSets.contains(o)) { rootIFD.addTagSet((TIFFTagSet)o); } } Iterator ifdIter = ifd.iterator(); while(ifdIter.hasNext()) { TIFFField field = (TIFFField)ifdIter.next(); rootIFD.addTIFFField(field); } } public void mergeTree(String formatName, Node root) throws IIOInvalidTreeException{ if (formatName.equals(nativeMetadataFormatName)) { if (root == null) { throw new IllegalArgumentException("root == null!"); } mergeNativeTree(root); } else if (formatName.equals (IIOMetadataFormatImpl.standardMetadataFormatName)) { if (root == null) { throw new IllegalArgumentException("root == null!"); } mergeStandardTree(root); } else { throw new IllegalArgumentException("Not a recognized format!"); } } public void reset() { rootIFD = new TIFFIFD(tagSets); } public TIFFIFD getRootIFD() { return rootIFD; } public TIFFField getTIFFField(int tagNumber) { return rootIFD.getTIFFField(tagNumber); } public void removeTIFFField(int tagNumber) { rootIFD.removeTIFFField(tagNumber); } /** * Returns a TIFFImageMetadata wherein all fields in the * root IFD from the BaselineTIFFTagSet are copied by value * and all other fields copied by reference. */ public TIFFImageMetadata getShallowClone() { return new TIFFImageMetadata(rootIFD.getShallowClone()); } } ././@LongLink0000000000000000000000000000014700000000000011567 Lustar rootrootjai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/tiff/TIFFLZWDecompressor.javajai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/tiff/TIFFLZWDecompressor.ja0000664000175100017510000002167110203036165032414 0ustar tilletille/* * $RCSfile: TIFFLZWDecompressor.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.1 $ * $Date: 2005-02-11 05:01:48 $ * $State: Exp $ */ package com.sun.media.imageioimpl.plugins.tiff; import java.awt.Rectangle; import java.io.IOException; import javax.imageio.IIOException; import javax.imageio.ImageReader; import com.sun.media.imageio.plugins.tiff.BaselineTIFFTagSet; import com.sun.media.imageio.plugins.tiff.TIFFDecompressor; import com.sun.media.imageio.plugins.tiff.TIFFTag; public class TIFFLZWDecompressor extends TIFFDecompressor { private static final boolean DEBUG = false; private static final int andTable[] = { 511, 1023, 2047, 4095 }; int predictor; byte[] srcData; byte[] dstData; int srcIndex; int dstIndex; byte stringTable[][]; int tableIndex, bitsToGet = 9; int nextData = 0; int nextBits = 0; public TIFFLZWDecompressor(int predictor) throws IIOException { super(); if (predictor != BaselineTIFFTagSet.PREDICTOR_NONE && predictor != BaselineTIFFTagSet.PREDICTOR_HORIZONTAL_DIFFERENCING) { throw new IIOException("Illegal value for Predictor in " + "TIFF file"); } if(DEBUG) { System.out.println("Using horizontal differencing predictor"); } this.predictor = predictor; } public void decodeRaw(byte[] b, int dstOffset, int bitsPerPixel, int scanlineStride) throws IOException { // Check bitsPerSample. if (predictor == BaselineTIFFTagSet.PREDICTOR_HORIZONTAL_DIFFERENCING) { int len = bitsPerSample.length; for(int i = 0; i < len; i++) { if(bitsPerSample[i] != 8) { throw new IIOException (bitsPerSample[i] + "-bit samples "+ "are not supported for Horizontal "+ "differencing Predictor"); } } } stream.seek(offset); byte[] sdata = new byte[byteCount]; stream.readFully(sdata); int bytesPerRow = (srcWidth*bitsPerPixel + 7)/8; byte[] buf; int bufOffset; if(bytesPerRow == scanlineStride) { buf = b; bufOffset = dstOffset; } else { buf = new byte[bytesPerRow*srcHeight]; bufOffset = 0; } int numBytesDecoded = decode(sdata, 0, buf, bufOffset); if(bytesPerRow != scanlineStride) { if(DEBUG) { System.out.println("bytesPerRow != scanlineStride"); } int off = 0; for (int y = 0; y < srcHeight; y++) { System.arraycopy(buf, off, b, dstOffset, bytesPerRow); off += bytesPerRow; dstOffset += scanlineStride; } } } public int decode(byte[] sdata, int srcOffset, byte[] ddata, int dstOffset) throws IOException { if (sdata[0] == (byte)0x00 && sdata[1] == (byte)0x01) { throw new IIOException ("TIFF 5.0-style LZW compression is not supported!"); } this.srcData = sdata; this.dstData = ddata; this.srcIndex = srcOffset; this.dstIndex = dstOffset; this.nextData = 0; this.nextBits = 0; initializeStringTable(); int code, oldCode = 0; byte[] string; while ((code = getNextCode()) != 257) { if (code == 256) { initializeStringTable(); code = getNextCode(); if (code == 257) { break; } writeString(stringTable[code]); oldCode = code; } else { if (code < tableIndex) { string = stringTable[code]; writeString(string); addStringToTable(stringTable[oldCode], string[0]); oldCode = code; } else { string = stringTable[oldCode]; string = composeString(string, string[0]); writeString(string); addStringToTable(string); oldCode = code; } } } if (predictor == BaselineTIFFTagSet.PREDICTOR_HORIZONTAL_DIFFERENCING) { for (int j = 0; j < srcHeight; j++) { int count = dstOffset + samplesPerPixel * (j * srcWidth + 1); for (int i = samplesPerPixel; i < srcWidth * samplesPerPixel; i++) { dstData[count] += dstData[count - samplesPerPixel]; count++; } } } return dstIndex - dstOffset; } /** * Initialize the string table. */ public void initializeStringTable() { stringTable = new byte[4096][]; for (int i = 0; i < 256; i++) { stringTable[i] = new byte[1]; stringTable[i][0] = (byte)i; } tableIndex = 258; bitsToGet = 9; } /** * Write out the string just uncompressed. */ public void writeString(byte string[]) { if(dstIndex < dstData.length) { int maxIndex = Math.min(string.length, dstData.length - dstIndex); for (int i=0; i < maxIndex; i++) { dstData[dstIndex++] = string[i]; } } } /** * Add a new string to the string table. */ public void addStringToTable(byte oldString[], byte newString) { int length = oldString.length; byte string[] = new byte[length + 1]; System.arraycopy(oldString, 0, string, 0, length); string[length] = newString; // Add this new String to the table stringTable[tableIndex++] = string; if (tableIndex == 511) { bitsToGet = 10; } else if (tableIndex == 1023) { bitsToGet = 11; } else if (tableIndex == 2047) { bitsToGet = 12; } } /** * Add a new string to the string table. */ public void addStringToTable(byte string[]) { // Add this new String to the table stringTable[tableIndex++] = string; if (tableIndex == 511) { bitsToGet = 10; } else if (tableIndex == 1023) { bitsToGet = 11; } else if (tableIndex == 2047) { bitsToGet = 12; } } /** * Append newString to the end of oldString. */ public byte[] composeString(byte oldString[], byte newString) { int length = oldString.length; byte string[] = new byte[length + 1]; System.arraycopy(oldString, 0, string, 0, length); string[length] = newString; return string; } // Returns the next 9, 10, 11 or 12 bits public int getNextCode() { // Attempt to get the next code. The exception is caught to make // this robust to cases wherein the EndOfInformation code has been // omitted from a strip. Examples of such cases have been observed // in practice. try { nextData = (nextData << 8) | (srcData[srcIndex++] & 0xff); nextBits += 8; if (nextBits < bitsToGet) { nextData = (nextData << 8) | (srcData[srcIndex++] & 0xff); nextBits += 8; } int code = (nextData >> (nextBits - bitsToGet)) & andTable[bitsToGet - 9]; nextBits -= bitsToGet; return code; } catch (ArrayIndexOutOfBoundsException e) { // Strip not terminated as expected: return EndOfInformation code. return 257; } } } ././@LongLink0000000000000000000000000000015100000000000011562 Lustar rootrootjai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/tiff/TIFFDeflateCompressor.javajai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/tiff/TIFFDeflateCompressor.0000664000175100017510000000466110203036165032460 0ustar tilletille/* * $RCSfile: TIFFDeflateCompressor.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.1 $ * $Date: 2005-02-11 05:01:44 $ * $State: Exp $ */ package com.sun.media.imageioimpl.plugins.tiff; import com.sun.media.imageio.plugins.tiff.BaselineTIFFTagSet; import com.sun.media.imageio.plugins.tiff.TIFFCompressor; import java.io.IOException; import java.util.zip.Deflater; import javax.imageio.ImageWriteParam; /** * Compressor for Deflate compression. */ public class TIFFDeflateCompressor extends TIFFDeflater { public TIFFDeflateCompressor(ImageWriteParam param, int predictor) { super("Deflate", BaselineTIFFTagSet.COMPRESSION_DEFLATE, param, predictor); } } ././@LongLink0000000000000000000000000000015400000000000011565 Lustar rootrootjai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/tiff/TIFFStreamMetadataFormat.javajai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/tiff/TIFFStreamMetadataForm0000664000175100017510000000752110203036165032477 0ustar tilletille/* * $RCSfile: TIFFStreamMetadataFormat.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.1 $ * $Date: 2005-02-11 05:01:50 $ * $State: Exp $ */ package com.sun.media.imageioimpl.plugins.tiff; import java.util.Collection; import java.util.HashMap; import java.util.Iterator; import java.util.Locale; import java.util.Map; import java.util.MissingResourceException; import java.util.ResourceBundle; import javax.imageio.ImageTypeSpecifier; import javax.imageio.metadata.IIOMetadataFormat; import com.sun.media.imageio.plugins.tiff.BaselineTIFFTagSet; import com.sun.media.imageio.plugins.tiff.TIFFTag; import com.sun.media.imageio.plugins.tiff.TIFFTagSet; public class TIFFStreamMetadataFormat extends TIFFMetadataFormat { private static TIFFStreamMetadataFormat theInstance = null; public boolean canNodeAppear(String elementName, ImageTypeSpecifier imageType) { return false; } private TIFFStreamMetadataFormat() { this.resourceBaseName = "com.sun.media.imageioimpl.plugins.tiff.TIFFStreamMetadataFormatResources"; this.rootName = TIFFStreamMetadata.nativeMetadataFormatName; TIFFElementInfo einfo; TIFFAttrInfo ainfo; String[] empty = new String[0]; String[] childNames; String[] attrNames; childNames = new String[] { "ByteOrder" }; einfo = new TIFFElementInfo(childNames, empty, CHILD_POLICY_ALL); elementInfoMap.put(TIFFStreamMetadata.nativeMetadataFormatName, einfo); childNames = empty; attrNames = new String[] { "value" }; einfo = new TIFFElementInfo(childNames, attrNames, CHILD_POLICY_EMPTY); elementInfoMap.put("ByteOrder", einfo); ainfo = new TIFFAttrInfo(); ainfo.dataType = DATATYPE_STRING; ainfo.isRequired = true; attrInfoMap.put("ByteOrder/value", ainfo); } public static synchronized IIOMetadataFormat getInstance() { if (theInstance == null) { theInstance = new TIFFStreamMetadataFormat(); } return theInstance; } } ././@LongLink0000000000000000000000000000015300000000000011564 Lustar rootrootjai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/tiff/TIFFYCbCrColorConverter.javajai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/tiff/TIFFYCbCrColorConverte0000664000175100017510000001225310417024535032431 0ustar tilletille/* * $RCSfile: TIFFYCbCrColorConverter.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.2 $ * $Date: 2006-04-11 22:10:37 $ * $State: Exp $ */ package com.sun.media.imageioimpl.plugins.tiff; import java.awt.color.ColorSpace; import com.sun.media.imageio.plugins.tiff.BaselineTIFFTagSet; import com.sun.media.imageio.plugins.tiff.TIFFColorConverter; import com.sun.media.imageio.plugins.tiff.TIFFField; /** */ public class TIFFYCbCrColorConverter extends TIFFColorConverter { private float LumaRed = 0.299f; private float LumaGreen = 0.587f; private float LumaBlue = 0.114f; private float referenceBlackY = 0.0f; private float referenceWhiteY = 255.0f; private float referenceBlackCb = 128.0f; private float referenceWhiteCb = 255.0f; private float referenceBlackCr = 128.0f; private float referenceWhiteCr = 255.0f; private float codingRangeY = 255.0f; private float codingRangeCbCr = 127.0f; public TIFFYCbCrColorConverter(TIFFImageMetadata metadata) { TIFFImageMetadata tmetadata = (TIFFImageMetadata)metadata; TIFFField f = tmetadata.getTIFFField(BaselineTIFFTagSet.TAG_Y_CB_CR_COEFFICIENTS); if (f != null && f.getCount() == 3) { this.LumaRed = f.getAsFloat(0); this.LumaGreen = f.getAsFloat(1); this.LumaBlue = f.getAsFloat(2); } f = tmetadata.getTIFFField(BaselineTIFFTagSet.TAG_REFERENCE_BLACK_WHITE); if (f != null && f.getCount() == 6) { this.referenceBlackY = f.getAsFloat(0); this.referenceWhiteY = f.getAsFloat(1); this.referenceBlackCb = f.getAsFloat(2); this.referenceWhiteCb = f.getAsFloat(3); this.referenceBlackCr = f.getAsFloat(4); this.referenceWhiteCr = f.getAsFloat(5); } } /* The full range component value is converted from the code by: FullRangeValue = (code - ReferenceBlack) * CodingRange / (ReferenceWhite - ReferenceBlack); The code is converted from the full-range component value by: code = (FullRangeValue * (ReferenceWhite - ReferenceBlack) / CodingRange) + ReferenceBlack; */ public void fromRGB(float r, float g, float b, float[] result) { // Convert RGB to full-range YCbCr. float Y = (LumaRed*r + LumaGreen*g + LumaBlue*b); float Cb = (b - Y)/(2 - 2*LumaBlue); float Cr = (r - Y)/(2 - 2*LumaRed); // Convert full-range YCbCr to code. result[0] = Y*(referenceWhiteY - referenceBlackY)/codingRangeY + referenceBlackY; result[1] = Cb*(referenceWhiteCb - referenceBlackCb)/codingRangeCbCr + referenceBlackCb; result[2] = Cr*(referenceWhiteCr - referenceBlackCr)/codingRangeCbCr + referenceBlackCr; } public void toRGB(float x0, float x1, float x2, float[] rgb) { // Convert YCbCr code to full-range YCbCr. float Y = (x0 - referenceBlackY)*codingRangeY/ (referenceWhiteY - referenceBlackY); float Cb = (x1 - referenceBlackCb)*codingRangeCbCr/ (referenceWhiteCb - referenceBlackCb); float Cr = (x2 - referenceBlackCr)*codingRangeCbCr/ (referenceWhiteCr - referenceBlackCr); // Convert YCbCr to RGB. rgb[0] = Cr*(2 - 2*LumaRed) + Y; rgb[2] = Cb*(2 - 2*LumaBlue) + Y; rgb[1] = (Y - LumaBlue*rgb[2] - LumaRed*rgb[0])/LumaGreen; } } jai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/tiff/TIFFDeflater.java0000664000175100017510000001221110203036165031415 0ustar tilletille/* * $RCSfile: TIFFDeflater.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.1 $ * $Date: 2005-02-11 05:01:45 $ * $State: Exp $ */ package com.sun.media.imageioimpl.plugins.tiff; import com.sun.media.imageio.plugins.tiff.BaselineTIFFTagSet; import com.sun.media.imageio.plugins.tiff.TIFFCompressor; import java.io.IOException; import java.util.zip.Deflater; import javax.imageio.ImageWriteParam; /** * Compressor superclass for Deflate and ZLib compression. */ public class TIFFDeflater extends TIFFCompressor { Deflater deflater; int predictor; public TIFFDeflater(String compressionType, int compressionTagValue, ImageWriteParam param, int predictorValue) { super(compressionType, compressionTagValue, true); this.predictor = predictorValue; // Set the deflate level. int deflateLevel; if(param != null && param.getCompressionMode() == ImageWriteParam.MODE_EXPLICIT) { float quality = param.getCompressionQuality(); deflateLevel = (int)(1 + 8*quality); } else { deflateLevel = Deflater.DEFAULT_COMPRESSION; } this.deflater = new Deflater(deflateLevel); } public int encode(byte[] b, int off, int width, int height, int[] bitsPerSample, int scanlineStride) throws IOException { int inputSize = height*scanlineStride; int blocks = (inputSize + 32767)/32768; // Worst case for Zlib deflate is input size + 5 bytes per 32k // block, plus 6 header bytes byte[] compData = new byte[inputSize + 5*blocks + 6]; int numCompressedBytes = 0; if(predictor == BaselineTIFFTagSet.PREDICTOR_HORIZONTAL_DIFFERENCING) { int samplesPerPixel = bitsPerSample.length; int bitsPerPixel = 0; for (int i = 0; i < samplesPerPixel; i++) { bitsPerPixel += bitsPerSample[i]; } int bytesPerRow = (bitsPerPixel*width + 7)/8; byte[] rowBuf = new byte[bytesPerRow]; int maxRow = height - 1; for(int i = 0; i < height; i++) { // Cannot modify b[] in place as it might be a data // array from the image being written so make a copy. System.arraycopy(b, off, rowBuf, 0, bytesPerRow); for(int j = bytesPerRow - 1; j >= samplesPerPixel; j--) { rowBuf[j] -= rowBuf[j - samplesPerPixel]; } deflater.setInput(rowBuf); if(i == maxRow) { deflater.finish(); } int numBytes = 0; while((numBytes = deflater.deflate(compData, numCompressedBytes, compData.length - numCompressedBytes)) != 0) { numCompressedBytes += numBytes; } off += scanlineStride; } } else { deflater.setInput(b, off, height*scanlineStride); deflater.finish(); numCompressedBytes = deflater.deflate(compData); } deflater.reset(); stream.write(compData, 0, numCompressedBytes); return numCompressedBytes; } } jai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/tiff/TIFFImageReader.java0000664000175100017510000016320510732276076032064 0ustar tilletille/* * $RCSfile: TIFFImageReader.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.13 $ * $Date: 2007-12-19 20:17:02 $ * $State: Exp $ */ package com.sun.media.imageioimpl.plugins.tiff; import java.awt.Point; import java.awt.Rectangle; import java.awt.color.ColorSpace; import java.awt.color.ICC_ColorSpace; import java.awt.color.ICC_Profile; import java.awt.image.BufferedImage; import java.awt.image.ColorModel; import java.awt.image.ComponentColorModel; import java.awt.image.ComponentSampleModel; import java.awt.image.DataBuffer; import java.awt.image.DataBufferByte; import java.awt.image.MultiPixelPackedSampleModel; import java.awt.image.Raster; import java.awt.image.RenderedImage; import java.awt.image.SampleModel; import java.awt.image.SinglePixelPackedSampleModel; import java.awt.image.WritableRaster; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.nio.ByteOrder; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.Iterator; import java.util.List; import javax.imageio.IIOException; import javax.imageio.ImageIO; import javax.imageio.ImageReader; import javax.imageio.ImageReadParam; import javax.imageio.ImageTypeSpecifier; import javax.imageio.metadata.IIOMetadata; import javax.imageio.spi.ImageReaderSpi; import javax.imageio.stream.ImageInputStream; import javax.imageio.stream.MemoryCacheImageInputStream; import org.w3c.dom.Node; import com.sun.media.imageio.plugins.tiff.BaselineTIFFTagSet; import com.sun.media.imageio.plugins.tiff.TIFFColorConverter; import com.sun.media.imageio.plugins.tiff.TIFFDecompressor; import com.sun.media.imageio.plugins.tiff.TIFFField; import com.sun.media.imageio.plugins.tiff.TIFFImageReadParam; import com.sun.media.imageio.plugins.tiff.TIFFTag; import com.sun.media.imageioimpl.common.ImageUtil; import com.sun.media.imageioimpl.common.PackageUtil; public class TIFFImageReader extends ImageReader { private static final boolean DEBUG = false; // XXX 'false' for release!!! // The current ImageInputStream source. ImageInputStream stream = null; // True if the file header has been read. boolean gotHeader = false; ImageReadParam imageReadParam = getDefaultReadParam(); // Stream metadata, or null. TIFFStreamMetadata streamMetadata = null; // The current image index. int currIndex = -1; // Metadata for image at 'currIndex', or null. TIFFImageMetadata imageMetadata = null; // A List of Longs indicating the stream // positions of the start of the IFD for each image. Entries // are added as needed. List imageStartPosition = new ArrayList(); // The number of images in the stream, if known, otherwise -1. int numImages = -1; // The ImageTypeSpecifiers of the images in the stream. // Contains a map of Integers to Lists. HashMap imageTypeMap = new HashMap(); BufferedImage theImage = null; int width = -1; int height = -1; int numBands = -1; int tileOrStripWidth = -1, tileOrStripHeight = -1; int planarConfiguration = BaselineTIFFTagSet.PLANAR_CONFIGURATION_CHUNKY; int rowsDone = 0; int compression; int photometricInterpretation; int samplesPerPixel; int[] sampleFormat; int[] bitsPerSample; int[] extraSamples; char[] colorMap; int sourceXOffset; int sourceYOffset; int srcXSubsampling; int srcYSubsampling; int dstWidth; int dstHeight; int dstMinX; int dstMinY; int dstXOffset; int dstYOffset; int tilesAcross; int tilesDown; int pixelsRead; int pixelsToRead; public TIFFImageReader(ImageReaderSpi originatingProvider) { super(originatingProvider); } public void setInput(Object input, boolean seekForwardOnly, boolean ignoreMetadata) { super.setInput(input, seekForwardOnly, ignoreMetadata); // Clear all local values based on the previous stream contents. resetLocal(); if (input != null) { if (!(input instanceof ImageInputStream)) { throw new IllegalArgumentException ("input not an ImageInputStream!"); } this.stream = (ImageInputStream)input; } else { this.stream = null; } } // Do not seek to the beginning of the stream so as to allow users to // point us at an IFD within some other file format private void readHeader() throws IIOException { if (gotHeader) { return; } if (stream == null) { throw new IllegalStateException("Input not set!"); } // Create an object to store the stream metadata this.streamMetadata = new TIFFStreamMetadata(); try { int byteOrder = stream.readUnsignedShort(); if (byteOrder == 0x4d4d) { streamMetadata.byteOrder = ByteOrder.BIG_ENDIAN; stream.setByteOrder(ByteOrder.BIG_ENDIAN); } else if (byteOrder == 0x4949) { streamMetadata.byteOrder = ByteOrder.LITTLE_ENDIAN; stream.setByteOrder(ByteOrder.LITTLE_ENDIAN); } else { processWarningOccurred( "Bad byte order in header, assuming little-endian"); streamMetadata.byteOrder = ByteOrder.LITTLE_ENDIAN; stream.setByteOrder(ByteOrder.LITTLE_ENDIAN); } int magic = stream.readUnsignedShort(); if (magic != 42) { processWarningOccurred( "Bad magic number in header, continuing"); } // Seek to start of first IFD long offset = stream.readUnsignedInt(); imageStartPosition.add(new Long(offset)); stream.seek(offset); } catch (IOException e) { throw new IIOException("I/O error reading header!", e); } gotHeader = true; } private int locateImage(int imageIndex) throws IIOException { readHeader(); try { // Find closest known index int index = Math.min(imageIndex, imageStartPosition.size() - 1); // Seek to that position Long l = (Long)imageStartPosition.get(index); stream.seek(l.longValue()); // Skip IFDs until at desired index or last image found while (index < imageIndex) { int count = stream.readUnsignedShort(); stream.skipBytes(12*count); long offset = stream.readUnsignedInt(); if (offset == 0) { return index; } imageStartPosition.add(new Long(offset)); stream.seek(offset); ++index; } } catch (IOException e) { throw new IIOException("Couldn't seek!", e); } if (currIndex != imageIndex) { imageMetadata = null; } currIndex = imageIndex; return imageIndex; } public int getNumImages(boolean allowSearch) throws IOException { if (stream == null) { throw new IllegalStateException("Input not set!"); } if (seekForwardOnly && allowSearch) { throw new IllegalStateException ("seekForwardOnly and allowSearch can't both be true!"); } if (numImages > 0) { return numImages; } if (allowSearch) { this.numImages = locateImage(Integer.MAX_VALUE) + 1; } return numImages; } public IIOMetadata getStreamMetadata() throws IIOException { readHeader(); return streamMetadata; } // Throw an IndexOutOfBoundsException if index < minIndex, // and bump minIndex if required. private void checkIndex(int imageIndex) { if (imageIndex < minIndex) { throw new IndexOutOfBoundsException("imageIndex < minIndex!"); } if (seekForwardOnly) { minIndex = imageIndex; } } // Verify that imageIndex is in bounds, find the image IFD, read the // image metadata, initialize instance variables from the metadata. private void seekToImage(int imageIndex) throws IIOException { checkIndex(imageIndex); int index = locateImage(imageIndex); if (index != imageIndex) { throw new IndexOutOfBoundsException("imageIndex out of bounds!"); } readMetadata(); initializeFromMetadata(); } // Stream must be positioned at start of IFD for 'currIndex' private void readMetadata() throws IIOException { if (stream == null) { throw new IllegalStateException("Input not set!"); } if (imageMetadata != null) { return; } try { // Create an object to store the image metadata List tagSets; if (imageReadParam instanceof TIFFImageReadParam) { tagSets = ((TIFFImageReadParam)imageReadParam).getAllowedTagSets(); } else { tagSets = new ArrayList(1); tagSets.add(BaselineTIFFTagSet.getInstance()); } this.imageMetadata = new TIFFImageMetadata(tagSets); imageMetadata.initializeFromStream(stream, ignoreMetadata); } catch (IIOException iioe) { throw iioe; } catch (IOException ioe) { throw new IIOException("I/O error reading image metadata!", ioe); } } private int getWidth() { return this.width; } private int getHeight() { return this.height; } private int getNumBands() { return this.numBands; } // Returns tile width if image is tiled, else image width private int getTileOrStripWidth() { TIFFField f = imageMetadata.getTIFFField(BaselineTIFFTagSet.TAG_TILE_WIDTH); return (f == null) ? getWidth() : f.getAsInt(0); } // Returns tile height if image is tiled, else strip height private int getTileOrStripHeight() { TIFFField f = imageMetadata.getTIFFField(BaselineTIFFTagSet.TAG_TILE_LENGTH); if (f != null) { return f.getAsInt(0); } f = imageMetadata.getTIFFField(BaselineTIFFTagSet.TAG_ROWS_PER_STRIP); // Default for ROWS_PER_STRIP is 2^32 - 1, i.e., infinity int h = (f == null) ? -1 : f.getAsInt(0); return (h == -1) ? getHeight() : h; } private int getPlanarConfiguration() { TIFFField f = imageMetadata.getTIFFField(BaselineTIFFTagSet.TAG_PLANAR_CONFIGURATION); if (f != null) { int planarConfigurationValue = f.getAsInt(0); if(planarConfigurationValue == BaselineTIFFTagSet.PLANAR_CONFIGURATION_PLANAR) { // Some writers (e.g. Kofax standard Multi-Page TIFF // Storage Filter v2.01.000; cf. bug 4929147) do not // correctly set the value of this field. Attempt to // ascertain whether the value is correctly Planar. if(getCompression() == BaselineTIFFTagSet.COMPRESSION_OLD_JPEG && imageMetadata.getTIFFField(BaselineTIFFTagSet.TAG_JPEG_INTERCHANGE_FORMAT) != null) { // JPEG interchange format cannot have // PlanarConfiguration value Chunky so reset. processWarningOccurred("PlanarConfiguration \"Planar\" value inconsistent with JPEGInterchangeFormat; resetting to \"Chunky\"."); planarConfigurationValue = BaselineTIFFTagSet.PLANAR_CONFIGURATION_CHUNKY; } else { TIFFField offsetField = imageMetadata.getTIFFField(BaselineTIFFTagSet.TAG_TILE_OFFSETS); if (offsetField == null) { // Tiles offsetField = imageMetadata.getTIFFField(BaselineTIFFTagSet.TAG_STRIP_OFFSETS); int tw = getTileOrStripWidth(); int th = getTileOrStripHeight(); int tAcross = (getWidth() + tw - 1)/tw; int tDown = (getHeight() + th - 1)/th; int tilesPerImage = tAcross*tDown; long[] offsetArray = offsetField.getAsLongs(); if(offsetArray != null && offsetArray.length == tilesPerImage) { // Length of offsets array is // TilesPerImage for Chunky and // SamplesPerPixel*TilesPerImage for Planar. processWarningOccurred("PlanarConfiguration \"Planar\" value inconsistent with TileOffsets field value count; resetting to \"Chunky\"."); planarConfigurationValue = BaselineTIFFTagSet.PLANAR_CONFIGURATION_CHUNKY; } } else { // Strips int rowsPerStrip = getTileOrStripHeight(); int stripsPerImage = (getHeight() + rowsPerStrip - 1)/rowsPerStrip; long[] offsetArray = offsetField.getAsLongs(); if(offsetArray != null && offsetArray.length == stripsPerImage) { // Length of offsets array is // StripsPerImage for Chunky and // SamplesPerPixel*StripsPerImage for Planar. processWarningOccurred("PlanarConfiguration \"Planar\" value inconsistent with StripOffsets field value count; resetting to \"Chunky\"."); planarConfigurationValue = BaselineTIFFTagSet.PLANAR_CONFIGURATION_CHUNKY; } } } } return planarConfigurationValue; } return BaselineTIFFTagSet.PLANAR_CONFIGURATION_CHUNKY; } private long getTileOrStripOffset(int tileIndex) throws IIOException { TIFFField f = imageMetadata.getTIFFField(BaselineTIFFTagSet.TAG_TILE_OFFSETS); if (f == null) { f = imageMetadata.getTIFFField(BaselineTIFFTagSet.TAG_STRIP_OFFSETS); } if (f == null) { f = imageMetadata.getTIFFField(BaselineTIFFTagSet.TAG_JPEG_INTERCHANGE_FORMAT); } if(f == null) { throw new IIOException ("Missing required strip or tile offsets field."); } return f.getAsLong(tileIndex); } private long getTileOrStripByteCount(int tileIndex) throws IOException { TIFFField f = imageMetadata.getTIFFField(BaselineTIFFTagSet.TAG_TILE_BYTE_COUNTS); if (f == null) { f = imageMetadata.getTIFFField(BaselineTIFFTagSet.TAG_STRIP_BYTE_COUNTS); } if (f == null) { f = imageMetadata.getTIFFField(BaselineTIFFTagSet.TAG_JPEG_INTERCHANGE_FORMAT_LENGTH); } long tileOrStripByteCount; if(f != null) { tileOrStripByteCount = f.getAsLong(tileIndex); } else { processWarningOccurred("TIFF directory contains neither StripByteCounts nor TileByteCounts field: attempting to calculate from strip or tile width and height."); // Initialize to number of bytes per strip or tile assuming // no compression. int bitsPerPixel = bitsPerSample[0]; for(int i = 1; i < samplesPerPixel; i++) { bitsPerPixel += bitsPerSample[i]; } int bytesPerRow = (getTileOrStripWidth()*bitsPerPixel + 7)/8; tileOrStripByteCount = bytesPerRow*getTileOrStripHeight(); // Clamp to end of stream if possible. long streamLength = stream.length(); if(streamLength != -1) { tileOrStripByteCount = Math.min(tileOrStripByteCount, streamLength - getTileOrStripOffset(tileIndex)); } else { processWarningOccurred("Stream length is unknown: cannot clamp estimated strip or tile byte count to EOF."); } } return tileOrStripByteCount; } private int getCompression() { TIFFField f = imageMetadata.getTIFFField(BaselineTIFFTagSet.TAG_COMPRESSION); if (f == null) { return BaselineTIFFTagSet.COMPRESSION_NONE; } else { return f.getAsInt(0); } } public int getWidth(int imageIndex) throws IOException { seekToImage(imageIndex); return getWidth(); } public int getHeight(int imageIndex) throws IOException { seekToImage(imageIndex); return getHeight(); } /** * Initializes these instance variables from the image metadata: *

     * compression
     * width
     * height
     * samplesPerPixel
     * numBands
     * colorMap
     * photometricInterpretation
     * sampleFormat
     * bitsPerSample
     * extraSamples
     * tileOrStripWidth
     * tileOrStripHeight
     * 
*/ private void initializeFromMetadata() { TIFFField f; // Compression f = imageMetadata.getTIFFField(BaselineTIFFTagSet.TAG_COMPRESSION); if (f == null) { processWarningOccurred ("Compression field is missing; assuming no compression"); compression = BaselineTIFFTagSet.COMPRESSION_NONE; } else { compression = f.getAsInt(0); } // Whether key dimensional information is absent. boolean isMissingDimension = false; // ImageWidth -> width f = imageMetadata.getTIFFField(BaselineTIFFTagSet.TAG_IMAGE_WIDTH); if (f != null) { this.width = f.getAsInt(0); } else { processWarningOccurred("ImageWidth field is missing."); isMissingDimension = true; } // ImageLength -> height f = imageMetadata.getTIFFField(BaselineTIFFTagSet.TAG_IMAGE_LENGTH); if (f != null) { this.height = f.getAsInt(0); } else { processWarningOccurred("ImageLength field is missing."); isMissingDimension = true; } // SamplesPerPixel f = imageMetadata.getTIFFField(BaselineTIFFTagSet.TAG_SAMPLES_PER_PIXEL); if (f != null) { samplesPerPixel = f.getAsInt(0); } else { samplesPerPixel = 1; isMissingDimension = true; } // If any dimension is missing and there is a JPEG stream available // get the information from it. int defaultBitDepth = 1; if(isMissingDimension && (f = imageMetadata.getTIFFField(BaselineTIFFTagSet.TAG_JPEG_INTERCHANGE_FORMAT)) != null) { Iterator iter = ImageIO.getImageReadersByFormatName("JPEG"); if(iter != null && iter.hasNext()) { ImageReader jreader = (ImageReader)iter.next(); try { stream.mark(); stream.seek(f.getAsLong(0)); jreader.setInput(stream); if(imageMetadata.getTIFFField(BaselineTIFFTagSet.TAG_IMAGE_WIDTH) == null) { this.width = jreader.getWidth(0); } if(imageMetadata.getTIFFField(BaselineTIFFTagSet.TAG_IMAGE_LENGTH) == null) { this.height = jreader.getHeight(0); } ImageTypeSpecifier imageType = jreader.getRawImageType(0); if(imageMetadata.getTIFFField(BaselineTIFFTagSet.TAG_SAMPLES_PER_PIXEL) == null) { this.samplesPerPixel = imageType.getSampleModel().getNumBands(); } stream.reset(); defaultBitDepth = imageType.getColorModel().getComponentSize(0); } catch(IOException e) { // Ignore it and proceed: an error will occur later. } jreader.dispose(); } } if (samplesPerPixel < 1) { processWarningOccurred("Samples per pixel < 1!"); } // SamplesPerPixel -> numBands numBands = samplesPerPixel; // ColorMap this.colorMap = null; f = imageMetadata.getTIFFField(BaselineTIFFTagSet.TAG_COLOR_MAP); if (f != null) { // Grab color map colorMap = f.getAsChars(); } // PhotometricInterpretation f = imageMetadata.getTIFFField(BaselineTIFFTagSet.TAG_PHOTOMETRIC_INTERPRETATION); if (f == null) { if (compression == BaselineTIFFTagSet.COMPRESSION_CCITT_RLE || compression == BaselineTIFFTagSet.COMPRESSION_CCITT_T_4 || compression == BaselineTIFFTagSet.COMPRESSION_CCITT_T_6) { processWarningOccurred ("PhotometricInterpretation field is missing; "+ "assuming WhiteIsZero"); photometricInterpretation = BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_WHITE_IS_ZERO; } else if(this.colorMap != null) { photometricInterpretation = BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_PALETTE_COLOR; } else if(samplesPerPixel == 3 || samplesPerPixel == 4) { photometricInterpretation = BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_RGB; } else { processWarningOccurred ("PhotometricInterpretation field is missing; "+ "assuming BlackIsZero"); photometricInterpretation = BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_BLACK_IS_ZERO; } } else { photometricInterpretation = f.getAsInt(0); } // SampleFormat boolean replicateFirst = false; int first = -1; f = imageMetadata.getTIFFField(BaselineTIFFTagSet.TAG_SAMPLE_FORMAT); sampleFormat = new int[samplesPerPixel]; replicateFirst = false; if (f == null) { replicateFirst = true; first = BaselineTIFFTagSet.SAMPLE_FORMAT_UNDEFINED; } else if (f.getCount() != samplesPerPixel) { replicateFirst = true; first = f.getAsInt(0); } for (int i = 0; i < samplesPerPixel; i++) { sampleFormat[i] = replicateFirst ? first : f.getAsInt(i); if (sampleFormat[i] != BaselineTIFFTagSet.SAMPLE_FORMAT_UNSIGNED_INTEGER && sampleFormat[i] != BaselineTIFFTagSet.SAMPLE_FORMAT_SIGNED_INTEGER && sampleFormat[i] != BaselineTIFFTagSet.SAMPLE_FORMAT_FLOATING_POINT && sampleFormat[i] != BaselineTIFFTagSet.SAMPLE_FORMAT_UNDEFINED) { processWarningOccurred( "Illegal value for SAMPLE_FORMAT, assuming SAMPLE_FORMAT_UNDEFINED"); sampleFormat[i] = BaselineTIFFTagSet.SAMPLE_FORMAT_UNDEFINED; } } // BitsPerSample f = imageMetadata.getTIFFField(BaselineTIFFTagSet.TAG_BITS_PER_SAMPLE); this.bitsPerSample = new int[samplesPerPixel]; replicateFirst = false; if (f == null) { replicateFirst = true; first = defaultBitDepth; } else if (f.getCount() != samplesPerPixel) { replicateFirst = true; first = f.getAsInt(0); } for (int i = 0; i < samplesPerPixel; i++) { // Replicate initial value if not enough values provided bitsPerSample[i] = replicateFirst ? first : f.getAsInt(i); if (DEBUG) { System.out.println("bitsPerSample[" + i + "] = " + bitsPerSample[i]); } } // ExtraSamples this.extraSamples = null; f = imageMetadata.getTIFFField(BaselineTIFFTagSet.TAG_EXTRA_SAMPLES); if (f != null) { extraSamples = f.getAsInts(); } // System.out.println("colorMap = " + colorMap); // if (colorMap != null) { // for (int i = 0; i < colorMap.length; i++) { // System.out.println("colorMap[" + i + "] = " + (int)(colorMap[i])); // } // } } public Iterator getImageTypes(int imageIndex) throws IIOException { List l; // List of ImageTypeSpecifiers Integer imageIndexInteger = new Integer(imageIndex); if(imageTypeMap.containsKey(imageIndexInteger)) { // Return the cached ITS List. l = (List)imageTypeMap.get(imageIndexInteger); } else { // Create a new ITS List. l = new ArrayList(1); // Create the ITS and cache if for later use so that this method // always returns an Iterator containing the same ITS objects. seekToImage(imageIndex); ImageTypeSpecifier itsRaw = TIFFDecompressor.getRawImageTypeSpecifier (photometricInterpretation, compression, samplesPerPixel, bitsPerSample, sampleFormat, extraSamples, colorMap); // Check for an ICCProfile field. TIFFField iccProfileField = imageMetadata.getTIFFField(BaselineTIFFTagSet.TAG_ICC_PROFILE); // If an ICCProfile field is present change the ImageTypeSpecifier // to use it if the data layout is component type. if(iccProfileField != null && itsRaw.getColorModel() instanceof ComponentColorModel) { // Create a ColorSpace from the profile. byte[] iccProfileValue = iccProfileField.getAsBytes(); ICC_Profile iccProfile = ICC_Profile.getInstance(iccProfileValue); ICC_ColorSpace iccColorSpace = new ICC_ColorSpace(iccProfile); // Get the raw sample and color information. ColorModel cmRaw = itsRaw.getColorModel(); ColorSpace csRaw = cmRaw.getColorSpace(); SampleModel smRaw = itsRaw.getSampleModel(); // Get the number of samples per pixel and the number // of color components. int numBands = smRaw.getNumBands(); int numComponents = iccColorSpace.getNumComponents(); // Replace the ColorModel with the ICC ColorModel if the // numbers of samples and color components are amenable. if(numBands == numComponents || numBands == numComponents + 1) { // Set alpha flags. boolean hasAlpha = numComponents != numBands; boolean isAlphaPre = hasAlpha && cmRaw.isAlphaPremultiplied(); // Create a ColorModel of the same class and with // the same transfer type. ColorModel iccColorModel = new ComponentColorModel(iccColorSpace, cmRaw.getComponentSize(), hasAlpha, isAlphaPre, cmRaw.getTransparency(), cmRaw.getTransferType()); // Prepend the ICC profile-based ITS to the List. The // ColorModel and SampleModel are guaranteed to be // compatible as the old and new ColorModels are both // ComponentColorModels with the same transfer type // and the same number of components. l.add(new ImageTypeSpecifier(iccColorModel, smRaw)); // Append the raw ITS to the List if and only if its // ColorSpace has the same type and number of components // as the ICC ColorSpace. if(csRaw.getType() == iccColorSpace.getType() && csRaw.getNumComponents() == iccColorSpace.getNumComponents()) { l.add(itsRaw); } } else { // ICCProfile not compatible with SampleModel. // Append the raw ITS to the List. l.add(itsRaw); } } else { // No ICCProfile field or raw ColorModel not component. // Append the raw ITS to the List. l.add(itsRaw); } // Cache the ITS List. imageTypeMap.put(imageIndexInteger, l); } return l.iterator(); } public IIOMetadata getImageMetadata(int imageIndex) throws IIOException { seekToImage(imageIndex); TIFFImageMetadata im = new TIFFImageMetadata(imageMetadata.getRootIFD().getTagSetList()); Node root = imageMetadata.getAsTree(TIFFImageMetadata.nativeMetadataFormatName); im.setFromTree(TIFFImageMetadata.nativeMetadataFormatName, root); return im; } public IIOMetadata getStreamMetadata(int imageIndex) throws IIOException { readHeader(); TIFFStreamMetadata sm = new TIFFStreamMetadata(); Node root = sm.getAsTree(TIFFStreamMetadata.nativeMetadataFormatName); sm.setFromTree(TIFFStreamMetadata.nativeMetadataFormatName, root); return sm; } public boolean isRandomAccessEasy(int imageIndex) throws IOException { if(currIndex != -1) { seekToImage(currIndex); return getCompression() == BaselineTIFFTagSet.COMPRESSION_NONE; } else { return false; } } // Thumbnails public boolean readSupportsThumbnails() { return false; } public boolean hasThumbnails(int imageIndex) { return false; } public int getNumThumbnails(int imageIndex) throws IOException { return 0; } public ImageReadParam getDefaultReadParam() { return new TIFFImageReadParam(); } public boolean isImageTiled(int imageIndex) throws IOException { seekToImage(imageIndex); TIFFField f = imageMetadata.getTIFFField(BaselineTIFFTagSet.TAG_TILE_WIDTH); return f != null; } public int getTileWidth(int imageIndex) throws IOException { seekToImage(imageIndex); return getTileOrStripWidth(); } public int getTileHeight(int imageIndex) throws IOException { seekToImage(imageIndex); return getTileOrStripHeight(); } public BufferedImage readTile(int imageIndex, int tileX, int tileY) throws IOException { int w = getWidth(imageIndex); int h = getHeight(imageIndex); int tw = getTileWidth(imageIndex); int th = getTileHeight(imageIndex); int x = tw*tileX; int y = th*tileY; if(tileX < 0 || tileY < 0 || x >= w || y >= h) { throw new IllegalArgumentException ("Tile indices are out of bounds!"); } if (x + tw > w) { tw = w - x; } if (y + th > h) { th = h - y; } ImageReadParam param = getDefaultReadParam(); Rectangle tileRect = new Rectangle(x, y, tw, th); param.setSourceRegion(tileRect); return read(imageIndex, param); } public boolean canReadRaster() { // Enable this? return false; } public Raster readRaster(int imageIndex, ImageReadParam param) throws IOException { // Enable this? throw new UnsupportedOperationException(); } // public BufferedImage readTileRaster(int imageIndex, // int tileX, int tileY) // throws IOException { // } private int[] sourceBands; private int[] destinationBands; private TIFFDecompressor decompressor; // floor(num/den) private static int ifloor(int num, int den) { if (num < 0) { num -= den - 1; } return num/den; } // ceil(num/den) private static int iceil(int num, int den) { if (num > 0) { num += den - 1; } return num/den; } private void prepareRead(int imageIndex, ImageReadParam param) throws IOException { if (stream == null) { throw new IllegalStateException("Input not set!"); } // A null ImageReadParam means we use the default if (param == null) { param = getDefaultReadParam(); } this.imageReadParam = param; seekToImage(imageIndex); this.tileOrStripWidth = getTileOrStripWidth(); this.tileOrStripHeight = getTileOrStripHeight(); this.planarConfiguration = getPlanarConfiguration(); this.sourceBands = param.getSourceBands(); if (sourceBands == null) { sourceBands = new int[numBands]; for (int i = 0; i < numBands; i++) { sourceBands[i] = i; } } // Initialize the destination image Iterator imageTypes = getImageTypes(imageIndex); ImageTypeSpecifier theImageType = ImageUtil.getDestinationType(param, imageTypes); int destNumBands = theImageType.getSampleModel().getNumBands(); this.destinationBands = param.getDestinationBands(); if (destinationBands == null) { destinationBands = new int[destNumBands]; for (int i = 0; i < destNumBands; i++) { destinationBands[i] = i; } } if (sourceBands.length != destinationBands.length) { throw new IllegalArgumentException( "sourceBands.length != destinationBands.length"); } for (int i = 0; i < sourceBands.length; i++) { int sb = sourceBands[i]; if (sb < 0 || sb >= numBands) { throw new IllegalArgumentException( "Source band out of range!"); } int db = destinationBands[i]; if (db < 0 || db >= destNumBands) { throw new IllegalArgumentException( "Destination band out of range!"); } } } public RenderedImage readAsRenderedImage(int imageIndex, ImageReadParam param) throws IOException { prepareRead(imageIndex, param); return new TIFFRenderedImage(this, imageIndex, imageReadParam, width, height); } private void decodeTile(int ti, int tj, int band) throws IOException { if(DEBUG) { System.out.println("decodeTile("+ti+","+tj+","+band+")"); } // Compute the region covered by the strip or tile Rectangle tileRect = new Rectangle(ti*tileOrStripWidth, tj*tileOrStripHeight, tileOrStripWidth, tileOrStripHeight); // Clip against the image bounds if the image is not tiled. If it // is tiled, the tile may legally extend beyond the image bounds. if(!isImageTiled(currIndex)) { tileRect = tileRect.intersection(new Rectangle(0, 0, width, height)); } // Return if the intersection is empty. if(tileRect.width <= 0 || tileRect.height <= 0) { return; } int srcMinX = tileRect.x; int srcMinY = tileRect.y; int srcWidth = tileRect.width; int srcHeight = tileRect.height; // Determine dest region that can be derived from the // source region dstMinX = iceil(srcMinX - sourceXOffset, srcXSubsampling); int dstMaxX = ifloor(srcMinX + srcWidth - 1 - sourceXOffset, srcXSubsampling); dstMinY = iceil(srcMinY - sourceYOffset, srcYSubsampling); int dstMaxY = ifloor(srcMinY + srcHeight - 1 - sourceYOffset, srcYSubsampling); dstWidth = dstMaxX - dstMinX + 1; dstHeight = dstMaxY - dstMinY + 1; dstMinX += dstXOffset; dstMinY += dstYOffset; // Clip against image bounds Rectangle dstRect = new Rectangle(dstMinX, dstMinY, dstWidth, dstHeight); dstRect = dstRect.intersection(theImage.getRaster().getBounds()); dstMinX = dstRect.x; dstMinY = dstRect.y; dstWidth = dstRect.width; dstHeight = dstRect.height; if (dstWidth <= 0 || dstHeight <= 0) { return; } // Backwards map dest region to source to determine // active source region int activeSrcMinX = (dstMinX - dstXOffset)*srcXSubsampling + sourceXOffset; int sxmax = (dstMinX + dstWidth - 1 - dstXOffset)*srcXSubsampling + sourceXOffset; int activeSrcWidth = sxmax - activeSrcMinX + 1; int activeSrcMinY = (dstMinY - dstYOffset)*srcYSubsampling + sourceYOffset; int symax = (dstMinY + dstHeight - 1 - dstYOffset)*srcYSubsampling + sourceYOffset; int activeSrcHeight = symax - activeSrcMinY + 1; decompressor.setSrcMinX(srcMinX); decompressor.setSrcMinY(srcMinY); decompressor.setSrcWidth(srcWidth); decompressor.setSrcHeight(srcHeight); decompressor.setDstMinX(dstMinX); decompressor.setDstMinY(dstMinY); decompressor.setDstWidth(dstWidth); decompressor.setDstHeight(dstHeight); decompressor.setActiveSrcMinX(activeSrcMinX); decompressor.setActiveSrcMinY(activeSrcMinY); decompressor.setActiveSrcWidth(activeSrcWidth); decompressor.setActiveSrcHeight(activeSrcHeight); int tileIndex = tj*tilesAcross + ti; if (planarConfiguration == BaselineTIFFTagSet.PLANAR_CONFIGURATION_PLANAR) { tileIndex += band*tilesAcross*tilesDown; } long offset = getTileOrStripOffset(tileIndex); long byteCount = getTileOrStripByteCount(tileIndex); // // Attempt to handle truncated streams, i.e., where reading the // compressed strip or tile would result in an EOFException. The // number of bytes to read is clamped to the number available // from the stream starting at the indicated position in the hope // that the decompressor will handle it. // long streamLength = stream.length(); if(streamLength > 0 && offset + byteCount > streamLength) { processWarningOccurred("Attempting to process truncated stream."); if(Math.max(byteCount = streamLength - offset, 0) == 0) { processWarningOccurred("No bytes in strip/tile: skipping."); return; } } decompressor.setStream(stream); decompressor.setOffset(offset); decompressor.setByteCount((int)byteCount); decompressor.beginDecoding(); stream.mark(); decompressor.decode(); stream.reset(); } private void reportProgress() { // Report image progress/update to listeners after each tile pixelsRead += dstWidth*dstHeight; processImageProgress(100.0f*pixelsRead/pixelsToRead); processImageUpdate(theImage, dstMinX, dstMinY, dstWidth, dstHeight, 1, 1, destinationBands); } public BufferedImage read(int imageIndex, ImageReadParam param) throws IOException { prepareRead(imageIndex, param); this.theImage = getDestination(param, getImageTypes(imageIndex), width, height); srcXSubsampling = imageReadParam.getSourceXSubsampling(); srcYSubsampling = imageReadParam.getSourceYSubsampling(); Point p = imageReadParam.getDestinationOffset(); dstXOffset = p.x; dstYOffset = p.y; // This could probably be made more efficient... Rectangle srcRegion = new Rectangle(0, 0, 0, 0); Rectangle destRegion = new Rectangle(0, 0, 0, 0); computeRegions(imageReadParam, width, height, theImage, srcRegion, destRegion); // Initial source pixel, taking source region and source // subsamplimg offsets into account sourceXOffset = srcRegion.x; sourceYOffset = srcRegion.y; pixelsToRead = destRegion.width*destRegion.height; pixelsRead = 0; processImageStarted(imageIndex); processImageProgress(0.0f); tilesAcross = (width + tileOrStripWidth - 1)/tileOrStripWidth; tilesDown = (height + tileOrStripHeight - 1)/tileOrStripHeight; int compression = getCompression(); // Attempt to get decompressor and color converted from the read param TIFFColorConverter colorConverter = null; if (imageReadParam instanceof TIFFImageReadParam) { TIFFImageReadParam tparam = (TIFFImageReadParam)imageReadParam; this.decompressor = tparam.getTIFFDecompressor(); colorConverter = tparam.getColorConverter(); } // If we didn't find one, use a standard decompressor if (this.decompressor == null) { if (compression == BaselineTIFFTagSet.COMPRESSION_NONE) { // Get the fillOrder field. TIFFField fillOrderField = imageMetadata.getTIFFField(BaselineTIFFTagSet.TAG_FILL_ORDER); // Set the decompressor based on the fill order. if(fillOrderField != null && fillOrderField.getAsInt(0) == 2) { this.decompressor = new TIFFLSBDecompressor(); } else { this.decompressor = new TIFFNullDecompressor(); } } else if (compression == BaselineTIFFTagSet.COMPRESSION_CCITT_T_6) { // Try to create the codecLib decompressor. if(PackageUtil.isCodecLibAvailable()) { try { this.decompressor = new TIFFCodecLibFaxDecompressor(compression); if(DEBUG) { System.out.println ("Using codecLib T.6 decompressor"); } } catch (RuntimeException re) { if(DEBUG) { System.out.println(re); } } } // Fall back to the Java decompressor. if (this.decompressor == null) { if(DEBUG) { System.out.println("Using Java T.6 decompressor"); } this.decompressor = new TIFFFaxDecompressor(); } } else if (compression == BaselineTIFFTagSet.COMPRESSION_CCITT_T_4) { if(PackageUtil.isCodecLibAvailable()) { // Try to create the codecLib decompressor. try { this.decompressor = new TIFFCodecLibFaxDecompressor(compression); if(DEBUG) { System.out.println ("Using codecLib T.4 decompressor"); } } catch (RuntimeException re) { if(DEBUG) { System.out.println(re); } } } // Fall back to the Java decompressor. if (this.decompressor == null) { if(DEBUG) { System.out.println("Using Java T.4 decompressor"); } this.decompressor = new TIFFFaxDecompressor(); } } else if (compression == BaselineTIFFTagSet.COMPRESSION_CCITT_RLE) { this.decompressor = new TIFFFaxDecompressor(); } else if (compression == BaselineTIFFTagSet.COMPRESSION_PACKBITS) { if(DEBUG) { System.out.println("Using TIFFPackBitsDecompressor"); } this.decompressor = new TIFFPackBitsDecompressor(); } else if (compression == BaselineTIFFTagSet.COMPRESSION_LZW) { if(DEBUG) { System.out.println("Using TIFFLZWDecompressor"); } TIFFField predictorField = imageMetadata.getTIFFField(BaselineTIFFTagSet.TAG_PREDICTOR); int predictor = ((predictorField == null) ? BaselineTIFFTagSet.PREDICTOR_NONE : predictorField.getAsInt(0)); this.decompressor = new TIFFLZWDecompressor(predictor); } else if (compression == BaselineTIFFTagSet.COMPRESSION_JPEG) { this.decompressor = new TIFFJPEGDecompressor(); } else if (compression == BaselineTIFFTagSet.COMPRESSION_ZLIB || compression == BaselineTIFFTagSet.COMPRESSION_DEFLATE) { TIFFField predictorField = imageMetadata.getTIFFField(BaselineTIFFTagSet.TAG_PREDICTOR); int predictor = ((predictorField == null) ? BaselineTIFFTagSet.PREDICTOR_NONE : predictorField.getAsInt(0)); this.decompressor = new TIFFDeflateDecompressor(predictor); } else if (compression == BaselineTIFFTagSet.COMPRESSION_OLD_JPEG) { TIFFField JPEGProcField = imageMetadata.getTIFFField(BaselineTIFFTagSet.TAG_JPEG_PROC); if(JPEGProcField == null) { processWarningOccurred ("JPEGProc field missing; assuming baseline sequential JPEG process."); } else if(JPEGProcField.getAsInt(0) != BaselineTIFFTagSet.JPEG_PROC_BASELINE) { throw new IIOException ("Old-style JPEG supported for baseline sequential JPEG process only!"); } this.decompressor = new TIFFOldJPEGDecompressor(); //throw new IIOException("Old-style JPEG not supported!"); } else { throw new IIOException ("Unsupported compression type (tag number = "+ compression+")!"); } if (photometricInterpretation == BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_Y_CB_CR && compression != BaselineTIFFTagSet.COMPRESSION_JPEG && compression != BaselineTIFFTagSet.COMPRESSION_OLD_JPEG) { boolean convertYCbCrToRGB = theImage.getColorModel().getColorSpace().getType() == ColorSpace.TYPE_RGB; TIFFDecompressor wrappedDecompressor = this.decompressor instanceof TIFFNullDecompressor ? null : this.decompressor; this.decompressor = new TIFFYCbCrDecompressor(wrappedDecompressor, convertYCbCrToRGB); } } if(DEBUG) { System.out.println("\nDecompressor class = "+ decompressor.getClass().getName()+"\n"); } if (colorConverter == null) { if (photometricInterpretation == BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_CIELAB && theImage.getColorModel().getColorSpace().getType() == ColorSpace.TYPE_RGB) { colorConverter = new TIFFCIELabColorConverter(); } else if (photometricInterpretation == BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_Y_CB_CR && !(this.decompressor instanceof TIFFYCbCrDecompressor) && compression != BaselineTIFFTagSet.COMPRESSION_JPEG && compression != BaselineTIFFTagSet.COMPRESSION_OLD_JPEG) { colorConverter = new TIFFYCbCrColorConverter(imageMetadata); } } decompressor.setReader(this); decompressor.setMetadata(imageMetadata); decompressor.setImage(theImage); decompressor.setPhotometricInterpretation(photometricInterpretation); decompressor.setCompression(compression); decompressor.setSamplesPerPixel(samplesPerPixel); decompressor.setBitsPerSample(bitsPerSample); decompressor.setSampleFormat(sampleFormat); decompressor.setExtraSamples(extraSamples); decompressor.setColorMap(colorMap); decompressor.setColorConverter(colorConverter); decompressor.setSourceXOffset(sourceXOffset); decompressor.setSourceYOffset(sourceYOffset); decompressor.setSubsampleX(srcXSubsampling); decompressor.setSubsampleY(srcYSubsampling); decompressor.setDstXOffset(dstXOffset); decompressor.setDstYOffset(dstYOffset); decompressor.setSourceBands(sourceBands); decompressor.setDestinationBands(destinationBands); // Compute bounds on the tile indices for this source region. int minTileX = TIFFImageWriter.XToTileX(srcRegion.x, 0, tileOrStripWidth); int minTileY = TIFFImageWriter.YToTileY(srcRegion.y, 0, tileOrStripHeight); int maxTileX = TIFFImageWriter.XToTileX(srcRegion.x + srcRegion.width - 1, 0, tileOrStripWidth); int maxTileY = TIFFImageWriter.YToTileY(srcRegion.y + srcRegion.height - 1, 0, tileOrStripHeight); boolean isAbortRequested = false; if (planarConfiguration == BaselineTIFFTagSet.PLANAR_CONFIGURATION_PLANAR) { decompressor.setPlanar(true); int[] sb = new int[1]; int[] db = new int[1]; for (int tj = minTileY; tj <= maxTileY; tj++) { for (int ti = minTileX; ti <= maxTileX; ti++) { for (int band = 0; band < numBands; band++) { sb[0] = sourceBands[band]; decompressor.setSourceBands(sb); db[0] = destinationBands[band]; decompressor.setDestinationBands(db); //XXX decompressor.beginDecoding(); // The method abortRequested() is synchronized // so check it only once per loop just before // doing any actual decoding. if(abortRequested()) { isAbortRequested = true; break; } decodeTile(ti, tj, band); } if(isAbortRequested) break; reportProgress(); } if(isAbortRequested) break; } } else { //XXX decompressor.beginDecoding(); for (int tj = minTileY; tj <= maxTileY; tj++) { for (int ti = minTileX; ti <= maxTileX; ti++) { // The method abortRequested() is synchronized // so check it only once per loop just before // doing any actual decoding. if(abortRequested()) { isAbortRequested = true; break; } decodeTile(ti, tj, -1); reportProgress(); } if(isAbortRequested) break; } } if (isAbortRequested) { processReadAborted(); } else { processImageComplete(); } return theImage; } public void reset() { super.reset(); resetLocal(); } protected void resetLocal() { stream = null; gotHeader = false; imageReadParam = getDefaultReadParam(); streamMetadata = null; currIndex = -1; imageMetadata = null; imageStartPosition = new ArrayList(); numImages = -1; imageTypeMap = new HashMap(); width = -1; height = -1; numBands = -1; tileOrStripWidth = -1; tileOrStripHeight = -1; planarConfiguration = BaselineTIFFTagSet.PLANAR_CONFIGURATION_CHUNKY; rowsDone = 0; } /** * Package scope method to allow decompressors, for example, to * emit warning messages. */ void forwardWarningMessage(String warning) { processWarningOccurred(warning); } protected static BufferedImage getDestination(ImageReadParam param, Iterator imageTypes, int width, int height) throws IIOException { if (imageTypes == null || !imageTypes.hasNext()) { throw new IllegalArgumentException("imageTypes null or empty!"); } BufferedImage dest = null; ImageTypeSpecifier imageType = null; // If param is non-null, use it if (param != null) { // Try to get the image itself dest = param.getDestination(); if (dest != null) { return dest; } // No image, get the image type imageType = param.getDestinationType(); } // No info from param, use fallback image type if (imageType == null) { Object o = imageTypes.next(); if (!(o instanceof ImageTypeSpecifier)) { throw new IllegalArgumentException ("Non-ImageTypeSpecifier retrieved from imageTypes!"); } imageType = (ImageTypeSpecifier)o; } else { boolean foundIt = false; while (imageTypes.hasNext()) { ImageTypeSpecifier type = (ImageTypeSpecifier)imageTypes.next(); if (type.equals(imageType)) { foundIt = true; break; } } if (!foundIt) { throw new IIOException ("Destination type from ImageReadParam does not match!"); } } Rectangle srcRegion = new Rectangle(0,0,0,0); Rectangle destRegion = new Rectangle(0,0,0,0); computeRegions(param, width, height, null, srcRegion, destRegion); int destWidth = destRegion.x + destRegion.width; int destHeight = destRegion.y + destRegion.height; // Create a new image based on the type specifier if ((long)destWidth*destHeight > Integer.MAX_VALUE) { throw new IllegalArgumentException ("width*height > Integer.MAX_VALUE!"); } return imageType.createBufferedImage(destWidth, destHeight); } } ././@LongLink0000000000000000000000000000014600000000000011566 Lustar rootrootjai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/tiff/TIFFImageWriterSpi.javajai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/tiff/TIFFImageWriterSpi.jav0000664000175100017510000000764110413303155032433 0ustar tilletille/* * $RCSfile: TIFFImageWriterSpi.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.2 $ * $Date: 2006-03-31 19:43:41 $ * $State: Exp $ */ package com.sun.media.imageioimpl.plugins.tiff; import java.util.Locale; import javax.imageio.ImageTypeSpecifier; import javax.imageio.ImageWriter; import javax.imageio.spi.ImageWriterSpi; import javax.imageio.spi.ServiceRegistry; import com.sun.media.imageioimpl.common.PackageUtil; public class TIFFImageWriterSpi extends ImageWriterSpi { private static final String[] names = { "tif", "TIF", "tiff", "TIFF" }; private static final String[] suffixes = { "tif", "tiff" }; private static final String[] MIMETypes = { "image/tiff" }; private static final String writerClassName = "com.sun.media.imageioimpl.plugins.tiff.TIFFImageWriter"; private static final String[] readerSpiNames = { "com.sun.media.imageioimpl.plugins.tiff.TIFFImageReaderSpi" }; private boolean registered = false; public TIFFImageWriterSpi() { super(PackageUtil.getVendor(), PackageUtil.getVersion(), names, suffixes, MIMETypes, writerClassName, STANDARD_OUTPUT_TYPE, readerSpiNames, false, TIFFStreamMetadata.nativeMetadataFormatName, "com.sun.media.imageioimpl.plugins.tiff.TIFFStreamMetadataFormat", null, null, false, TIFFImageMetadata.nativeMetadataFormatName, "com.sun.media.imageioimpl.plugins.tiff.TIFFImageMetadataFormat", null, null ); } public boolean canEncodeImage(ImageTypeSpecifier type) { return true; } public String getDescription(Locale locale) { String desc = PackageUtil.getSpecificationTitle() + " TIFF Image Writer"; return desc; } public ImageWriter createWriterInstance(Object extension) { return new TIFFImageWriter(this); } public void onRegistration(ServiceRegistry registry, Class category) { if (registered) { return; } registered = true; } } jai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/tiff/TIFFElementInfo.java0000664000175100017510000000536210203036165032105 0ustar tilletille/* * $RCSfile: TIFFElementInfo.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.1 $ * $Date: 2005-02-11 05:01:45 $ * $State: Exp $ */ package com.sun.media.imageioimpl.plugins.tiff; import javax.imageio.metadata.IIOMetadataFormat; public class TIFFElementInfo { String[] childNames; String[] attributeNames; int childPolicy; int minChildren = 0; int maxChildren = Integer.MAX_VALUE; int objectValueType = IIOMetadataFormat.VALUE_NONE; Class objectClass = null; Object objectDefaultValue = null; Object[] objectEnumerations = null; Comparable objectMinValue = null; Comparable objectMaxValue = null; int objectArrayMinLength = 0; int objectArrayMaxLength = 0; public TIFFElementInfo(String[] childNames, String[] attributeNames, int childPolicy) { this.childNames = childNames; this.attributeNames = attributeNames; this.childPolicy = childPolicy; } } ././@LongLink0000000000000000000000000000014700000000000011567 Lustar rootrootjai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/tiff/TIFFLSBDecompressor.javajai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/tiff/TIFFLSBDecompressor.ja0000664000175100017510000000632010203036165032352 0ustar tilletille/* * $RCSfile: TIFFLSBDecompressor.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.1 $ * $Date: 2005-02-11 05:01:48 $ * $State: Exp $ */ package com.sun.media.imageioimpl.plugins.tiff; import java.io.IOException; import com.sun.media.imageio.plugins.tiff.TIFFDecompressor; public class TIFFLSBDecompressor extends TIFFDecompressor { /** * Table for flipping bytes from LSB-to-MSB to MSB-to-LSB. */ private static byte[] flipTable = TIFFFaxDecompressor.flipTable; public TIFFLSBDecompressor() {} public void decodeRaw(byte[] b, int dstOffset, int bitsPerPixel, int scanlineStride) throws IOException { stream.seek(offset); int bytesPerRow = (srcWidth*bitsPerPixel + 7)/8; if(bytesPerRow == scanlineStride) { int numBytes = bytesPerRow*srcHeight; stream.readFully(b, dstOffset, numBytes); int xMax = dstOffset + numBytes; for (int x = dstOffset; x < xMax; x++) { b[x] = flipTable[b[x]&0xff]; } } else { for (int y = 0; y < srcHeight; y++) { stream.readFully(b, dstOffset, bytesPerRow); int xMax = dstOffset + bytesPerRow; for (int x = dstOffset; x < xMax; x++) { b[x] = flipTable[b[x]&0xff]; } dstOffset += scanlineStride; } } } } ././@LongLink0000000000000000000000000000015700000000000011570 Lustar rootrootjai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/tiff/TIFFCodecLibFaxDecompressor.javajai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/tiff/TIFFCodecLibFaxDecompr0000664000175100017510000001763410203036165032402 0ustar tilletille/* * $RCSfile: TIFFCodecLibFaxDecompressor.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.1 $ * $Date: 2005-02-11 05:01:44 $ * $State: Exp $ */ package com.sun.media.imageioimpl.plugins.tiff; import java.io.IOException; import com.sun.media.imageio.plugins.tiff.BaselineTIFFTagSet; import com.sun.media.imageio.plugins.tiff.TIFFDecompressor; public class TIFFCodecLibFaxDecompressor extends TIFFFaxDecompressor { private static final boolean DEBUG = false; // XXX 'false' for release!!! /** * com.sun.medialib.codec.g3fax.Decoder for T.4 or * com.sun.medialib.codec.g4fax.Decoder for T.6. */ private Object decoder = null; /** * Constructor which initializes the internal codecLib decoder. * * @throws RuntimeException if bilevelCompression is * not T.4 or T.6 compression or if codecLib is not available. */ public TIFFCodecLibFaxDecompressor(int bilevelCompression) { super(); try { // 'compression' is set in the superclass method. if(bilevelCompression == BaselineTIFFTagSet.COMPRESSION_CCITT_T_4) { com.sun.medialib.codec.g3fax.Decoder decoder = new com.sun.medialib.codec.g3fax.Decoder(); this.decoder = decoder; } else if(bilevelCompression == BaselineTIFFTagSet.COMPRESSION_CCITT_T_6) { com.sun.medialib.codec.g4fax.Decoder decoder = new com.sun.medialib.codec.g4fax.Decoder(); this.decoder = decoder; } else { throw new RuntimeException("Unknown compression = "+ bilevelCompression); } } catch (Throwable e) { throw new RuntimeException("CodecLib not available"); } } public synchronized final void decodeRaw(byte[] b, int dstOffset, int pixelBitStride, // always 1 int scanlineStride) throws IOException { int bytesPerRow = (srcWidth + 7)/8; byte[] image = null; byte[] code = new byte[byteCount]; stream.seek(offset); stream.readFully(code, 0, byteCount); // Flip the bytes if fill order is LSB-to-MSB. if(fillOrder == 2) { for(int i = 0; i < byteCount; i++) { code[i] = flipTable[code[i]&0xff]; } } if (dstOffset == 0 && bytesPerRow == scanlineStride) { image = b; } else { image = new byte[srcWidth*srcHeight]; } if (compression == BaselineTIFFTagSet.COMPRESSION_CCITT_T_6) { com.sun.medialib.codec.g4fax.Decoder decoder = (com.sun.medialib.codec.g4fax.Decoder)this.decoder; if(DEBUG) { System.out.println("Using MediaLib G4 decoder"); } int result = com.sun.medialib.codec.g4fax.Constants.G4FAX_FAILURE; try { result = decoder.decode(image, code, srcWidth, srcHeight, 0); } catch(Throwable t) { ((TIFFImageReader)reader).forwardWarningMessage ("codecLib T.6 decompressor failed; falling back to Java."); result = com.sun.medialib.codec.g4fax.Constants.G4FAX_FAILURE; } if(result == com.sun.medialib.codec.g4fax.Constants.G4FAX_FAILURE) { // Fall back to Java decoder. if(DEBUG) { System.out.println("Falling back to Java G4 decoder"); } super.decodeRaw(b, dstOffset, pixelBitStride, scanlineStride); return; } } else { com.sun.medialib.codec.g3fax.Decoder decoder = (com.sun.medialib.codec.g3fax.Decoder)this.decoder; if(DEBUG) { System.out.println("Using MediaLib G3 decoder"); } int decodingFlags = 0; if(oneD == 1) { decodingFlags = decoder.G3FAX_VERTICAL_CODING | decoder.G3FAX_NORTC; if(DEBUG) { System.out.print("G3FAX_VERTICAL_CODING"+ " | G3FAX_NORTC"); } } else { decodingFlags = decoder.G3FAX_HORIZONTAL_CODING | decoder.G3FAX_NORTC; if(DEBUG) { System.out.print("G3FAX_HORIZONTAL_CODING"+ " | G3FAX_NORTC"); } } if(fillBits == 1) { if(DEBUG) { System.out.print(" | G3FAX_EOLPADDING_CODING"); } decodingFlags |= decoder.G3FAX_EOLPADDING; } if(DEBUG) { System.out.println(""); } int result = com.sun.medialib.codec.g3fax.Constants.G3FAX_FAILURE; try { result = decoder.decode(image, code, srcWidth, srcHeight, decodingFlags); } catch(Throwable t) { ((TIFFImageReader)reader).forwardWarningMessage ("codecLib T.4 decompressor failed; falling back to Java."); result = com.sun.medialib.codec.g3fax.Constants.G3FAX_FAILURE; } if(result == com.sun.medialib.codec.g3fax.Constants.G3FAX_FAILURE) { // Fall back to Java decoder. if(DEBUG) { System.out.println("Falling back to Java G3 decoder"); } super.decodeRaw(b, dstOffset, pixelBitStride, scanlineStride); return; } } if (image != b) { int srcOffset = 0; for (int row = 0; row < srcHeight; row++) { System.arraycopy(image, srcOffset, b, dstOffset, bytesPerRow); srcOffset += bytesPerRow; dstOffset += scanlineStride; } } } } ././@LongLink0000000000000000000000000000015000000000000011561 Lustar rootrootjai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/tiff/TIFFNullDecompressor.javajai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/tiff/TIFFNullDecompressor.j0000664000175100017510000002043710203036165032510 0ustar tilletille/* * $RCSfile: TIFFNullDecompressor.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.1 $ * $Date: 2005-02-11 05:01:48 $ * $State: Exp $ */ package com.sun.media.imageioimpl.plugins.tiff; import java.io.IOException; import com.sun.media.imageio.plugins.tiff.TIFFDecompressor; public class TIFFNullDecompressor extends TIFFDecompressor { private static final boolean DEBUG = false; // XXX false for release! /** * Whether to read the active source region only. */ private boolean isReadActiveOnly = false; /** The original value of srcMinX. */ private int originalSrcMinX; /** The original value of srcMinY. */ private int originalSrcMinY; /** The original value of srcWidth. */ private int originalSrcWidth; /** The original value of srcHeight. */ private int originalSrcHeight; public TIFFNullDecompressor() {} // // This approach to reading the active reading is a hack of sorts // as the original values of the entire source region are stored, // overwritten, and then restored. It would probably be better to // revise TIFFDecompressor such that this were not necessary, i.e., // change beginDecoding() and decode() to use the active region values // when random access is easy and the entire region values otherwise. // public void beginDecoding() { // Determine number of bits per pixel. int bitsPerPixel = 0; for(int i = 0; i < bitsPerSample.length; i++) { bitsPerPixel += bitsPerSample[i]; } // Can read active region only if row starts on a byte boundary. if((activeSrcMinX != srcMinX || activeSrcMinY != srcMinY || activeSrcWidth != srcWidth || activeSrcHeight != srcHeight) && ((activeSrcMinX - srcMinX)*bitsPerPixel) % 8 == 0) { // Set flag. isReadActiveOnly = true; // Cache original region. originalSrcMinX = srcMinX; originalSrcMinY = srcMinY; originalSrcWidth = srcWidth; originalSrcHeight = srcHeight; // Replace region with active region. srcMinX = activeSrcMinX; srcMinY = activeSrcMinY; srcWidth = activeSrcWidth; srcHeight = activeSrcHeight; } else { // Clear flag. isReadActiveOnly = false; } if(DEBUG) { if(isReadActiveOnly) { System.out.println("Reading active region."); System.out.println("source region: "+ new java.awt.Rectangle(originalSrcMinX, originalSrcMinY, originalSrcWidth, originalSrcHeight)); System.out.println("active region: "+ new java.awt.Rectangle(activeSrcMinX, activeSrcMinY, activeSrcWidth, activeSrcHeight)); } else { System.out.println("Reading entire region."); System.out.println("source region: "+ new java.awt.Rectangle(srcMinX, srcMinY, srcWidth, srcHeight)); } System.out.println("destination region: "+ new java.awt.Rectangle(dstMinX, dstMinY, dstWidth, dstHeight)); } super.beginDecoding(); } public void decode() throws IOException { super.decode(); // Reset state. if(isReadActiveOnly) { // Restore original source region values. srcMinX = originalSrcMinX; srcMinY = originalSrcMinY; srcWidth = originalSrcWidth; srcHeight = originalSrcHeight; // Unset flag. isReadActiveOnly = false; } } public void decodeRaw(byte[] b, int dstOffset, int bitsPerPixel, int scanlineStride) throws IOException { if(isReadActiveOnly) { // Read the active source region only. int activeBytesPerRow = (activeSrcWidth*bitsPerPixel + 7)/8; int totalBytesPerRow = (originalSrcWidth*bitsPerPixel + 7)/8; int bytesToSkipPerRow = totalBytesPerRow - activeBytesPerRow; // // Seek to the start of the active region: // // active offset = original offset + // number of bytes to start of first active row + // number of bytes to first active pixel within row // // Since the condition for reading from the active region only is // // ((activeSrcMinX - srcMinX)*bitsPerPixel) % 8 == 0 // // the bit offset to the first active pixel within the first // active row is a multiple of 8. // stream.seek(offset + (activeSrcMinY - originalSrcMinY)*totalBytesPerRow + ((activeSrcMinX - originalSrcMinX)*bitsPerPixel)/8); int lastRow = activeSrcHeight - 1; for (int y = 0; y < activeSrcHeight; y++) { stream.read(b, dstOffset, activeBytesPerRow); dstOffset += scanlineStride; // Skip unneeded bytes (row suffix + row prefix). if(y != lastRow) { stream.skipBytes(bytesToSkipPerRow); } } } else { // Read the entire source region. stream.seek(offset); int bytesPerRow = (srcWidth*bitsPerPixel + 7)/8; if(bytesPerRow == scanlineStride) { stream.read(b, dstOffset, bytesPerRow*srcHeight); } else { for (int y = 0; y < srcHeight; y++) { stream.read(b, dstOffset, bytesPerRow); dstOffset += scanlineStride; } } } } } jai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/tiff/TIFFT6Compressor.java0000664000175100017510000001721310417024535032251 0ustar tilletille/* * $RCSfile: TIFFT6Compressor.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.3 $ * $Date: 2006-04-11 22:10:37 $ * $State: Exp $ */ package com.sun.media.imageioimpl.plugins.tiff; import com.sun.media.imageio.plugins.tiff.BaselineTIFFTagSet; import com.sun.media.imageio.plugins.tiff.TIFFCompressor; import com.sun.media.imageio.plugins.tiff.TIFFField; import com.sun.media.imageio.plugins.tiff.TIFFTag; import java.io.IOException; import javax.imageio.IIOException; /** * */ public class TIFFT6Compressor extends TIFFFaxCompressor { public TIFFT6Compressor() { super("CCITT T.6", BaselineTIFFTagSet.COMPRESSION_CCITT_T_6, true); } /** * Encode a buffer of data using CCITT T.6 Compression also known as * Group 4 facsimile compression. * * @param data The row of data to compress. * @param lineStride Byte step between the same sample in different rows. * @param colOffset Bit offset within first data[rowOffset]. * @param width Number of bits in the row. * @param height Number of rows in the buffer. * @param compData The compressed data. * * @return The number of bytes saved in the compressed data array. */ public synchronized int encodeT6(byte[] data, int lineStride, int colOffset, int width, int height, byte[] compData) { // // ao, a1, a2 are bit indices in the current line // b1 and b2 are bit indices in the reference line (line above) // color is the current color (WHITE or BLACK) // byte[] refData = null; int refAddr = 0; int lineAddr = 0; int outIndex = 0; initBitBuf(); // // Iterate over all lines // while(height-- != 0) { int a0 = colOffset; int last = a0 + width; int testbit = ((data[lineAddr + (a0>>>3)]&0xff) >>> (7-(a0 & 0x7))) & 0x1; int a1 = testbit != 0 ? a0 : nextState(data, lineAddr, a0, last); testbit = refData == null ? 0: ((refData[refAddr + (a0>>>3)]&0xff) >>> (7-(a0 & 0x7))) & 0x1; int b1 = testbit != 0 ? a0 : nextState(refData, refAddr, a0, last); // // The current color is set to WHITE at line start // int color = WHITE; while(true) { int b2 = nextState(refData, refAddr, b1, last); if(b2 < a1) { // pass mode outIndex += add2DBits(compData, outIndex, pass, 0); a0 = b2; } else { int tmp = b1 - a1 + 3; if((tmp <= 6) && (tmp >= 0)) { // vertical mode outIndex += add2DBits(compData, outIndex, vert, tmp); a0 = a1; } else { // horizontal mode int a2 = nextState(data, lineAddr, a1, last); outIndex += add2DBits(compData, outIndex, horz, 0); outIndex += add1DBits(compData, outIndex, a1-a0, color); outIndex += add1DBits(compData, outIndex, a2-a1, color^1); a0 = a2; } } if(a0 >= last) { break; } color = ((data[lineAddr + (a0>>>3)]&0xff) >>> (7-(a0 & 0x7))) & 0x1; a1 = nextState(data, lineAddr, a0, last); b1 = nextState(refData, refAddr, a0, last); testbit = refData == null ? 0: ((refData[refAddr + (b1>>>3)]&0xff) >>> (7-(b1 & 0x7))) & 0x1; if(testbit == color) { b1 = nextState(refData, refAddr, b1, last); } } refData = data; refAddr = lineAddr; lineAddr += lineStride; } // End while(height--) // // append eofb // outIndex += addEOFB(compData, outIndex); // Flip the bytes if inverse fill was requested. if(inverseFill) { for(int i = 0; i < outIndex; i++) { compData[i] = TIFFFaxDecompressor.flipTable[compData[i]&0xff]; } } return outIndex; } public int encode(byte[] b, int off, int width, int height, int[] bitsPerSample, int scanlineStride) throws IOException { if (bitsPerSample.length != 1 || bitsPerSample[0] != 1) { throw new IIOException( "Bits per sample must be 1 for T6 compression!"); } if (metadata instanceof TIFFImageMetadata) { TIFFImageMetadata tim = (TIFFImageMetadata)metadata; long[] options = new long[1]; options[0] = 0; BaselineTIFFTagSet base = BaselineTIFFTagSet.getInstance(); TIFFField T6Options = new TIFFField(base.getTag(BaselineTIFFTagSet.TAG_T6_OPTIONS), TIFFTag.TIFF_LONG, 1, options); tim.rootIFD.addTIFFField(T6Options); } // See comment in TIFFT4Compressor int maxBits = 9*((width + 1)/2) + 2; int bufSize = (maxBits + 7)/8; bufSize = height*(bufSize + 2) + 12; byte[] compData = new byte[bufSize]; int bytes = encodeT6(b, scanlineStride, 8*off, width, height, compData); stream.write(compData, 0, bytes); return bytes; } } ././@LongLink0000000000000000000000000000015400000000000011565 Lustar rootrootjai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/tiff/TIFFPackBitsDecompressor.javajai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/tiff/TIFFPackBitsDecompress0000664000175100017510000001153710203036165032506 0ustar tilletille/* * $RCSfile: TIFFPackBitsDecompressor.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.1 $ * $Date: 2005-02-11 05:01:49 $ * $State: Exp $ */ package com.sun.media.imageioimpl.plugins.tiff; import java.awt.Rectangle; import java.io.IOException; import javax.imageio.ImageReader; import com.sun.media.imageio.plugins.tiff.BaselineTIFFTagSet; import com.sun.media.imageio.plugins.tiff.TIFFDecompressor; import com.sun.media.imageio.plugins.tiff.TIFFTag; public class TIFFPackBitsDecompressor extends TIFFDecompressor { private static final boolean DEBUG = false; public TIFFPackBitsDecompressor() { } public int decode(byte[] srcData, int srcOffset, byte[] dstData, int dstOffset) throws IOException { int srcIndex = srcOffset; int dstIndex = dstOffset; int dstArraySize = dstData.length; int srcArraySize = srcData.length; try { while (dstIndex < dstArraySize && srcIndex < srcArraySize) { byte b = srcData[srcIndex++]; if (b >= 0 && b <= 127) { // second test not needed? // Literal run packet for (int i = 0; i < b + 1; i++) { dstData[dstIndex++] = srcData[srcIndex++]; } } else if (b <= -1 && b >= -127) { // 2-byte encoded run packet byte repeat = srcData[srcIndex++]; for (int i = 0; i < (-b + 1); i++) { dstData[dstIndex++] = repeat; } } else { // No-op packet, do nothing ++srcIndex; } } } catch(ArrayIndexOutOfBoundsException e) { if(reader instanceof TIFFImageReader) { ((TIFFImageReader)reader).forwardWarningMessage ("ArrayIndexOutOfBoundsException ignored in TIFFPackBitsDecompressor.decode()"); } } return dstIndex - dstOffset; } public void decodeRaw(byte[] b, int dstOffset, int bitsPerPixel, int scanlineStride) throws IOException { stream.seek(offset); byte[] srcData = new byte[byteCount]; stream.readFully(srcData); int bytesPerRow = (srcWidth*bitsPerPixel + 7)/8; byte[] buf; int bufOffset; if(bytesPerRow == scanlineStride) { buf = b; bufOffset = dstOffset; } else { buf = new byte[bytesPerRow*srcHeight]; bufOffset = 0; } decode(srcData, 0, buf, bufOffset); if(bytesPerRow != scanlineStride) { if(DEBUG) { System.out.println("bytesPerRow != scanlineStride"); } int off = 0; for (int y = 0; y < srcHeight; y++) { System.arraycopy(buf, off, b, dstOffset, bytesPerRow); off += bytesPerRow; dstOffset += scanlineStride; } } } } ././@LongLink0000000000000000000000000000016500000000000011567 Lustar rootrootjai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/tiff/TIFFStreamMetadataFormatResources.javajai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/tiff/TIFFStreamMetadataForm0000664000175100017510000000456610203036165032505 0ustar tilletille/* * $RCSfile: TIFFStreamMetadataFormatResources.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.1 $ * $Date: 2005-02-11 05:01:50 $ * $State: Exp $ */ package com.sun.media.imageioimpl.plugins.tiff; import java.util.ListResourceBundle; public class TIFFStreamMetadataFormatResources extends ListResourceBundle { private static final Object[][] contents = { { "ByteOrder", "The stream byte order" }, { "ByteOrder/value", "One of \"BIG_ENDIAN\" or \"LITTLE_ENDIAN\"" } }; public TIFFStreamMetadataFormatResources() { } public Object[][] getContents() { return contents; } } ././@LongLink0000000000000000000000000000015400000000000011565 Lustar rootrootjai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/tiff/TIFFCIELabColorConverter.javajai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/tiff/TIFFCIELabColorConvert0000664000175100017510000001235610203036165032340 0ustar tilletille/* * $RCSfile: TIFFCIELabColorConverter.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.1 $ * $Date: 2005-02-11 05:01:44 $ * $State: Exp $ */ package com.sun.media.imageioimpl.plugins.tiff; import com.sun.media.imageio.plugins.tiff.TIFFColorConverter; /** */ public class TIFFCIELabColorConverter extends TIFFColorConverter { // XYX coordinate or reference white (CIE D65) private static final float Xn = 95.047f; private static final float Yn = 100.0f; private static final float Zn = 108.883f; private static final float THRESHOLD = (float)Math.pow(0.008856, 1.0/3.0); public TIFFCIELabColorConverter() {} private float clamp(float x) { if (x < 0.0f) { return 0.0f; } else if (x > 100.0f) { return 255.0f; } else { return x*(255.0f/100.0f); } } private float clamp2(float x) { if (x < 0.0f) { return 0.0f; } else if (x > 255.0f) { return 255.0f; } else { return x; } } public void fromRGB(float r, float g, float b, float[] result) { float X = 0.412453f*r + 0.357580f*g + 0.180423f*b; float Y = 0.212671f*r + 0.715160f*g + 0.072169f*b; float Z = 0.019334f*r + 0.119193f*g + 0.950227f*b; float YYn = Y/Yn; float XXn = X/Xn; float ZZn = Z/Zn; if (YYn < 0.008856f) { YYn = 7.787f*YYn + 16.0f/116.0f; } else { YYn = (float)Math.pow(YYn, 1.0/3.0); } if (XXn < 0.008856f) { XXn = 7.787f*XXn + 16.0f/116.0f; } else { XXn = (float)Math.pow(XXn, 1.0/3.0); } if (ZZn < 0.008856f) { ZZn = 7.787f*ZZn + 16.0f/116.0f; } else { ZZn = (float)Math.pow(ZZn, 1.0/3.0); } float LStar = 116.0f*YYn - 16.0f; float aStar = 500.0f*(XXn - YYn); float bStar = 200.0f*(YYn - ZZn); LStar *= 255.0f/100.0f; if (aStar < 0.0f) { aStar += 256.0f; } if (bStar < 0.0f) { bStar += 256.0f; } result[0] = clamp2(LStar); result[1] = clamp2(aStar); result[2] = clamp2(bStar); } public void toRGB(float x0, float x1, float x2, float[] rgb) { float LStar = x0*100.0f/255.0f; float aStar = (x1 > 128.0f) ? (x1 - 256.0f) : x1; float bStar = (x2 > 128.0f) ? (x2 - 256.0f) : x2; float YYn; // Y/Yn float fY; // 'F' value for Y if (LStar < 8.0f) { YYn = LStar/903.3f; fY = 7.787f*YYn + 16.0f/116.0f; } else { float YYn_cubeRoot = (LStar + 16.0f)/116.0f; YYn = YYn_cubeRoot*YYn_cubeRoot*YYn_cubeRoot; fY = (float)Math.pow(YYn, 1.0/3.0); } float Y = YYn*Yn; float fX = fY + (aStar/500.0f); float X; if (fX <= THRESHOLD) { X = Xn*(fX - 16.0f/116.0f)/7.787f; } else { X = Xn*fX*fX*fX; } float fZ = fY - bStar/200.0f; float Z; if (fZ <= THRESHOLD) { Z = Zn*(fZ - 16.0f/116.0f)/7.787f; } else { Z = Zn*fZ*fZ*fZ; } float R = 3.240479f*X - 1.537150f*Y - 0.498535f*Z; float G = -0.969256f*X + 1.875992f*Y + 0.041556f*Z; float B = 0.055648f*X - 0.204043f*Y + 1.057311f*Z; rgb[0] = clamp(R); rgb[1] = clamp(G); rgb[2] = clamp(B); } } ././@LongLink0000000000000000000000000000015400000000000011565 Lustar rootrootjai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/tiff/TIFFCodecLibT4Compressor.javajai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/tiff/TIFFCodecLibT4Compress0000664000175100017510000001440710367517633032367 0ustar tilletille/* * $RCSfile: TIFFCodecLibT4Compressor.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.2 $ * $Date: 2006-01-30 23:22:03 $ * $State: Exp $ */ package com.sun.media.imageioimpl.plugins.tiff; public class TIFFCodecLibT4Compressor extends TIFFT4Compressor { private static final boolean DEBUG = false; // XXX 'false' for release!!! Object encoder; public TIFFCodecLibT4Compressor() { super(); try { com.sun.medialib.codec.g3fax.Encoder encoder = new com.sun.medialib.codec.g3fax.Encoder(); this.encoder = encoder; } catch(Throwable t) { throw new RuntimeException("CodecLib not available"); } } /** * Encode a buffer of data using CCITT T.4 Compression also known as * Group 3 facsimile compression. * * @param is1DMode Whether to perform one-dimensional encoding. * @param isEOLAligned Whether EOL bit sequences should be padded. * @param data The row of data to compress. * @param lineStride Byte step between the same sample in different rows. * @param colOffset Bit offset within first data[rowOffset]. * @param width Number of bits in the row. * @param height Number of rows in the buffer. * @param compData The compressed data. * * @return The number of bytes saved in the compressed data array. */ public final int encodeT4(boolean is1DMode, boolean isEOLAligned, byte[] data, int lineStride, int colOffset, int width, int height, byte[] compData) { // Defer to superclass if bit offset is not byte-aligned. if(colOffset % 8 != 0) { return super.encodeT4(is1DMode, isEOLAligned, data, lineStride, colOffset, width, height, compData); } // Set image to data if possible; otherwise copy. int bytesPerRow = (width + 7)/8; byte[] image = null; if(colOffset == 0 && bytesPerRow == lineStride) { image = data; } else { image = new byte[bytesPerRow*height]; int dataOffset = colOffset / 8; int imageOffset = 0; for(int row = 0; row < height; row++) { System.arraycopy(data, dataOffset, image, imageOffset, bytesPerRow); dataOffset += lineStride; imageOffset += bytesPerRow; } } // Attempt the codecLib encoder. com.sun.medialib.codec.g3fax.Encoder clibEncoder = (com.sun.medialib.codec.g3fax.Encoder)encoder; //System.out.println("Using codecLib G3 encoder"); // Set encoding flags. int encodingFlags = is1DMode ? com.sun.medialib.codec.g3fax.Constants.G3FAX_HORIZONTAL_CODING : com.sun.medialib.codec.g3fax.Constants.G3FAX_VERTICAL_CODING; if(isEOLAligned) { encodingFlags |= com.sun.medialib.codec.g3fax.Constants.G3FAX_EOLPADDING; } if(inverseFill) { encodingFlags |= com.sun.medialib.codec.g3fax.Constants.G3FAX_LSB2MSB; } int result = com.sun.medialib.codec.g3fax.Constants.G3FAX_FAILURE; try { if(DEBUG) { System.out.println("Using MediaLib G3 encoder"); } result = clibEncoder.encode(compData, image, width, height, 2, // k parameter encodingFlags); } catch(Throwable t) { if(DEBUG) { System.out.println("MediaLib G3 encoder failed: "+t); } // XXX Should write a warning to listeners here. result = com.sun.medialib.codec.g3fax.Constants.G3FAX_FAILURE; } // If the codecLib encoder failed, try the superclass. if(result == com.sun.medialib.codec.g3fax.Constants.G3FAX_FAILURE) { if(DEBUG) { System.out.println("Falling back to Java G3 encoder"); } result = super.encodeT4(is1DMode, isEOLAligned, data, lineStride, colOffset, width, height, compData); } return result; } } ././@LongLink0000000000000000000000000000015200000000000011563 Lustar rootrootjai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/tiff/TIFFEXIFJPEGCompressor.javajai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/tiff/TIFFEXIFJPEGCompressor0000664000175100017510000000657610417024535032253 0ustar tilletille/* * $RCSfile: TIFFEXIFJPEGCompressor.java,v $ * * * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.2 $ * $Date: 2006-04-11 22:10:35 $ * $State: Exp $ */ package com.sun.media.imageioimpl.plugins.tiff; import java.awt.image.BufferedImage; import java.io.ByteArrayOutputStream; import java.io.IOException; import javax.imageio.IIOException; import javax.imageio.IIOImage; import javax.imageio.ImageIO; import javax.imageio.ImageWriteParam; import javax.imageio.ImageWriter; import javax.imageio.metadata.IIOMetadata; import javax.imageio.stream.MemoryCacheImageOutputStream; import com.sun.media.imageio.plugins.tiff.BaselineTIFFTagSet; import com.sun.media.imageio.plugins.tiff.EXIFParentTIFFTagSet; import com.sun.media.imageio.plugins.tiff.EXIFTIFFTagSet; import com.sun.media.imageio.plugins.tiff.TIFFCompressor; import com.sun.media.imageio.plugins.tiff.TIFFField; import com.sun.media.imageio.plugins.tiff.TIFFTag; import com.sun.media.imageio.plugins.tiff.TIFFTagSet; /** * A TIFFCompressor for the JPEG variant of EXIF. */ public class TIFFEXIFJPEGCompressor extends TIFFBaseJPEGCompressor { public TIFFEXIFJPEGCompressor(ImageWriteParam param) { super(TIFFImageWriter.EXIF_JPEG_COMPRESSION_TYPE, BaselineTIFFTagSet.COMPRESSION_OLD_JPEG, false, param); } public void setMetadata(IIOMetadata metadata) { // Set the metadata. super.setMetadata(metadata); // Initialize the JPEG writer and writeparam. initJPEGWriter(false, // No stream metadata (not writing abbreviated) true); // Yes image metadata (remove APPn markers) } } jai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/tiff/TIFFFieldNode.java0000664000175100017510000002053110421250106031517 0ustar tilletille/* * $RCSfile: TIFFFieldNode.java,v $ * * * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.2 $ * $Date: 2006-04-18 20:47:02 $ * $State: Exp $ */ package com.sun.media.imageioimpl.plugins.tiff; import java.io.IOException; import java.io.Serializable; import java.util.Arrays; import java.util.List; import javax.imageio.metadata.IIOMetadata; import javax.imageio.metadata.IIOMetadataNode; import javax.imageio.stream.ImageOutputStream; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import com.sun.media.imageio.plugins.tiff.TIFFDirectory; import com.sun.media.imageio.plugins.tiff.TIFFField; import com.sun.media.imageio.plugins.tiff.TIFFTag; import com.sun.media.imageio.plugins.tiff.TIFFTagSet; import com.sun.media.imageioimpl.plugins.tiff.TIFFIFD; import com.sun.media.imageioimpl.plugins.tiff.TIFFImageMetadata; /** * The Node representation of a TIFFField * wherein the child node is procedural rather than buffered. * * @since 1.1-beta */ public class TIFFFieldNode extends IIOMetadataNode { private static String getNodeName(TIFFField f) { return f.getData() instanceof TIFFDirectory ? "TIFFIFD" : "TIFFField"; } private boolean isIFD; /** Initialization flag. */ private Boolean isInitialized = Boolean.FALSE; private TIFFField field; // XXX Set the user object to "field"? public TIFFFieldNode(TIFFField field) { super(getNodeName(field)); isIFD = field.getData() instanceof TIFFDirectory; this.field = field; TIFFTag tag = field.getTag(); int tagNumber = tag.getNumber(); String tagName = tag.getName(); if(isIFD) { if(tagNumber != 0) { setAttribute("parentTagNumber", Integer.toString(tagNumber)); } if(tagName != null) { setAttribute("parentTagName", tagName); } TIFFDirectory dir = (TIFFDirectory)field.getData(); TIFFTagSet[] tagSets = dir.getTagSets(); if(tagSets != null) { String tagSetNames = ""; for(int i = 0; i < tagSets.length; i++) { tagSetNames += tagSets[i].getClass().getName(); if(i != tagSets.length - 1) { tagSetNames += ","; } } setAttribute("tagSets", tagSetNames); } } else { setAttribute("number", Integer.toString(tagNumber)); setAttribute("name", tagName); } } private synchronized void initialize() { if(isInitialized == Boolean.TRUE) return; if(isIFD) { TIFFDirectory dir = (TIFFDirectory)field.getData(); TIFFField[] fields = dir.getTIFFFields(); if(fields != null) { TIFFTagSet[] tagSets = dir.getTagSets(); List tagSetList = Arrays.asList(tagSets); int numFields = fields.length; for(int i = 0; i < numFields; i++) { TIFFField f = fields[i]; int tagNumber = f.getTagNumber(); TIFFTag tag = TIFFIFD.getTag(tagNumber, tagSetList); Node node = f.getAsNativeNode(); if (node != null) { appendChild(node); } } } } else { IIOMetadataNode child; int count = field.getCount(); if (field.getType() == TIFFTag.TIFF_UNDEFINED) { child = new IIOMetadataNode("TIFFUndefined"); byte[] data = field.getAsBytes(); StringBuffer sb = new StringBuffer(); for (int i = 0; i < count; i++) { sb.append(Integer.toString(data[i] & 0xff)); if (i < count - 1) { sb.append(","); } } child.setAttribute("value", sb.toString()); } else { child = new IIOMetadataNode("TIFF" + field.getTypeName(field.getType()) + "s"); TIFFTag tag = field.getTag(); for (int i = 0; i < count; i++) { IIOMetadataNode cchild = new IIOMetadataNode("TIFF" + field.getTypeName(field.getType())); cchild.setAttribute("value", field.getValueAsString(i)); if (tag.hasValueNames() && field.isIntegral()) { int value = field.getAsInt(i); String name = tag.getValueName(value); if (name != null) { cchild.setAttribute("description", name); } } child.appendChild(cchild); } } appendChild(child); } isInitialized = Boolean.TRUE; } // Need to override this method to avoid a stack overflow exception // which will occur if super.appendChild is called from initialize(). public Node appendChild(Node newChild) { if (newChild == null) { throw new IllegalArgumentException("newChild == null!"); } return super.insertBefore(newChild, null); } // Override all methods which refer to child nodes. public boolean hasChildNodes() { initialize(); return super.hasChildNodes(); } public int getLength() { initialize(); return super.getLength(); } public Node getFirstChild() { initialize(); return super.getFirstChild(); } public Node getLastChild() { initialize(); return super.getLastChild(); } public Node getPreviousSibling() { initialize(); return super.getPreviousSibling(); } public Node getNextSibling() { initialize(); return super.getNextSibling(); } public Node insertBefore(Node newChild, Node refChild) { initialize(); return super.insertBefore(newChild, refChild); } public Node replaceChild(Node newChild, Node oldChild) { initialize(); return super.replaceChild(newChild, oldChild); } public Node removeChild(Node oldChild) { initialize(); return super.removeChild(oldChild); } public Node cloneNode(boolean deep) { initialize(); return super.cloneNode(deep); } } ././@LongLink0000000000000000000000000000014600000000000011566 Lustar rootrootjai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/tiff/TIFFNullCompressor.javajai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/tiff/TIFFNullCompressor.jav0000664000175100017510000000574310203036165032531 0ustar tilletille/* * $RCSfile: TIFFNullCompressor.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.1 $ * $Date: 2005-02-11 05:01:48 $ * $State: Exp $ */ package com.sun.media.imageioimpl.plugins.tiff; import com.sun.media.imageio.plugins.tiff.BaselineTIFFTagSet; import com.sun.media.imageio.plugins.tiff.TIFFCompressor; import java.io.IOException; /** * */ public class TIFFNullCompressor extends TIFFCompressor { public TIFFNullCompressor() { super("", BaselineTIFFTagSet.COMPRESSION_NONE, true); } public int encode(byte[] b, int off, int width, int height, int[] bitsPerSample, int scanlineStride) throws IOException { int bitsPerPixel = 0; for (int i = 0; i < bitsPerSample.length; i++) { bitsPerPixel += bitsPerSample[i]; } int bytesPerRow = (bitsPerPixel*width + 7)/8; int numBytes = height*bytesPerRow; if(bytesPerRow == scanlineStride) { stream.write(b, off, numBytes); } else { for (int row = 0; row < height; row++) { stream.write(b, off, bytesPerRow); off += scanlineStride; } } return numBytes; } } ././@LongLink0000000000000000000000000000015300000000000011564 Lustar rootrootjai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/tiff/TIFFImageMetadataFormat.javajai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/tiff/TIFFImageMetadataForma0000664000175100017510000001510310203036165032422 0ustar tilletille/* * $RCSfile: TIFFImageMetadataFormat.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.1 $ * $Date: 2005-02-11 05:01:46 $ * $State: Exp $ */ package com.sun.media.imageioimpl.plugins.tiff; import java.util.Collection; import java.util.HashMap; import java.util.Iterator; import java.util.Locale; import java.util.Map; import java.util.MissingResourceException; import java.util.ResourceBundle; import javax.imageio.ImageTypeSpecifier; import javax.imageio.metadata.IIOMetadataFormat; import com.sun.media.imageio.plugins.tiff.BaselineTIFFTagSet; import com.sun.media.imageio.plugins.tiff.TIFFTag; import com.sun.media.imageio.plugins.tiff.TIFFTagSet; public class TIFFImageMetadataFormat extends TIFFMetadataFormat { private static TIFFImageMetadataFormat theInstance = null; static { } public boolean canNodeAppear(String elementName, ImageTypeSpecifier imageType) { return false; } private TIFFImageMetadataFormat() { this.resourceBaseName = "com.sun.media.imageioimpl.plugins.tiff.TIFFImageMetadataFormatResources"; this.rootName = TIFFImageMetadata.nativeMetadataFormatName; TIFFElementInfo einfo; TIFFAttrInfo ainfo; String[] empty = new String[0]; String[] childNames; String[] attrNames; childNames = new String[] { "TIFFIFD" }; einfo = new TIFFElementInfo(childNames, empty, CHILD_POLICY_SEQUENCE); elementInfoMap.put(TIFFImageMetadata.nativeMetadataFormatName, einfo); childNames = new String[] { "TIFFField", "TIFFIFD" }; attrNames = new String[] { "tagSets", "parentTagNumber", "parentTagName" }; einfo = new TIFFElementInfo(childNames, attrNames, CHILD_POLICY_SEQUENCE); elementInfoMap.put("TIFFIFD", einfo); ainfo = new TIFFAttrInfo(); ainfo.dataType = DATATYPE_STRING; ainfo.isRequired = true; attrInfoMap.put("TIFFIFD/tagSets", ainfo); ainfo = new TIFFAttrInfo(); ainfo.dataType = DATATYPE_INTEGER; ainfo.isRequired = false; attrInfoMap.put("TIFFIFD/parentTagNumber", ainfo); ainfo = new TIFFAttrInfo(); ainfo.dataType = DATATYPE_STRING; ainfo.isRequired = false; attrInfoMap.put("TIFFIFD/parentTagName", ainfo); String[] types = { "TIFFByte", "TIFFAscii", "TIFFShort", "TIFFSShort", "TIFFLong", "TIFFSLong", "TIFFRational", "TIFFSRational", "TIFFFloat", "TIFFDouble", "TIFFUndefined" }; attrNames = new String[] { "value", "description" }; String[] attrNamesValueOnly = new String[] { "value" }; TIFFAttrInfo ainfoValue = new TIFFAttrInfo(); TIFFAttrInfo ainfoDescription = new TIFFAttrInfo(); for (int i = 0; i < types.length; i++) { if (!types[i].equals("TIFFUndefined")) { childNames = new String[1]; childNames[0] = types[i]; einfo = new TIFFElementInfo(childNames, empty, CHILD_POLICY_SEQUENCE); elementInfoMap.put(types[i] + "s", einfo); } boolean hasDescription = !types[i].equals("TIFFUndefined") && !types[i].equals("TIFFAscii") && !types[i].equals("TIFFRational") && !types[i].equals("TIFFSRational") && !types[i].equals("TIFFFloat") && !types[i].equals("TIFFDouble"); String[] anames = hasDescription ? attrNames : attrNamesValueOnly; einfo = new TIFFElementInfo(empty, anames, CHILD_POLICY_EMPTY); elementInfoMap.put(types[i], einfo); attrInfoMap.put(types[i] + "/value", ainfoValue); if (hasDescription) { attrInfoMap.put(types[i] + "/description", ainfoDescription); } } childNames = new String[2*types.length - 1]; for (int i = 0; i < types.length; i++) { childNames[2*i] = types[i]; if (!types[i].equals("TIFFUndefined")) { childNames[2*i + 1] = types[i] + "s"; } } attrNames = new String[] { "number", "name" }; einfo = new TIFFElementInfo(childNames, attrNames, CHILD_POLICY_CHOICE); elementInfoMap.put("TIFFField", einfo); ainfo = new TIFFAttrInfo(); ainfo.isRequired = true; attrInfoMap.put("TIFFField/number", ainfo); ainfo = new TIFFAttrInfo(); attrInfoMap.put("TIFFField/name", ainfo); } public static synchronized IIOMetadataFormat getInstance() { if (theInstance == null) { theInstance = new TIFFImageMetadataFormat(); } return theInstance; } } jai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/tiff/TIFFIFD.java0000664000175100017510000005550010506607706030314 0ustar tilletille/* * $RCSfile: TIFFIFD.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.7 $ * $Date: 2006-09-27 23:56:30 $ * $State: Exp $ */ package com.sun.media.imageioimpl.plugins.tiff; import java.io.EOFException; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import java.util.TreeMap; import java.util.Vector; import javax.imageio.stream.ImageInputStream; import javax.imageio.stream.ImageOutputStream; import com.sun.media.imageio.plugins.tiff.BaselineTIFFTagSet; import com.sun.media.imageio.plugins.tiff.TIFFDirectory; import com.sun.media.imageio.plugins.tiff.TIFFField; import com.sun.media.imageio.plugins.tiff.TIFFTag; import com.sun.media.imageio.plugins.tiff.TIFFTagSet; public class TIFFIFD extends TIFFDirectory { private long stripOrTileByteCountsPosition = -1; private long stripOrTileOffsetsPosition = -1; private long lastPosition = -1; public static TIFFTag getTag(int tagNumber, List tagSets) { Iterator iter = tagSets.iterator(); while (iter.hasNext()) { TIFFTagSet tagSet = (TIFFTagSet)iter.next(); TIFFTag tag = tagSet.getTag(tagNumber); if (tag != null) { return tag; } } return null; } public static TIFFTag getTag(String tagName, List tagSets) { Iterator iter = tagSets.iterator(); while (iter.hasNext()) { TIFFTagSet tagSet = (TIFFTagSet)iter.next(); TIFFTag tag = tagSet.getTag(tagName); if (tag != null) { return tag; } } return null; } private static void writeTIFFFieldToStream(TIFFField field, ImageOutputStream stream) throws IOException { int count = field.getCount(); Object data = field.getData(); switch (field.getType()) { case TIFFTag.TIFF_ASCII: for (int i = 0; i < count; i++) { String s = ((String[])data)[i]; int length = s.length(); for (int j = 0; j < length; j++) { stream.writeByte(s.charAt(j) & 0xff); } stream.writeByte(0); } break; case TIFFTag.TIFF_UNDEFINED: case TIFFTag.TIFF_BYTE: case TIFFTag.TIFF_SBYTE: stream.write((byte[])data); break; case TIFFTag.TIFF_SHORT: stream.writeChars((char[])data, 0, ((char[])data).length); break; case TIFFTag.TIFF_SSHORT: stream.writeShorts((short[])data, 0, ((short[])data).length); break; case TIFFTag.TIFF_SLONG: stream.writeInts((int[])data, 0, ((int[])data).length); break; case TIFFTag.TIFF_LONG: for (int i = 0; i < count; i++) { stream.writeInt((int)(((long[])data)[i])); } break; case TIFFTag.TIFF_IFD_POINTER: stream.writeInt(0); // will need to be backpatched break; case TIFFTag.TIFF_FLOAT: stream.writeFloats((float[])data, 0, ((float[])data).length); break; case TIFFTag.TIFF_DOUBLE: stream.writeDoubles((double[])data, 0, ((double[])data).length); break; case TIFFTag.TIFF_SRATIONAL: for (int i = 0; i < count; i++) { stream.writeInt(((int[][])data)[i][0]); stream.writeInt(((int[][])data)[i][1]); } break; case TIFFTag.TIFF_RATIONAL: for (int i = 0; i < count; i++) { long num = ((long[][])data)[i][0]; long den = ((long[][])data)[i][1]; stream.writeInt((int)num); stream.writeInt((int)den); } break; default: // error } } public TIFFIFD(List tagSets, TIFFTag parentTag) { super((TIFFTagSet[])tagSets.toArray(new TIFFTagSet[tagSets.size()]), parentTag); } public TIFFIFD(List tagSets) { this(tagSets, null); } public List getTagSetList() { return Arrays.asList(getTagSets()); } /** * Returns an Iterator over the TIFF fields. The * traversal is in the order of increasing tag number. */ // Note: the sort is guaranteed for low fields by the use of an // array wherein the index corresponds to the tag number and for // the high fields by the use of a TreeMap with tag number keys. public Iterator iterator() { return Arrays.asList(getTIFFFields()).iterator(); } // Stream position initially at beginning, left at end // if ignoreUnknownFields is true, do not load fields for which // a tag cannot be found in an allowed TagSet. public void initialize(ImageInputStream stream, boolean ignoreUnknownFields) throws IOException { removeTIFFFields(); List tagSetList = getTagSetList(); int numEntries = stream.readUnsignedShort(); for (int i = 0; i < numEntries; i++) { // Read tag number, value type, and value count. int tag = stream.readUnsignedShort(); int type = stream.readUnsignedShort(); int count = (int)stream.readUnsignedInt(); // Get the associated TIFFTag. TIFFTag tiffTag = getTag(tag, tagSetList); // Ignore unknown fields. if(ignoreUnknownFields && tiffTag == null) { // Skip the value/offset so as to leave the stream // position at the start of the next IFD entry. stream.skipBytes(4); // XXX Warning message ... // Continue with the next IFD entry. continue; } long nextTagOffset = stream.getStreamPosition() + 4; int sizeOfType = TIFFTag.getSizeOfType(type); if (count*sizeOfType > 4) { long value = stream.readUnsignedInt(); stream.seek(value); } if (tag == BaselineTIFFTagSet.TAG_STRIP_BYTE_COUNTS || tag == BaselineTIFFTagSet.TAG_TILE_BYTE_COUNTS || tag == BaselineTIFFTagSet.TAG_JPEG_INTERCHANGE_FORMAT_LENGTH) { this.stripOrTileByteCountsPosition = stream.getStreamPosition(); } else if (tag == BaselineTIFFTagSet.TAG_STRIP_OFFSETS || tag == BaselineTIFFTagSet.TAG_TILE_OFFSETS || tag == BaselineTIFFTagSet.TAG_JPEG_INTERCHANGE_FORMAT) { this.stripOrTileOffsetsPosition = stream.getStreamPosition(); } Object obj = null; try { switch (type) { case TIFFTag.TIFF_BYTE: case TIFFTag.TIFF_SBYTE: case TIFFTag.TIFF_UNDEFINED: case TIFFTag.TIFF_ASCII: byte[] bvalues = new byte[count]; stream.readFully(bvalues, 0, count); if (type == TIFFTag.TIFF_ASCII) { // Can be multiple strings Vector v = new Vector(); boolean inString = false; int prevIndex = 0; for (int index = 0; index <= count; index++) { if (index < count && bvalues[index] != 0) { if (!inString) { // start of string prevIndex = index; inString = true; } } else { // null or special case at end of string if (inString) { // end of string String s = new String(bvalues, prevIndex, index - prevIndex); v.add(s); inString = false; } } } count = v.size(); String[] strings; if(count != 0) { strings = new String[count]; for (int c = 0 ; c < count; c++) { strings[c] = (String)v.elementAt(c); } } else { // This case has been observed when the value of // 'count' recorded in the field is non-zero but // the value portion contains all nulls. count = 1; strings = new String[] {""}; } obj = strings; } else { obj = bvalues; } break; case TIFFTag.TIFF_SHORT: char[] cvalues = new char[count]; for (int j = 0; j < count; j++) { cvalues[j] = (char)(stream.readUnsignedShort()); } obj = cvalues; break; case TIFFTag.TIFF_LONG: case TIFFTag.TIFF_IFD_POINTER: long[] lvalues = new long[count]; for (int j = 0; j < count; j++) { lvalues[j] = stream.readUnsignedInt(); } obj = lvalues; break; case TIFFTag.TIFF_RATIONAL: long[][] llvalues = new long[count][2]; for (int j = 0; j < count; j++) { llvalues[j][0] = stream.readUnsignedInt(); llvalues[j][1] = stream.readUnsignedInt(); } obj = llvalues; break; case TIFFTag.TIFF_SSHORT: short[] svalues = new short[count]; for (int j = 0; j < count; j++) { svalues[j] = stream.readShort(); } obj = svalues; break; case TIFFTag.TIFF_SLONG: int[] ivalues = new int[count]; for (int j = 0; j < count; j++) { ivalues[j] = stream.readInt(); } obj = ivalues; break; case TIFFTag.TIFF_SRATIONAL: int[][] iivalues = new int[count][2]; for (int j = 0; j < count; j++) { iivalues[j][0] = stream.readInt(); iivalues[j][1] = stream.readInt(); } obj = iivalues; break; case TIFFTag.TIFF_FLOAT: float[] fvalues = new float[count]; for (int j = 0; j < count; j++) { fvalues[j] = stream.readFloat(); } obj = fvalues; break; case TIFFTag.TIFF_DOUBLE: double[] dvalues = new double[count]; for (int j = 0; j < count; j++) { dvalues[j] = stream.readDouble(); } obj = dvalues; break; default: // XXX Warning break; } } catch(EOFException eofe) { // The TIFF 6.0 fields have tag numbers less than or equal // to 532 (ReferenceBlackWhite) or equal to 33432 (Copyright). // If there is an error reading a baseline tag, then re-throw // the exception and fail; otherwise continue with the next // field. if(BaselineTIFFTagSet.getInstance().getTag(tag) == null) { throw eofe; } } if (tiffTag == null) { // XXX Warning: unknown tag } else if (!tiffTag.isDataTypeOK(type)) { // XXX Warning: bad data type } else if (tiffTag.isIFDPointer() && obj != null) { stream.mark(); stream.seek(((long[])obj)[0]); List tagSets = new ArrayList(1); tagSets.add(tiffTag.getTagSet()); TIFFIFD subIFD = new TIFFIFD(tagSets); // XXX Use same ignore policy for sub-IFD fields? subIFD.initialize(stream, ignoreUnknownFields); obj = subIFD; stream.reset(); } if (tiffTag == null) { tiffTag = new TIFFTag(null, tag, 1 << type, null); } // Add the field if its contents have been initialized which // will not be the case if an EOF was ignored above. if(obj != null) { TIFFField f = new TIFFField(tiffTag, type, count, obj); addTIFFField(f); } stream.seek(nextTagOffset); } this.lastPosition = stream.getStreamPosition(); } public void writeToStream(ImageOutputStream stream) throws IOException { int numFields = getNumTIFFFields(); stream.writeShort(numFields); long nextSpace = stream.getStreamPosition() + 12*numFields + 4; Iterator iter = iterator(); while (iter.hasNext()) { TIFFField f = (TIFFField)iter.next(); TIFFTag tag = f.getTag(); int type = f.getType(); int count = f.getCount(); // Hack to deal with unknown tags if (type == 0) { type = TIFFTag.TIFF_UNDEFINED; } int size = count*TIFFTag.getSizeOfType(type); if (type == TIFFTag.TIFF_ASCII) { int chars = 0; for (int i = 0; i < count; i++) { chars += f.getAsString(i).length() + 1; } count = chars; size = count; } int tagNumber = f.getTagNumber(); stream.writeShort(tagNumber); stream.writeShort(type); stream.writeInt(count); // Write a dummy value to fill space stream.writeInt(0); stream.mark(); // Mark beginning of next field stream.skipBytes(-4); long pos; if (size > 4 || tag.isIFDPointer()) { // Ensure IFD or value is written on a word boundary nextSpace = (nextSpace + 3) & ~0x3; stream.writeInt((int)nextSpace); stream.seek(nextSpace); pos = nextSpace; if (tag.isIFDPointer()) { TIFFIFD subIFD = (TIFFIFD)f.getData(); subIFD.writeToStream(stream); nextSpace = subIFD.lastPosition; } else { writeTIFFFieldToStream(f, stream); nextSpace = stream.getStreamPosition(); } } else { pos = stream.getStreamPosition(); writeTIFFFieldToStream(f, stream); } // If we are writing the data for the // StripByteCounts, TileByteCounts, StripOffsets, // TileOffsets, JPEGInterchangeFormat, or // JPEGInterchangeFormatLength fields, record the current stream // position for backpatching if (tagNumber == BaselineTIFFTagSet.TAG_STRIP_BYTE_COUNTS || tagNumber == BaselineTIFFTagSet.TAG_TILE_BYTE_COUNTS || tagNumber == BaselineTIFFTagSet.TAG_JPEG_INTERCHANGE_FORMAT_LENGTH) { this.stripOrTileByteCountsPosition = pos; } else if (tagNumber == BaselineTIFFTagSet.TAG_STRIP_OFFSETS || tagNumber == BaselineTIFFTagSet.TAG_TILE_OFFSETS || tagNumber == BaselineTIFFTagSet.TAG_JPEG_INTERCHANGE_FORMAT) { this.stripOrTileOffsetsPosition = pos; } stream.reset(); // Go to marked position of next field } this.lastPosition = nextSpace; } public long getStripOrTileByteCountsPosition() { return stripOrTileByteCountsPosition; } public long getStripOrTileOffsetsPosition() { return stripOrTileOffsetsPosition; } public long getLastPosition() { return lastPosition; } void setPositions(long stripOrTileOffsetsPosition, long stripOrTileByteCountsPosition, long lastPosition) { this.stripOrTileOffsetsPosition = stripOrTileOffsetsPosition; this.stripOrTileByteCountsPosition = stripOrTileByteCountsPosition; this.lastPosition = lastPosition; } /** * Returns a TIFFIFD wherein all fields from the * BaselineTIFFTagSet are copied by value and all other * fields copied by reference. */ public TIFFIFD getShallowClone() { // Get the baseline TagSet. TIFFTagSet baselineTagSet = BaselineTIFFTagSet.getInstance(); // If the baseline TagSet is not included just return. List tagSetList = getTagSetList(); if(!tagSetList.contains(baselineTagSet)) { return this; } // Create a new object. TIFFIFD shallowClone = new TIFFIFD(tagSetList, getParentTag()); // Get the tag numbers in the baseline set. Set baselineTagNumbers = baselineTagSet.getTagNumbers(); // Iterate over the fields in this IFD. Iterator fields = iterator(); while(fields.hasNext()) { // Get the next field. TIFFField field = (TIFFField)fields.next(); // Get its tag number. Integer tagNumber = new Integer(field.getTagNumber()); // Branch based on membership in baseline set. TIFFField fieldClone; if(baselineTagNumbers.contains(tagNumber)) { // Copy by value. Object fieldData = field.getData(); int fieldType = field.getType(); try { switch (fieldType) { case TIFFTag.TIFF_BYTE: case TIFFTag.TIFF_SBYTE: case TIFFTag.TIFF_UNDEFINED: fieldData = ((byte[])fieldData).clone(); break; case TIFFTag.TIFF_ASCII: fieldData = ((String[])fieldData).clone(); break; case TIFFTag.TIFF_SHORT: fieldData = ((char[])fieldData).clone(); break; case TIFFTag.TIFF_LONG: case TIFFTag.TIFF_IFD_POINTER: fieldData = ((long[])fieldData).clone(); break; case TIFFTag.TIFF_RATIONAL: fieldData = ((long[][])fieldData).clone(); break; case TIFFTag.TIFF_SSHORT: fieldData = ((short[])fieldData).clone(); break; case TIFFTag.TIFF_SLONG: fieldData = ((int[])fieldData).clone(); break; case TIFFTag.TIFF_SRATIONAL: fieldData = ((int[][])fieldData).clone(); break; case TIFFTag.TIFF_FLOAT: fieldData = ((float[])fieldData).clone(); break; case TIFFTag.TIFF_DOUBLE: fieldData = ((double[])fieldData).clone(); break; default: // Shouldn't happen but do nothing ... } } catch(Exception e) { // Ignore it and copy by reference ... } fieldClone = new TIFFField(field.getTag(), fieldType, field.getCount(), fieldData); } else { // Copy by reference. fieldClone = field; } // Add the field to the clone. shallowClone.addTIFFField(fieldClone); } // Set positions. shallowClone.setPositions(stripOrTileOffsetsPosition, stripOrTileByteCountsPosition, lastPosition); return shallowClone; } } ././@LongLink0000000000000000000000000000015200000000000011563 Lustar rootrootjai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/tiff/TIFFPackBitsCompressor.javajai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/tiff/TIFFPackBitsCompressor0000664000175100017510000001152310203036165032531 0ustar tilletille/* * $RCSfile: TIFFPackBitsCompressor.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.1 $ * $Date: 2005-02-11 05:01:49 $ * $State: Exp $ */ package com.sun.media.imageioimpl.plugins.tiff; import com.sun.media.imageio.plugins.tiff.BaselineTIFFTagSet; import com.sun.media.imageio.plugins.tiff.TIFFCompressor; import java.io.IOException; /** * */ public class TIFFPackBitsCompressor extends TIFFCompressor { public TIFFPackBitsCompressor() { super("PackBits", BaselineTIFFTagSet.COMPRESSION_PACKBITS, true); } /** * Performs PackBits compression for a single buffer of data. * This should be called for each row of each tile. The returned * value is the offset into the output buffer after compression. */ private static int packBits(byte[] input, int inOffset, int inCount, byte[] output, int outOffset) { int inMax = inOffset + inCount - 1; int inMaxMinus1 = inMax - 1; while(inOffset <= inMax) { int run = 1; byte replicate = input[inOffset]; while(run < 127 && inOffset < inMax && input[inOffset] == input[inOffset+1]) { run++; inOffset++; } if(run > 1) { inOffset++; output[outOffset++] = (byte)(-(run - 1)); output[outOffset++] = replicate; } run = 0; int saveOffset = outOffset; while(run < 128 && ((inOffset < inMax && input[inOffset] != input[inOffset+1]) || (inOffset < inMaxMinus1 && input[inOffset] != input[inOffset+2]))) { run++; output[++outOffset] = input[inOffset++]; } if(run > 0) { output[saveOffset] = (byte)(run - 1); outOffset++; } if(inOffset == inMax) { if(run > 0 && run < 128) { output[saveOffset]++; output[outOffset++] = input[inOffset++]; } else { output[outOffset++] = (byte)0; output[outOffset++] = input[inOffset++]; } } } return outOffset; } public int encode(byte[] b, int off, int width, int height, int[] bitsPerSample, int scanlineStride) throws IOException { int bitsPerPixel = 0; for (int i = 0; i < bitsPerSample.length; i++) { bitsPerPixel += bitsPerSample[i]; } int bytesPerRow = (bitsPerPixel*width + 7)/8; int bufSize = (int)(bytesPerRow + (bytesPerRow + 127)/128); byte[] compData = new byte[bufSize]; int bytesWritten = 0; for(int i = 0; i < height; i++) { int bytes = packBits(b, off, scanlineStride, compData, 0); off += scanlineStride; bytesWritten += bytes; stream.write(compData, 0, bytes); } return bytesWritten; } } ././@LongLink0000000000000000000000000000015000000000000011561 Lustar rootrootjai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/tiff/TIFFJPEGDecompressor.javajai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/tiff/TIFFJPEGDecompressor.j0000664000175100017510000002003210417024535032317 0ustar tilletille/* * $RCSfile: TIFFJPEGDecompressor.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.2 $ * $Date: 2006-04-11 22:10:36 $ * $State: Exp $ */ package com.sun.media.imageioimpl.plugins.tiff; import java.io.IOException; import java.io.ByteArrayInputStream; import java.util.Iterator; import javax.imageio.ImageIO; import javax.imageio.ImageReader; import javax.imageio.ImageReadParam; import javax.imageio.stream.MemoryCacheImageInputStream; import javax.imageio.stream.ImageInputStream; import com.sun.media.imageio.plugins.tiff.BaselineTIFFTagSet; import com.sun.media.imageio.plugins.tiff.TIFFDecompressor; import com.sun.media.imageio.plugins.tiff.TIFFField; public class TIFFJPEGDecompressor extends TIFFDecompressor { private static final boolean DEBUG = false; // XXX false for release. // Start of Image protected static final int SOI = 0xD8; // End of Image protected static final int EOI = 0xD9; //private static ImageReaderSpi jpegReaderSPI = null;//XXX protected ImageReader JPEGReader = null; protected ImageReadParam JPEGParam; protected boolean hasJPEGTables = false; protected byte[] tables = null; private byte[] data = new byte[0]; /* XXX static { try { IIORegistry registry = IIORegistry.getDefaultInstance(); Class imageReaderClass = Class.forName("javax.imageio.spi.ImageReaderSpi"); Iterator readerSPIs = registry.getServiceProviders(imageReaderClass, new JPEGSPIFilter(), true); if(readerSPIs.hasNext()) { jpegReaderSPI = (ImageReaderSpi)readerSPIs.next(); } } catch(Exception e) { // Ignore it ... } } */ public TIFFJPEGDecompressor() {} /* XXX private static class JPEGSPIFilter implements ServiceRegistry.Filter { JPEGSPIFilter() {} public boolean filter(Object provider) { ImageReaderSpi readerSPI = (ImageReaderSpi)provider; if(readerSPI.getPluginClassName().startsWith("com.sun.imageio")) { String streamMetadataName = readerSPI.getNativeStreamMetadataFormatName(); if(streamMetadataName != null) { return streamMetadataName.indexOf("jpeg_stream") != -1; } else { return false; } } return false; } } */ public void beginDecoding() { // Initialize the JPEG reader if needed. if(this.JPEGReader == null) { if(DEBUG) System.out.println("Initializing JPEGReader"); /* XXX if(this.jpegReaderSPI != null) { try { this.JPEGReader = jpegReaderSPI.createReaderInstance(); } catch(Exception e) { } } if(this.JPEGReader == null) { */ // Get all JPEG readers. Iterator iter = ImageIO.getImageReadersByFormatName("jpeg"); if(!iter.hasNext()) { // XXX The exception thrown should be an IIOException. throw new IllegalStateException("No JPEG readers found!"); } // Initialize reader to the first one. this.JPEGReader = (ImageReader)iter.next(); if(DEBUG) System.out.println("Using "+ JPEGReader.getClass().getName()); this.JPEGParam = JPEGReader.getDefaultReadParam(); } // Get the JPEGTables field. TIFFImageMetadata tmetadata = (TIFFImageMetadata)metadata; TIFFField f = tmetadata.getTIFFField(BaselineTIFFTagSet.TAG_JPEG_TABLES); if (f != null) { this.hasJPEGTables = true; this.tables = f.getAsBytes(); } else { this.hasJPEGTables = false; } } public void decodeRaw(byte[] b, int dstOffset, int bitsPerPixel, int scanlineStride) throws IOException { // Seek to the data position for this segment. stream.seek(offset); // Set the stream variable depending on presence of JPEGTables. ImageInputStream is; if(this.hasJPEGTables) { if(DEBUG) System.out.println("Reading abbreviated stream."); // The current strip or tile is an abbreviated JPEG stream. // Reallocate memory if there is not enough already. int dataLength = tables.length + byteCount; if(data.length < dataLength) { data = new byte[dataLength]; } // Copy the tables ignoring any EOI and subsequent bytes. int dataOffset = tables.length; for(int i = tables.length - 2; i > 0; i--) { if((tables[i] & 0xff) == 0xff && (tables[i+1] & 0xff) == EOI) { dataOffset = i; break; } } System.arraycopy(tables, 0, data, 0, dataOffset); // Check for SOI and skip it if present. byte byte1 = (byte)stream.read(); byte byte2 = (byte)stream.read(); if(!((byte1 & 0xff) == 0xff && (byte2 & 0xff) == SOI)) { data[dataOffset++] = (byte)byte1; data[dataOffset++] = (byte)byte2; } // Read remaining data. stream.readFully(data, dataOffset, byteCount - 2); // Create ImageInputStream. ByteArrayInputStream bais = new ByteArrayInputStream(data); is = new MemoryCacheImageInputStream(bais); } else { if(DEBUG) System.out.println("Reading complete stream."); // The current strip or tile is a complete JPEG stream. is = stream; } // Set the stream on the reader. JPEGReader.setInput(is, false, true); // Set the destination to the raw image ignoring the parameters. JPEGParam.setDestination(rawImage); // Read the strip or tile. JPEGReader.read(0, JPEGParam); } protected void finalize() throws Throwable { super.finalize(); JPEGReader.dispose(); } } ././@LongLink0000000000000000000000000000014600000000000011566 Lustar rootrootjai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/tiff/TIFFStreamMetadata.javajai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/tiff/TIFFStreamMetadata.jav0000664000175100017510000001202110203036165032421 0ustar tilletille/* * $RCSfile: TIFFStreamMetadata.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.1 $ * $Date: 2005-02-11 05:01:50 $ * $State: Exp $ */ package com.sun.media.imageioimpl.plugins.tiff; import java.nio.ByteOrder; import javax.imageio.metadata.IIOMetadata; import javax.imageio.metadata.IIOMetadataNode; import javax.imageio.metadata.IIOInvalidTreeException; import org.w3c.dom.NamedNodeMap; import org.w3c.dom.Node; public class TIFFStreamMetadata extends IIOMetadata { // package scope static final String nativeMetadataFormatName = "com_sun_media_imageio_plugins_tiff_stream_1.0"; static final String nativeMetadataFormatClassName = "com.sun.media.imageioimpl.plugins.tiff.TIFFStreamMetadataFormat"; private static final String bigEndianString = ByteOrder.BIG_ENDIAN.toString(); private static final String littleEndianString = ByteOrder.LITTLE_ENDIAN.toString(); public ByteOrder byteOrder = ByteOrder.BIG_ENDIAN; public TIFFStreamMetadata() { super(false, nativeMetadataFormatName, nativeMetadataFormatClassName, null, null); } public boolean isReadOnly() { return false; } // Shorthand for throwing an IIOInvalidTreeException private static void fatal(Node node, String reason) throws IIOInvalidTreeException { throw new IIOInvalidTreeException(reason, node); } public Node getAsTree(String formatName) { IIOMetadataNode root = new IIOMetadataNode(nativeMetadataFormatName); IIOMetadataNode byteOrderNode = new IIOMetadataNode("ByteOrder"); byteOrderNode.setAttribute("value", byteOrder.toString()); root.appendChild(byteOrderNode); return root; } // public void setFromTree(String formatName, Node root) { // } private void mergeNativeTree(Node root) throws IIOInvalidTreeException { Node node = root; if (!node.getNodeName().equals(nativeMetadataFormatName)) { fatal(node, "Root must be " + nativeMetadataFormatName); } node = node.getFirstChild(); if (node == null || !node.getNodeName().equals("ByteOrder")) { fatal(node, "Root must have \"ByteOrder\" child"); } NamedNodeMap attrs = node.getAttributes(); String order = (String)attrs.getNamedItem("value").getNodeValue(); if (order == null) { fatal(node, "ByteOrder node must have a \"value\" attribute"); } if (order.equals(bigEndianString)) { this.byteOrder = ByteOrder.BIG_ENDIAN; } else if (order.equals(littleEndianString)) { this.byteOrder = ByteOrder.LITTLE_ENDIAN; } else { fatal(node, "Incorrect value for ByteOrder \"value\" attribute"); } } public void mergeTree(String formatName, Node root) throws IIOInvalidTreeException { if (formatName.equals(nativeMetadataFormatName)) { if (root == null) { throw new IllegalArgumentException("root == null!"); } mergeNativeTree(root); } else { throw new IllegalArgumentException("Not a recognized format!"); } } public void reset() { this.byteOrder = ByteOrder.BIG_ENDIAN; } } ././@LongLink0000000000000000000000000000014500000000000011565 Lustar rootrootjai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/tiff/TIFFFaxCompressor.javajai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/tiff/TIFFFaxCompressor.java0000664000175100017510000004672210417024535032505 0ustar tilletille/* * $RCSfile: TIFFFaxCompressor.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.3 $ * $Date: 2006-04-11 22:10:35 $ * $State: Exp $ */ package com.sun.media.imageioimpl.plugins.tiff; import java.io.IOException; import javax.imageio.metadata.IIOMetadata; import com.sun.media.imageio.plugins.tiff.BaselineTIFFTagSet; import com.sun.media.imageio.plugins.tiff.TIFFCompressor; import com.sun.media.imageio.plugins.tiff.TIFFField; /** * */ public abstract class TIFFFaxCompressor extends TIFFCompressor { /** * The CCITT numerical definition of white. */ public static final int WHITE = 0; /** * The CCITT numerical definition of black. */ public static final int BLACK = 1; // --- Begin tables for CCITT compression --- public static byte[] byteTable = new byte[] { 8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, // 0 to 15 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // 16 to 31 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 32 to 47 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 48 to 63 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 64 to 79 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 80 to 95 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 96 to 111 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 112 to 127 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 128 to 143 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 144 to 159 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 160 to 175 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 176 to 191 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 192 to 207 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 208 to 223 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 224 to 239 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 // 240 to 255 }; /** * Terminating codes for black runs. */ public static int[] termCodesBlack = new int[] { /* 0 0x0000 */ 0x0dc0000a, 0x40000003, 0xc0000002, 0x80000002, /* 4 0x0004 */ 0x60000003, 0x30000004, 0x20000004, 0x18000005, /* 8 0x0008 */ 0x14000006, 0x10000006, 0x08000007, 0x0a000007, /* 12 0x000c */ 0x0e000007, 0x04000008, 0x07000008, 0x0c000009, /* 16 0x0010 */ 0x05c0000a, 0x0600000a, 0x0200000a, 0x0ce0000b, /* 20 0x0014 */ 0x0d00000b, 0x0d80000b, 0x06e0000b, 0x0500000b, /* 24 0x0018 */ 0x02e0000b, 0x0300000b, 0x0ca0000c, 0x0cb0000c, /* 28 0x001c */ 0x0cc0000c, 0x0cd0000c, 0x0680000c, 0x0690000c, /* 32 0x0020 */ 0x06a0000c, 0x06b0000c, 0x0d20000c, 0x0d30000c, /* 36 0x0024 */ 0x0d40000c, 0x0d50000c, 0x0d60000c, 0x0d70000c, /* 40 0x0028 */ 0x06c0000c, 0x06d0000c, 0x0da0000c, 0x0db0000c, /* 44 0x002c */ 0x0540000c, 0x0550000c, 0x0560000c, 0x0570000c, /* 48 0x0030 */ 0x0640000c, 0x0650000c, 0x0520000c, 0x0530000c, /* 52 0x0034 */ 0x0240000c, 0x0370000c, 0x0380000c, 0x0270000c, /* 56 0x0038 */ 0x0280000c, 0x0580000c, 0x0590000c, 0x02b0000c, /* 60 0x003c */ 0x02c0000c, 0x05a0000c, 0x0660000c, 0x0670000c }; /** * Terminating codes for white runs. */ public static int[] termCodesWhite = new int[] { /* 0 0x0000 */ 0x35000008, 0x1c000006, 0x70000004, 0x80000004, /* 4 0x0004 */ 0xb0000004, 0xc0000004, 0xe0000004, 0xf0000004, /* 8 0x0008 */ 0x98000005, 0xa0000005, 0x38000005, 0x40000005, /* 12 0x000c */ 0x20000006, 0x0c000006, 0xd0000006, 0xd4000006, /* 16 0x0010 */ 0xa8000006, 0xac000006, 0x4e000007, 0x18000007, /* 20 0x0014 */ 0x10000007, 0x2e000007, 0x06000007, 0x08000007, /* 24 0x0018 */ 0x50000007, 0x56000007, 0x26000007, 0x48000007, /* 28 0x001c */ 0x30000007, 0x02000008, 0x03000008, 0x1a000008, /* 32 0x0020 */ 0x1b000008, 0x12000008, 0x13000008, 0x14000008, /* 36 0x0024 */ 0x15000008, 0x16000008, 0x17000008, 0x28000008, /* 40 0x0028 */ 0x29000008, 0x2a000008, 0x2b000008, 0x2c000008, /* 44 0x002c */ 0x2d000008, 0x04000008, 0x05000008, 0x0a000008, /* 48 0x0030 */ 0x0b000008, 0x52000008, 0x53000008, 0x54000008, /* 52 0x0034 */ 0x55000008, 0x24000008, 0x25000008, 0x58000008, /* 56 0x0038 */ 0x59000008, 0x5a000008, 0x5b000008, 0x4a000008, /* 60 0x003c */ 0x4b000008, 0x32000008, 0x33000008, 0x34000008 }; /** * Make-up codes for black runs. */ public static int[] makeupCodesBlack = new int[] { /* 0 0x0000 */ 0x00000000, 0x03c0000a, 0x0c80000c, 0x0c90000c, /* 4 0x0004 */ 0x05b0000c, 0x0330000c, 0x0340000c, 0x0350000c, /* 8 0x0008 */ 0x0360000d, 0x0368000d, 0x0250000d, 0x0258000d, /* 12 0x000c */ 0x0260000d, 0x0268000d, 0x0390000d, 0x0398000d, /* 16 0x0010 */ 0x03a0000d, 0x03a8000d, 0x03b0000d, 0x03b8000d, /* 20 0x0014 */ 0x0290000d, 0x0298000d, 0x02a0000d, 0x02a8000d, /* 24 0x0018 */ 0x02d0000d, 0x02d8000d, 0x0320000d, 0x0328000d, /* 28 0x001c */ 0x0100000b, 0x0180000b, 0x01a0000b, 0x0120000c, /* 32 0x0020 */ 0x0130000c, 0x0140000c, 0x0150000c, 0x0160000c, /* 36 0x0024 */ 0x0170000c, 0x01c0000c, 0x01d0000c, 0x01e0000c, /* 40 0x0028 */ 0x01f0000c, 0x00000000, 0x00000000, 0x00000000, /* 44 0x002c */ 0x00000000, 0x00000000, 0x00000000, 0x00000000, /* 48 0x0030 */ 0x00000000, 0x00000000, 0x00000000, 0x00000000, /* 52 0x0034 */ 0x00000000, 0x00000000, 0x00000000, 0x00000000, /* 56 0x0038 */ 0x00000000, 0x00000000, 0x00000000, 0x00000000 }; /** * Make-up codes for white runs. */ public static int[] makeupCodesWhite = new int[] { /* 0 0x0000 */ 0x00000000, 0xd8000005, 0x90000005, 0x5c000006, /* 4 0x0004 */ 0x6e000007, 0x36000008, 0x37000008, 0x64000008, /* 8 0x0008 */ 0x65000008, 0x68000008, 0x67000008, 0x66000009, /* 12 0x000c */ 0x66800009, 0x69000009, 0x69800009, 0x6a000009, /* 16 0x0010 */ 0x6a800009, 0x6b000009, 0x6b800009, 0x6c000009, /* 20 0x0014 */ 0x6c800009, 0x6d000009, 0x6d800009, 0x4c000009, /* 24 0x0018 */ 0x4c800009, 0x4d000009, 0x60000006, 0x4d800009, /* 28 0x001c */ 0x0100000b, 0x0180000b, 0x01a0000b, 0x0120000c, /* 32 0x0020 */ 0x0130000c, 0x0140000c, 0x0150000c, 0x0160000c, /* 36 0x0024 */ 0x0170000c, 0x01c0000c, 0x01d0000c, 0x01e0000c, /* 40 0x0028 */ 0x01f0000c, 0x00000000, 0x00000000, 0x00000000, /* 44 0x002c */ 0x00000000, 0x00000000, 0x00000000, 0x00000000, /* 48 0x0030 */ 0x00000000, 0x00000000, 0x00000000, 0x00000000, /* 52 0x0034 */ 0x00000000, 0x00000000, 0x00000000, 0x00000000, /* 56 0x0038 */ 0x00000000, 0x00000000, 0x00000000, 0x00000000 }; /** * Pass mode table. */ public static int[] passMode = new int[] { 0x10000004 // 0001 }; /** * Vertical mode table. */ public static int[] vertMode = new int[] { 0x06000007, // 0000011 0x0c000006, // 000011 0x60000003, // 011 0x80000001, // 1 0x40000003, // 010 0x08000006, // 000010 0x04000007 // 0000010 }; /** * Horizontal mode table. */ public static int[] horzMode = new int[] { 0x20000003 // 001 }; /** * Black and white terminating code table. */ public static int[][] termCodes = new int[][] {termCodesWhite, termCodesBlack}; /** * Black and white make-up code table. */ public static int[][] makeupCodes = new int[][] {makeupCodesWhite, makeupCodesBlack}; /** * Black and white pass mode table. */ public static int[][] pass = new int[][] {passMode, passMode}; /** * Black and white vertical mode table. */ public static int[][] vert = new int[][] {vertMode, vertMode}; /** * Black and white horizontal mode table. */ public static int[][] horz = new int[][] {horzMode, horzMode}; // --- End tables for CCITT compression --- /** * Whether bits are inserted in reverse order (TIFF FillOrder 2). */ public boolean inverseFill = false; /** * Output bit buffer. */ public int bits; /** * Number of bits in the output bit buffer. */ public int ndex; /** * Constructor. The superclass constructor is merely invoked with the * same parameters. */ protected TIFFFaxCompressor(String compressionType, int compressionTagValue, boolean isCompressionLossless) { super(compressionType, compressionTagValue, isCompressionLossless); } /** * Sets the value of the metadata field. * *

The implementation in this class also sets local options * from the FILL_ORDER field if it exists.

* * @param metadata the IIOMetadata object for the * image being written. * * @see #getMetadata() */ public void setMetadata(IIOMetadata metadata) { super.setMetadata(metadata); if (metadata instanceof TIFFImageMetadata) { TIFFImageMetadata tim = (TIFFImageMetadata)metadata; TIFFField f = tim.getTIFFField(BaselineTIFFTagSet.TAG_FILL_ORDER); inverseFill = (f != null && f.getAsInt(0) == 2); } } /** * Return min of maxOffset or offset of first pixel * different from pixel at bitOffset. */ public int nextState(byte[] data, int base, int bitOffset, int maxOffset) { if(data == null) { return maxOffset; } int next = base + (bitOffset>>>3); // If the offset is beyond the data already then the minimum of the // current offset and maxOffset must be maxOffset. if(next >= data.length) { return maxOffset; } int end = base + (maxOffset>>>3); if(end == data.length) { // Prevents out of bounds exception below end--; } int extra = bitOffset & 0x7; int testbyte; if((data[next] & (0x80 >>> extra)) != 0) { // look for "0" testbyte = ~(data[next]) & (0xff >>> extra); while (next < end) { if (testbyte != 0) { break; } testbyte = ~(data[++next]) & 0xff; } } else { // look for "1" if ((testbyte = (data[next] & (0xff >>> extra))) != 0) { bitOffset = (next-base)*8 + byteTable[testbyte]; return ((bitOffset < maxOffset) ? bitOffset : maxOffset); } while (next < end) { if ((testbyte = data[++next]&0xff) != 0) { // "1" is in current byte bitOffset = (next-base)*8 + byteTable[testbyte]; return ((bitOffset < maxOffset) ? bitOffset : maxOffset); } } } bitOffset = (next-base)*8 + byteTable[testbyte]; return ((bitOffset < maxOffset) ? bitOffset : maxOffset); } /** * Initialize bit buffer machinery. */ public void initBitBuf() { ndex = 0; bits = 0x00000000; } /** * Get code for run and add to compressed bitstream. */ public int add1DBits(byte[] buf, int where, // byte offs int count, // #pixels in run int color) // color of run { int sixtyfours; int mask; int len = where; sixtyfours = count >>> 6; // count / 64; count = count & 0x3f; // count % 64 if (sixtyfours != 0) { for ( ; sixtyfours > 40; sixtyfours -= 40) { mask = makeupCodes[color][40]; bits |= (mask & 0xfff80000) >>> ndex; ndex += (int)(mask & 0x0000ffff); while (ndex > 7) { buf[len++] = (byte)(bits >>> 24); bits <<= 8; ndex -= 8; } } mask = makeupCodes[color][sixtyfours]; bits |= (mask & 0xfff80000) >>> ndex; ndex += (int)(mask & 0x0000ffff); while (ndex > 7) { buf[len++] = (byte)(bits >>> 24); bits <<= 8; ndex -= 8; } } mask = termCodes[color][count]; bits |= (mask & 0xfff80000) >>> ndex; ndex += (int)(mask & 0x0000ffff); while (ndex > 7) { buf[len++] = (byte)(bits >>> 24); bits <<= 8; ndex -= 8; } return(len - where); } /** * Place entry from mode table into compressed bitstream. */ public int add2DBits(byte[] buf, // compressed buffer int where, // byte offset into compressed buffer int[][] mode, // 2-D mode to be encoded int entry) // mode entry (0 unless vertical) { int mask; int len = where; int color = 0; mask = mode[color][entry]; bits |= (mask & 0xfff80000) >>> ndex; ndex += (int)(mask & 0x0000ffff); while (ndex > 7) { buf[len++] = (byte)(bits >>> 24); bits <<= 8; ndex -= 8; } return(len - where); } /** * Add an End-of-Line (EOL == 0x001) to the compressed bitstream * with optional byte alignment. */ public int addEOL(boolean is1DMode,// 1D encoding boolean addFill, // byte aligned EOLs boolean add1, // add1 ? EOL+1 : EOL+0 byte[] buf, // compressed buffer address int where) // current byte offset into buffer { int len = where; // // Add zero-valued fill bits such that the EOL is aligned as // // xxxx 0000 0000 0001 // if(addFill) { // // Simply increment the bit count. No need to feed bits into // the output buffer at this point as there are at most 7 bits // in the bit buffer, at most 7 are added here, and at most // 13 below making the total 7+7+13 = 27 before the bit feed // at the end of this routine. // ndex += ((ndex <= 4) ? 4 - ndex : 12 - ndex); } // // Write EOL into buffer // if(is1DMode) { bits |= 0x00100000 >>> ndex; ndex += 12; } else { bits |= (add1 ? 0x00180000 : 0x00100000) >>> ndex; ndex += 13; } while (ndex > 7) { buf[len++] = (byte)(bits >>> 24); bits <<= 8; ndex -= 8; } return(len - where); } /** * Add an End-of-Facsimile-Block (EOFB == 0x001001) to the compressed * bitstream. */ public int addEOFB(byte[] buf, // compressed buffer int where) // byte offset into compressed buffer { int len = where; // // eofb code // bits |= 0x00100100 >>> ndex; // // eofb code length // ndex += 24; // // flush all pending bits // while(ndex > 0) { buf[len++] = (byte)(bits >>> 24); bits <<= 8; ndex -= 8; } return(len - where); } /** * One-dimensionally encode a row of data using CCITT Huffman compression. * The bit buffer should be initialized as required before invoking this * method and should be flushed after the method returns. The fill order * is always highest-order to lowest-order bit so the calling routine * should handle bit inversion. */ public int encode1D(byte[] data, int rowOffset, int colOffset, int rowLength, byte[] compData, int compOffset) { int lineAddr = rowOffset; int bitIndex = colOffset; int last = bitIndex + rowLength; int outIndex = compOffset; // // Is first pixel black // int testbit = ((data[lineAddr + (bitIndex>>>3)]&0xff) >>> (7-(bitIndex & 0x7))) & 0x1; int currentColor = BLACK; if (testbit != 0) { outIndex += add1DBits(compData, outIndex, 0, WHITE); } else { currentColor = WHITE; } // // Run-length encode line // while (bitIndex < last) { int bitCount = nextState(data, lineAddr, bitIndex, last) - bitIndex; outIndex += add1DBits(compData, outIndex, bitCount, currentColor); bitIndex += bitCount; currentColor ^= 0x00000001; } return outIndex - compOffset; } } ././@LongLink0000000000000000000000000000014500000000000011565 Lustar rootrootjai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/tiff/TIFFRenderedImage.javajai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/tiff/TIFFRenderedImage.java0000664000175100017510000002236410377160137032405 0ustar tilletille/* * $RCSfile: TIFFRenderedImage.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.2 $ * $Date: 2006-02-22 22:06:23 $ * $State: Exp $ */ package com.sun.media.imageioimpl.plugins.tiff; import java.awt.Rectangle; import java.awt.image.BufferedImage; import java.awt.image.ColorModel; import java.awt.image.Raster; import java.awt.image.RenderedImage; import java.awt.image.SampleModel; import java.awt.image.WritableRaster; import java.io.IOException; import java.util.Iterator; import java.util.List; import java.util.Vector; import javax.imageio.ImageReadParam; import javax.imageio.ImageTypeSpecifier; import com.sun.media.imageio.plugins.tiff.TIFFImageReadParam; import com.sun.media.imageio.plugins.tiff.TIFFTagSet; public class TIFFRenderedImage implements RenderedImage { TIFFImageReader reader; int imageIndex; ImageReadParam tileParam; int subsampleX; int subsampleY; boolean isSubsampling; int width; int height; int tileWidth; int tileHeight; ImageTypeSpecifier its; public TIFFRenderedImage(TIFFImageReader reader, int imageIndex, ImageReadParam readParam, int width, int height) throws IOException { this.reader = reader; this.imageIndex = imageIndex; this.tileParam = cloneImageReadParam(readParam, false); this.subsampleX = tileParam.getSourceXSubsampling(); this.subsampleY = tileParam.getSourceYSubsampling(); this.isSubsampling = this.subsampleX != 1 || this.subsampleY != 1; this.width = width/subsampleX; this.height = height/subsampleY; // If subsampling is being used, we may not match the // true tile grid exactly, but everything should still work this.tileWidth = reader.getTileWidth(imageIndex)/subsampleX; this.tileHeight = reader.getTileHeight(imageIndex)/subsampleY; Iterator iter = reader.getImageTypes(imageIndex); this.its = (ImageTypeSpecifier)iter.next(); tileParam.setDestinationType(its); } /** * Creates a copy of param. The source subsampling and * and bands settings and the destination bands and offset settings * are copied. If param is a TIFFImageReadParam * then the TIFFDecompressor and * TIFFColorConverter settings are also copied; otherwise * they are explicitly set to null. * * @param param the parameters to be copied. * @param copyTagSets whether the TIFFTagSet settings * should be copied if set. * @return copied parameters. */ private ImageReadParam cloneImageReadParam(ImageReadParam param, boolean copyTagSets) { // Create a new TIFFImageReadParam. TIFFImageReadParam newParam = new TIFFImageReadParam(); // Copy the basic settings. newParam.setSourceSubsampling(param.getSourceXSubsampling(), param.getSourceYSubsampling(), param.getSubsamplingXOffset(), param.getSubsamplingYOffset()); newParam.setSourceBands(param.getSourceBands()); newParam.setDestinationBands(param.getDestinationBands()); newParam.setDestinationOffset(param.getDestinationOffset()); // Set the decompressor and color converter. if(param instanceof TIFFImageReadParam) { // Copy the settings from the input parameter. TIFFImageReadParam tparam = (TIFFImageReadParam)param; newParam.setTIFFDecompressor(tparam.getTIFFDecompressor()); newParam.setColorConverter(tparam.getColorConverter()); if(copyTagSets) { List tagSets = tparam.getAllowedTagSets(); if(tagSets != null) { Iterator tagSetIter = tagSets.iterator(); if(tagSetIter != null) { while(tagSetIter.hasNext()) { TIFFTagSet tagSet = (TIFFTagSet)tagSetIter.next(); newParam.addAllowedTagSet(tagSet); } } } } } else { // Set the decompressor and color converter to null. newParam.setTIFFDecompressor(null); newParam.setColorConverter(null); } return newParam; } public Vector getSources() { return null; } public Object getProperty(String name) { return java.awt.Image.UndefinedProperty; } public String[] getPropertyNames() { return null; } public ColorModel getColorModel() { return its.getColorModel(); } public SampleModel getSampleModel() { return its.getSampleModel(); } public int getWidth() { return width; } public int getHeight() { return height; } public int getMinX() { return 0; } public int getMinY() { return 0; } public int getNumXTiles() { return (width + tileWidth - 1)/tileWidth; } public int getNumYTiles() { return (height + tileHeight - 1)/tileHeight; } public int getMinTileX() { return 0; } public int getMinTileY() { return 0; } public int getTileWidth() { return tileWidth; } public int getTileHeight() { return tileHeight; } public int getTileGridXOffset() { return 0; } public int getTileGridYOffset() { return 0; } public Raster getTile(int tileX, int tileY) { Rectangle tileRect = new Rectangle(tileX*tileWidth, tileY*tileHeight, tileWidth, tileHeight); return getData(tileRect); } public Raster getData() { return read(new Rectangle(0, 0, getWidth(), getHeight())); } public Raster getData(Rectangle rect) { return read(rect); } // This method needs to be synchronized as it updates the instance // variable 'tileParam'. public synchronized WritableRaster read(Rectangle rect) { // XXX Does this need to consider the subsampling offsets or is // that handled implicitly by the reader? tileParam.setSourceRegion(isSubsampling ? new Rectangle(subsampleX*rect.x, subsampleY*rect.y, subsampleX*rect.width, subsampleY*rect.height) : rect); try { BufferedImage bi = reader.read(imageIndex, tileParam); WritableRaster ras = bi.getRaster(); return ras.createWritableChild(0, 0, ras.getWidth(), ras.getHeight(), rect.x, rect.y, null); } catch (IOException e) { throw new RuntimeException(e); } } public WritableRaster copyData(WritableRaster raster) { if (raster == null) { return read(new Rectangle(0, 0, getWidth(), getHeight())); } else { Raster src = read(raster.getBounds()); raster.setRect(src); return raster; } } } ././@LongLink0000000000000000000000000000014700000000000011567 Lustar rootrootjai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/tiff/TIFFFaxDecompressor.javajai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/tiff/TIFFFaxDecompressor.ja0000664000175100017510000015226010666120610032457 0ustar tilletille/* * $RCSfile: TIFFFaxDecompressor.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.15 $ * $Date: 2007-08-31 23:17:28 $ * $State: Exp $ */ package com.sun.media.imageioimpl.plugins.tiff; import java.awt.image.DataBuffer; import java.awt.image.DataBufferByte; import java.awt.image.BufferedImage; import java.awt.image.WritableRaster; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.EOFException; import java.io.PrintStream; import javax.imageio.IIOException; import javax.imageio.ImageTypeSpecifier; import com.sun.media.imageio.plugins.tiff.BaselineTIFFTagSet; import com.sun.media.imageio.plugins.tiff.TIFFDecompressor; import com.sun.media.imageio.plugins.tiff.TIFFField; public class TIFFFaxDecompressor extends TIFFDecompressor { /** * The logical order of bits within a byte. *
     * 1 = MSB-to-LSB
     * 2 = LSB-to-MSB (flipped)
     * 
*/ protected int fillOrder; protected int compression; private int t4Options; private int t6Options; // Variables set by T4Options /** * Uncompressed mode flag: 1 if uncompressed, 0 if not. */ protected int uncompressedMode = 0; /** * EOL padding flag: 1 if fill bits have been added before an EOL such * that the EOL ends on a byte boundary, 0 otherwise. */ protected int fillBits = 0; /** * Coding dimensionality: 1 for 2-dimensional, 0 for 1-dimensional. */ protected int oneD; private byte[] data; private int bitPointer, bytePointer; // Output image buffer private byte[] buffer; private int w, h, bitsPerScanline; private int lineBitNum; // Data structures needed to store changing elements for the previous // and the current scanline private int changingElemSize = 0; private int prevChangingElems[]; private int currChangingElems[]; // Element at which to start search in getNextChangingElement private int lastChangingElement = 0; static int table1[] = { 0x00, // 0 bits are left in first byte - SHOULD NOT HAPPEN 0x01, // 1 bits are left in first byte 0x03, // 2 bits are left in first byte 0x07, // 3 bits are left in first byte 0x0f, // 4 bits are left in first byte 0x1f, // 5 bits are left in first byte 0x3f, // 6 bits are left in first byte 0x7f, // 7 bits are left in first byte 0xff // 8 bits are left in first byte }; static int table2[] = { 0x00, // 0 0x80, // 1 0xc0, // 2 0xe0, // 3 0xf0, // 4 0xf8, // 5 0xfc, // 6 0xfe, // 7 0xff // 8 }; // Table to be used when fillOrder = 2, for flipping bytes. static byte flipTable[] = { 0, -128, 64, -64, 32, -96, 96, -32, 16, -112, 80, -48, 48, -80, 112, -16, 8, -120, 72, -56, 40, -88, 104, -24, 24, -104, 88, -40, 56, -72, 120, -8, 4, -124, 68, -60, 36, -92, 100, -28, 20, -108, 84, -44, 52, -76, 116, -12, 12, -116, 76, -52, 44, -84, 108, -20, 28, -100, 92, -36, 60, -68, 124, -4, 2, -126, 66, -62, 34, -94, 98, -30, 18, -110, 82, -46, 50, -78, 114, -14, 10, -118, 74, -54, 42, -86, 106, -22, 26, -102, 90, -38, 58, -70, 122, -6, 6, -122, 70, -58, 38, -90, 102, -26, 22, -106, 86, -42, 54, -74, 118, -10, 14, -114, 78, -50, 46, -82, 110, -18, 30, -98, 94, -34, 62, -66, 126, -2, 1, -127, 65, -63, 33, -95, 97, -31, 17, -111, 81, -47, 49, -79, 113, -15, 9, -119, 73, -55, 41, -87, 105, -23, 25, -103, 89, -39, 57, -71, 121, -7, 5, -123, 69, -59, 37, -91, 101, -27, 21, -107, 85, -43, 53, -75, 117, -11, 13, -115, 77, -51, 45, -83, 109, -19, 29, -99, 93, -35, 61, -67, 125, -3, 3, -125, 67, -61, 35, -93, 99, -29, 19, -109, 83, -45, 51, -77, 115, -13, 11, -117, 75, -53, 43, -85, 107, -21, 27, -101, 91, -37, 59, -69, 123, -5, 7, -121, 71, -57, 39, -89, 103, -25, 23, -105, 87, -41, 55, -73, 119, -9, 15, -113, 79, -49, 47, -81, 111, -17, 31, -97, 95, -33, 63, -65, 127, -1, }; // The main 10 bit white runs lookup table static short white[] = { // 0 - 7 6430, 6400, 6400, 6400, 3225, 3225, 3225, 3225, // 8 - 15 944, 944, 944, 944, 976, 976, 976, 976, // 16 - 23 1456, 1456, 1456, 1456, 1488, 1488, 1488, 1488, // 24 - 31 718, 718, 718, 718, 718, 718, 718, 718, // 32 - 39 750, 750, 750, 750, 750, 750, 750, 750, // 40 - 47 1520, 1520, 1520, 1520, 1552, 1552, 1552, 1552, // 48 - 55 428, 428, 428, 428, 428, 428, 428, 428, // 56 - 63 428, 428, 428, 428, 428, 428, 428, 428, // 64 - 71 654, 654, 654, 654, 654, 654, 654, 654, // 72 - 79 1072, 1072, 1072, 1072, 1104, 1104, 1104, 1104, // 80 - 87 1136, 1136, 1136, 1136, 1168, 1168, 1168, 1168, // 88 - 95 1200, 1200, 1200, 1200, 1232, 1232, 1232, 1232, // 96 - 103 622, 622, 622, 622, 622, 622, 622, 622, // 104 - 111 1008, 1008, 1008, 1008, 1040, 1040, 1040, 1040, // 112 - 119 44, 44, 44, 44, 44, 44, 44, 44, // 120 - 127 44, 44, 44, 44, 44, 44, 44, 44, // 128 - 135 396, 396, 396, 396, 396, 396, 396, 396, // 136 - 143 396, 396, 396, 396, 396, 396, 396, 396, // 144 - 151 1712, 1712, 1712, 1712, 1744, 1744, 1744, 1744, // 152 - 159 846, 846, 846, 846, 846, 846, 846, 846, // 160 - 167 1264, 1264, 1264, 1264, 1296, 1296, 1296, 1296, // 168 - 175 1328, 1328, 1328, 1328, 1360, 1360, 1360, 1360, // 176 - 183 1392, 1392, 1392, 1392, 1424, 1424, 1424, 1424, // 184 - 191 686, 686, 686, 686, 686, 686, 686, 686, // 192 - 199 910, 910, 910, 910, 910, 910, 910, 910, // 200 - 207 1968, 1968, 1968, 1968, 2000, 2000, 2000, 2000, // 208 - 215 2032, 2032, 2032, 2032, 16, 16, 16, 16, // 216 - 223 10257, 10257, 10257, 10257, 12305, 12305, 12305, 12305, // 224 - 231 330, 330, 330, 330, 330, 330, 330, 330, // 232 - 239 330, 330, 330, 330, 330, 330, 330, 330, // 240 - 247 330, 330, 330, 330, 330, 330, 330, 330, // 248 - 255 330, 330, 330, 330, 330, 330, 330, 330, // 256 - 263 362, 362, 362, 362, 362, 362, 362, 362, // 264 - 271 362, 362, 362, 362, 362, 362, 362, 362, // 272 - 279 362, 362, 362, 362, 362, 362, 362, 362, // 280 - 287 362, 362, 362, 362, 362, 362, 362, 362, // 288 - 295 878, 878, 878, 878, 878, 878, 878, 878, // 296 - 303 1904, 1904, 1904, 1904, 1936, 1936, 1936, 1936, // 304 - 311 -18413, -18413, -16365, -16365, -14317, -14317, -10221, -10221, // 312 - 319 590, 590, 590, 590, 590, 590, 590, 590, // 320 - 327 782, 782, 782, 782, 782, 782, 782, 782, // 328 - 335 1584, 1584, 1584, 1584, 1616, 1616, 1616, 1616, // 336 - 343 1648, 1648, 1648, 1648, 1680, 1680, 1680, 1680, // 344 - 351 814, 814, 814, 814, 814, 814, 814, 814, // 352 - 359 1776, 1776, 1776, 1776, 1808, 1808, 1808, 1808, // 360 - 367 1840, 1840, 1840, 1840, 1872, 1872, 1872, 1872, // 368 - 375 6157, 6157, 6157, 6157, 6157, 6157, 6157, 6157, // 376 - 383 6157, 6157, 6157, 6157, 6157, 6157, 6157, 6157, // 384 - 391 -12275, -12275, -12275, -12275, -12275, -12275, -12275, -12275, // 392 - 399 -12275, -12275, -12275, -12275, -12275, -12275, -12275, -12275, // 400 - 407 14353, 14353, 14353, 14353, 16401, 16401, 16401, 16401, // 408 - 415 22547, 22547, 24595, 24595, 20497, 20497, 20497, 20497, // 416 - 423 18449, 18449, 18449, 18449, 26643, 26643, 28691, 28691, // 424 - 431 30739, 30739, -32749, -32749, -30701, -30701, -28653, -28653, // 432 - 439 -26605, -26605, -24557, -24557, -22509, -22509, -20461, -20461, // 440 - 447 8207, 8207, 8207, 8207, 8207, 8207, 8207, 8207, // 448 - 455 72, 72, 72, 72, 72, 72, 72, 72, // 456 - 463 72, 72, 72, 72, 72, 72, 72, 72, // 464 - 471 72, 72, 72, 72, 72, 72, 72, 72, // 472 - 479 72, 72, 72, 72, 72, 72, 72, 72, // 480 - 487 72, 72, 72, 72, 72, 72, 72, 72, // 488 - 495 72, 72, 72, 72, 72, 72, 72, 72, // 496 - 503 72, 72, 72, 72, 72, 72, 72, 72, // 504 - 511 72, 72, 72, 72, 72, 72, 72, 72, // 512 - 519 104, 104, 104, 104, 104, 104, 104, 104, // 520 - 527 104, 104, 104, 104, 104, 104, 104, 104, // 528 - 535 104, 104, 104, 104, 104, 104, 104, 104, // 536 - 543 104, 104, 104, 104, 104, 104, 104, 104, // 544 - 551 104, 104, 104, 104, 104, 104, 104, 104, // 552 - 559 104, 104, 104, 104, 104, 104, 104, 104, // 560 - 567 104, 104, 104, 104, 104, 104, 104, 104, // 568 - 575 104, 104, 104, 104, 104, 104, 104, 104, // 576 - 583 4107, 4107, 4107, 4107, 4107, 4107, 4107, 4107, // 584 - 591 4107, 4107, 4107, 4107, 4107, 4107, 4107, 4107, // 592 - 599 4107, 4107, 4107, 4107, 4107, 4107, 4107, 4107, // 600 - 607 4107, 4107, 4107, 4107, 4107, 4107, 4107, 4107, // 608 - 615 266, 266, 266, 266, 266, 266, 266, 266, // 616 - 623 266, 266, 266, 266, 266, 266, 266, 266, // 624 - 631 266, 266, 266, 266, 266, 266, 266, 266, // 632 - 639 266, 266, 266, 266, 266, 266, 266, 266, // 640 - 647 298, 298, 298, 298, 298, 298, 298, 298, // 648 - 655 298, 298, 298, 298, 298, 298, 298, 298, // 656 - 663 298, 298, 298, 298, 298, 298, 298, 298, // 664 - 671 298, 298, 298, 298, 298, 298, 298, 298, // 672 - 679 524, 524, 524, 524, 524, 524, 524, 524, // 680 - 687 524, 524, 524, 524, 524, 524, 524, 524, // 688 - 695 556, 556, 556, 556, 556, 556, 556, 556, // 696 - 703 556, 556, 556, 556, 556, 556, 556, 556, // 704 - 711 136, 136, 136, 136, 136, 136, 136, 136, // 712 - 719 136, 136, 136, 136, 136, 136, 136, 136, // 720 - 727 136, 136, 136, 136, 136, 136, 136, 136, // 728 - 735 136, 136, 136, 136, 136, 136, 136, 136, // 736 - 743 136, 136, 136, 136, 136, 136, 136, 136, // 744 - 751 136, 136, 136, 136, 136, 136, 136, 136, // 752 - 759 136, 136, 136, 136, 136, 136, 136, 136, // 760 - 767 136, 136, 136, 136, 136, 136, 136, 136, // 768 - 775 168, 168, 168, 168, 168, 168, 168, 168, // 776 - 783 168, 168, 168, 168, 168, 168, 168, 168, // 784 - 791 168, 168, 168, 168, 168, 168, 168, 168, // 792 - 799 168, 168, 168, 168, 168, 168, 168, 168, // 800 - 807 168, 168, 168, 168, 168, 168, 168, 168, // 808 - 815 168, 168, 168, 168, 168, 168, 168, 168, // 816 - 823 168, 168, 168, 168, 168, 168, 168, 168, // 824 - 831 168, 168, 168, 168, 168, 168, 168, 168, // 832 - 839 460, 460, 460, 460, 460, 460, 460, 460, // 840 - 847 460, 460, 460, 460, 460, 460, 460, 460, // 848 - 855 492, 492, 492, 492, 492, 492, 492, 492, // 856 - 863 492, 492, 492, 492, 492, 492, 492, 492, // 864 - 871 2059, 2059, 2059, 2059, 2059, 2059, 2059, 2059, // 872 - 879 2059, 2059, 2059, 2059, 2059, 2059, 2059, 2059, // 880 - 887 2059, 2059, 2059, 2059, 2059, 2059, 2059, 2059, // 888 - 895 2059, 2059, 2059, 2059, 2059, 2059, 2059, 2059, // 896 - 903 200, 200, 200, 200, 200, 200, 200, 200, // 904 - 911 200, 200, 200, 200, 200, 200, 200, 200, // 912 - 919 200, 200, 200, 200, 200, 200, 200, 200, // 920 - 927 200, 200, 200, 200, 200, 200, 200, 200, // 928 - 935 200, 200, 200, 200, 200, 200, 200, 200, // 936 - 943 200, 200, 200, 200, 200, 200, 200, 200, // 944 - 951 200, 200, 200, 200, 200, 200, 200, 200, // 952 - 959 200, 200, 200, 200, 200, 200, 200, 200, // 960 - 967 232, 232, 232, 232, 232, 232, 232, 232, // 968 - 975 232, 232, 232, 232, 232, 232, 232, 232, // 976 - 983 232, 232, 232, 232, 232, 232, 232, 232, // 984 - 991 232, 232, 232, 232, 232, 232, 232, 232, // 992 - 999 232, 232, 232, 232, 232, 232, 232, 232, // 1000 - 1007 232, 232, 232, 232, 232, 232, 232, 232, // 1008 - 1015 232, 232, 232, 232, 232, 232, 232, 232, // 1016 - 1023 232, 232, 232, 232, 232, 232, 232, 232, }; // Additional make up codes for both White and Black runs static short additionalMakeup[] = { 28679, 28679, 31752, (short)32777, (short)33801, (short)34825, (short)35849, (short)36873, (short)29703, (short)29703, (short)30727, (short)30727, (short)37897, (short)38921, (short)39945, (short)40969 }; // Initial black run look up table, uses the first 4 bits of a code static short initBlack[] = { // 0 - 7 3226, 6412, 200, 168, 38, 38, 134, 134, // 8 - 15 100, 100, 100, 100, 68, 68, 68, 68 }; // static short twoBitBlack[] = {292, 260, 226, 226}; // 0 - 3 // Main black run table, using the last 9 bits of possible 13 bit code static short black[] = { // 0 - 7 62, 62, 30, 30, 0, 0, 0, 0, // 8 - 15 0, 0, 0, 0, 0, 0, 0, 0, // 16 - 23 0, 0, 0, 0, 0, 0, 0, 0, // 24 - 31 0, 0, 0, 0, 0, 0, 0, 0, // 32 - 39 3225, 3225, 3225, 3225, 3225, 3225, 3225, 3225, // 40 - 47 3225, 3225, 3225, 3225, 3225, 3225, 3225, 3225, // 48 - 55 3225, 3225, 3225, 3225, 3225, 3225, 3225, 3225, // 56 - 63 3225, 3225, 3225, 3225, 3225, 3225, 3225, 3225, // 64 - 71 588, 588, 588, 588, 588, 588, 588, 588, // 72 - 79 1680, 1680, 20499, 22547, 24595, 26643, 1776, 1776, // 80 - 87 1808, 1808, -24557, -22509, -20461, -18413, 1904, 1904, // 88 - 95 1936, 1936, -16365, -14317, 782, 782, 782, 782, // 96 - 103 814, 814, 814, 814, -12269, -10221, 10257, 10257, // 104 - 111 12305, 12305, 14353, 14353, 16403, 18451, 1712, 1712, // 112 - 119 1744, 1744, 28691, 30739, -32749, -30701, -28653, -26605, // 120 - 127 2061, 2061, 2061, 2061, 2061, 2061, 2061, 2061, // 128 - 135 424, 424, 424, 424, 424, 424, 424, 424, // 136 - 143 424, 424, 424, 424, 424, 424, 424, 424, // 144 - 151 424, 424, 424, 424, 424, 424, 424, 424, // 152 - 159 424, 424, 424, 424, 424, 424, 424, 424, // 160 - 167 750, 750, 750, 750, 1616, 1616, 1648, 1648, // 168 - 175 1424, 1424, 1456, 1456, 1488, 1488, 1520, 1520, // 176 - 183 1840, 1840, 1872, 1872, 1968, 1968, 8209, 8209, // 184 - 191 524, 524, 524, 524, 524, 524, 524, 524, // 192 - 199 556, 556, 556, 556, 556, 556, 556, 556, // 200 - 207 1552, 1552, 1584, 1584, 2000, 2000, 2032, 2032, // 208 - 215 976, 976, 1008, 1008, 1040, 1040, 1072, 1072, // 216 - 223 1296, 1296, 1328, 1328, 718, 718, 718, 718, // 224 - 231 456, 456, 456, 456, 456, 456, 456, 456, // 232 - 239 456, 456, 456, 456, 456, 456, 456, 456, // 240 - 247 456, 456, 456, 456, 456, 456, 456, 456, // 248 - 255 456, 456, 456, 456, 456, 456, 456, 456, // 256 - 263 326, 326, 326, 326, 326, 326, 326, 326, // 264 - 271 326, 326, 326, 326, 326, 326, 326, 326, // 272 - 279 326, 326, 326, 326, 326, 326, 326, 326, // 280 - 287 326, 326, 326, 326, 326, 326, 326, 326, // 288 - 295 326, 326, 326, 326, 326, 326, 326, 326, // 296 - 303 326, 326, 326, 326, 326, 326, 326, 326, // 304 - 311 326, 326, 326, 326, 326, 326, 326, 326, // 312 - 319 326, 326, 326, 326, 326, 326, 326, 326, // 320 - 327 358, 358, 358, 358, 358, 358, 358, 358, // 328 - 335 358, 358, 358, 358, 358, 358, 358, 358, // 336 - 343 358, 358, 358, 358, 358, 358, 358, 358, // 344 - 351 358, 358, 358, 358, 358, 358, 358, 358, // 352 - 359 358, 358, 358, 358, 358, 358, 358, 358, // 360 - 367 358, 358, 358, 358, 358, 358, 358, 358, // 368 - 375 358, 358, 358, 358, 358, 358, 358, 358, // 376 - 383 358, 358, 358, 358, 358, 358, 358, 358, // 384 - 391 490, 490, 490, 490, 490, 490, 490, 490, // 392 - 399 490, 490, 490, 490, 490, 490, 490, 490, // 400 - 407 4113, 4113, 6161, 6161, 848, 848, 880, 880, // 408 - 415 912, 912, 944, 944, 622, 622, 622, 622, // 416 - 423 654, 654, 654, 654, 1104, 1104, 1136, 1136, // 424 - 431 1168, 1168, 1200, 1200, 1232, 1232, 1264, 1264, // 432 - 439 686, 686, 686, 686, 1360, 1360, 1392, 1392, // 440 - 447 12, 12, 12, 12, 12, 12, 12, 12, // 448 - 455 390, 390, 390, 390, 390, 390, 390, 390, // 456 - 463 390, 390, 390, 390, 390, 390, 390, 390, // 464 - 471 390, 390, 390, 390, 390, 390, 390, 390, // 472 - 479 390, 390, 390, 390, 390, 390, 390, 390, // 480 - 487 390, 390, 390, 390, 390, 390, 390, 390, // 488 - 495 390, 390, 390, 390, 390, 390, 390, 390, // 496 - 503 390, 390, 390, 390, 390, 390, 390, 390, // 504 - 511 390, 390, 390, 390, 390, 390, 390, 390, }; static byte twoDCodes[] = { // 0 - 7 80, 88, 23, 71, 30, 30, 62, 62, // 8 - 15 4, 4, 4, 4, 4, 4, 4, 4, // 16 - 23 11, 11, 11, 11, 11, 11, 11, 11, // 24 - 31 11, 11, 11, 11, 11, 11, 11, 11, // 32 - 39 35, 35, 35, 35, 35, 35, 35, 35, // 40 - 47 35, 35, 35, 35, 35, 35, 35, 35, // 48 - 55 51, 51, 51, 51, 51, 51, 51, 51, // 56 - 63 51, 51, 51, 51, 51, 51, 51, 51, // 64 - 71 41, 41, 41, 41, 41, 41, 41, 41, // 72 - 79 41, 41, 41, 41, 41, 41, 41, 41, // 80 - 87 41, 41, 41, 41, 41, 41, 41, 41, // 88 - 95 41, 41, 41, 41, 41, 41, 41, 41, // 96 - 103 41, 41, 41, 41, 41, 41, 41, 41, // 104 - 111 41, 41, 41, 41, 41, 41, 41, 41, // 112 - 119 41, 41, 41, 41, 41, 41, 41, 41, // 120 - 127 41, 41, 41, 41, 41, 41, 41, 41, }; public TIFFFaxDecompressor() {} /** * Invokes the superclass method and then sets instance variables on * the basis of the metadata set on this decompressor. */ public void beginDecoding() { super.beginDecoding(); if(metadata instanceof TIFFImageMetadata) { TIFFImageMetadata tmetadata = (TIFFImageMetadata)metadata; TIFFField f; f = tmetadata.getTIFFField(BaselineTIFFTagSet.TAG_FILL_ORDER); this.fillOrder = f == null ? 1 : f.getAsInt(0); f = tmetadata.getTIFFField(BaselineTIFFTagSet.TAG_COMPRESSION); this.compression = f == null ? BaselineTIFFTagSet.COMPRESSION_CCITT_RLE : f.getAsInt(0); f = tmetadata.getTIFFField(BaselineTIFFTagSet.TAG_T4_OPTIONS); this.t4Options = f == null ? 0 : f.getAsInt(0); this.oneD = (int)(t4Options & 0x01); // uncompressedMode - haven't dealt with this yet. this.uncompressedMode = (int)((t4Options & 0x02) >> 1); this.fillBits = (int)((t4Options & 0x04) >> 2); f = tmetadata.getTIFFField(BaselineTIFFTagSet.TAG_T6_OPTIONS); this.t6Options = f == null ? 0 : f.getAsInt(0); } else { this.fillOrder = 1; // MSB-to-LSB this.compression = BaselineTIFFTagSet.COMPRESSION_CCITT_RLE; // RLE this.t4Options = 0; // Irrelevant as applies to T.4 only this.oneD = 0; // One-dimensional this.uncompressedMode = 0; // Not uncompressed mode this.fillBits = 0; // No fill bits this.t6Options = 0; } } public void decodeRaw(byte[] b, int dstOffset, int pixelBitStride, // will always be 1 int scanlineStride) throws IOException { this.buffer = b; this.w = srcWidth; this.h = srcHeight; this.bitsPerScanline = scanlineStride*8; this.lineBitNum = 8*dstOffset; this.data = new byte[(int)byteCount]; this.bitPointer = 0; this.bytePointer = 0; this.prevChangingElems = new int[w + 1]; this.currChangingElems = new int[w + 1]; stream.seek(offset); stream.readFully(data); try { if (compression == BaselineTIFFTagSet.COMPRESSION_CCITT_RLE) { decodeRLE(); } else if (compression == BaselineTIFFTagSet.COMPRESSION_CCITT_T_4) { decodeT4(); } else if (compression == BaselineTIFFTagSet.COMPRESSION_CCITT_T_6) { this.uncompressedMode = (int)((t6Options & 0x02) >> 1); decodeT6(); } else { throw new IIOException("Unknown compression type " + compression); } } catch(ArrayIndexOutOfBoundsException e) { ByteArrayOutputStream baos = new ByteArrayOutputStream(); e.printStackTrace(new PrintStream(baos)); String s = new String(baos.toByteArray()); warning("Ignoring exception:\n "+s); } } public void decodeRLE() throws IIOException { for (int i = 0; i < h; i++) { // Decode the line. decodeNextScanline(srcMinY + i); // Advance to the next byte boundary if not already there. if (bitPointer != 0) { bytePointer++; bitPointer = 0; } // Update the total number of bits. lineBitNum += bitsPerScanline; } } public void decodeNextScanline(int lineIndex) throws IIOException { int bits = 0, code = 0, isT = 0; int current, entry, twoBits; boolean isWhite = true; int dstEnd = 0; int bitOffset = 0; // Initialize starting of the changing elements array changingElemSize = 0; // While scanline not complete while (bitOffset < w) { // Mark start of white run. int runOffset = bitOffset; while (isWhite && bitOffset < w) { // White run current = nextNBits(10); entry = white[current]; // Get the 3 fields from the entry isT = entry & 0x0001; bits = (entry >>> 1) & 0x0f; if (bits == 12) { // Additional Make up code // Get the next 2 bits twoBits = nextLesserThan8Bits(2); // Consolidate the 2 new bits and last 2 bits into 4 bits current = ((current << 2) & 0x000c) | twoBits; entry = additionalMakeup[current]; bits = (entry >>> 1) & 0x07; // 3 bits 0000 0111 code = (entry >>> 4) & 0x0fff; // 12 bits bitOffset += code; // Skip white run updatePointer(4 - bits); } else if (bits == 0) { // ERROR warning("Error 0"); // XXX return? } else if (bits == 15) { // EOL // // Instead of throwing an exception, assume that the // EOL was premature; emit a warning and return. // warning("Premature EOL in white run of line "+lineIndex+ ": read "+bitOffset+" of "+w+" expected pixels."); return; } else { // 11 bits - 0000 0111 1111 1111 = 0x07ff code = (entry >>> 5) & 0x07ff; bitOffset += code; updatePointer(10 - bits); if (isT == 0) { isWhite = false; currChangingElems[changingElemSize++] = bitOffset; } } } // Check whether this run completed one width if (bitOffset == w) { // If the white run has not been terminated then ensure that // the next code word is a terminating code for a white run // of length zero. int runLength = bitOffset - runOffset; if(isWhite && runLength != 0 && runLength % 64 == 0 && nextNBits(8) != 0x35) { warning("Missing zero white run length terminating code!"); updatePointer(8); } break; } // Mark start of black run. runOffset = bitOffset; while (isWhite == false && bitOffset < w) { // Black run current = nextLesserThan8Bits(4); entry = initBlack[current]; // Get the 3 fields from the entry isT = entry & 0x0001; bits = (entry >>> 1) & 0x000f; code = (entry >>> 5) & 0x07ff; if (code == 100) { current = nextNBits(9); entry = black[current]; // Get the 3 fields from the entry isT = entry & 0x0001; bits = (entry >>> 1) & 0x000f; code = (entry >>> 5) & 0x07ff; if (bits == 12) { // Additional makeup codes updatePointer(5); current = nextLesserThan8Bits(4); entry = additionalMakeup[current]; bits = (entry >>> 1) & 0x07; // 3 bits 0000 0111 code = (entry >>> 4) & 0x0fff; // 12 bits setToBlack(bitOffset, code); bitOffset += code; updatePointer(4 - bits); } else if (bits == 15) { // // Instead of throwing an exception, assume that the // EOL was premature; emit a warning and return. // warning("Premature EOL in black run of line "+ lineIndex+": read "+bitOffset+" of "+w+ " expected pixels."); return; } else { setToBlack(bitOffset, code); bitOffset += code; updatePointer(9 - bits); if (isT == 0) { isWhite = true; currChangingElems[changingElemSize++] = bitOffset; } } } else if (code == 200) { // Is a Terminating code current = nextLesserThan8Bits(2); entry = twoBitBlack[current]; code = (entry >>> 5) & 0x07ff; bits = (entry >>> 1) & 0x0f; setToBlack(bitOffset, code); bitOffset += code; updatePointer(2 - bits); isWhite = true; currChangingElems[changingElemSize++] = bitOffset; } else { // Is a Terminating code setToBlack(bitOffset, code); bitOffset += code; updatePointer(4 - bits); isWhite = true; currChangingElems[changingElemSize++] = bitOffset; } } // Check whether this run completed one width if (bitOffset == w) { // If the black run has not been terminated then ensure that // the next code word is a terminating code for a black run // of length zero. int runLength = bitOffset - runOffset; if(!isWhite && runLength != 0 && runLength % 64 == 0 && nextNBits(10) != 0x37) { warning("Missing zero black run length terminating code!"); updatePointer(10); } break; } } currChangingElems[changingElemSize++] = bitOffset; } public void decodeT4() throws IIOException { int height = h; int a0, a1, b1, b2; int[] b = new int[2]; int entry, code, bits, color; boolean isWhite; int currIndex = 0; int temp[]; if(data.length < 2) { throw new IIOException("Insufficient data to read initial EOL."); } // The data should start with an EOL code int next12 = nextNBits(12); if(next12 != 1) { warning("T.4 compressed data should begin with EOL."); } updatePointer(12); // Find the first one-dimensionally encoded line. int modeFlag = 0; int lines = -1; // indicates imaginary line before first actual line. while(modeFlag != 1) { try { modeFlag = findNextLine(); lines++; // Normally 'lines' will be 0 on exiting loop. } catch(EOFException eofe) { throw new IIOException("No reference line present."); } } int bitOffset; // Then the 1D encoded scanline data will occur, changing elements // array gets set. decodeNextScanline(srcMinY); lines++; lineBitNum += bitsPerScanline; while(lines < height) { // Every line must begin with an EOL followed by a bit which // indicates whether the following scanline is 1D or 2D encoded. try { modeFlag = findNextLine(); } catch(EOFException eofe) { warning("Input exhausted before EOL found at line "+ (srcMinY+lines)+": read 0 of "+w+" expected pixels."); break; } if(modeFlag == 0) { // 2D encoded scanline follows // Initialize previous scanlines changing elements, and // initialize current scanline's changing elements array temp = prevChangingElems; prevChangingElems = currChangingElems; currChangingElems = temp; currIndex = 0; // a0 has to be set just before the start of this scanline. a0 = -1; isWhite = true; bitOffset = 0; lastChangingElement = 0; while (bitOffset < w) { // Get the next changing element getNextChangingElement(a0, isWhite, b); b1 = b[0]; b2 = b[1]; // Get the next seven bits entry = nextLesserThan8Bits(7); // Run these through the 2DCodes table entry = (int)(twoDCodes[entry] & 0xff); // Get the code and the number of bits used up code = (entry & 0x78) >>> 3; bits = entry & 0x07; if (code == 0) { if (!isWhite) { setToBlack(bitOffset, b2 - bitOffset); } bitOffset = a0 = b2; // Set pointer to consume the correct number of bits. updatePointer(7 - bits); } else if (code == 1) { // Horizontal updatePointer(7 - bits); // identify the next 2 codes. int number; if (isWhite) { number = decodeWhiteCodeWord(); bitOffset += number; currChangingElems[currIndex++] = bitOffset; number = decodeBlackCodeWord(); setToBlack(bitOffset, number); bitOffset += number; currChangingElems[currIndex++] = bitOffset; } else { number = decodeBlackCodeWord(); setToBlack(bitOffset, number); bitOffset += number; currChangingElems[currIndex++] = bitOffset; number = decodeWhiteCodeWord(); bitOffset += number; currChangingElems[currIndex++] = bitOffset; } a0 = bitOffset; } else if (code <= 8) { // Vertical a1 = b1 + (code - 5); currChangingElems[currIndex++] = a1; // We write the current color till a1 - 1 pos, // since a1 is where the next color starts if (!isWhite) { setToBlack(bitOffset, a1 - bitOffset); } bitOffset = a0 = a1; isWhite = !isWhite; updatePointer(7 - bits); } else { warning("Unknown coding mode encountered at line "+ (srcMinY+lines)+": read "+bitOffset+" of "+w+ " expected pixels."); // Find the next one-dimensionally encoded line. int numLinesTested = 0; while(modeFlag != 1) { try { modeFlag = findNextLine(); numLinesTested++; } catch(EOFException eofe) { warning("Sync loss at line "+ (srcMinY+lines)+": read "+ lines+" of "+height+" lines."); return; } } lines += numLinesTested - 1; updatePointer(13); break; } } // Add the changing element beyond the current scanline for the // other color too currChangingElems[currIndex++] = bitOffset; changingElemSize = currIndex; } else { // modeFlag == 1 // 1D encoded scanline follows decodeNextScanline(srcMinY+lines); } lineBitNum += bitsPerScanline; lines++; } // while(lines < height) } public synchronized void decodeT6() throws IIOException { int height = h; int bufferOffset = 0; int a0, a1, b1, b2; int entry, code, bits; byte color; boolean isWhite; int currIndex; int temp[]; // Return values from getNextChangingElement int[] b = new int[2]; // uncompressedMode - have written some code for this, but this // has not been tested due to lack of test images using this optional // extension. This code is when code == 11. aastha 03/03/1999 // Local cached reference int[] cce = currChangingElems; // Assume invisible preceding row of all white pixels and insert // both black and white changing elements beyond the end of this // imaginary scanline. changingElemSize = 0; cce[changingElemSize++] = w; cce[changingElemSize++] = w; int bitOffset; for (int lines = 0; lines < height; lines++) { // a0 has to be set just before the start of the scanline. a0 = -1; isWhite = true; // Assign the changing elements of the previous scanline to // prevChangingElems and start putting this new scanline's // changing elements into the currChangingElems. temp = prevChangingElems; prevChangingElems = currChangingElems; cce = currChangingElems = temp; currIndex = 0; // Start decoding the scanline bitOffset = 0; // Reset search start position for getNextChangingElement lastChangingElement = 0; // Till one whole scanline is decoded while (bitOffset < w) { // Get the next changing element getNextChangingElement(a0, isWhite, b); b1 = b[0]; b2 = b[1]; // Get the next seven bits entry = nextLesserThan8Bits(7); // Run these through the 2DCodes table entry = (int)(twoDCodes[entry] & 0xff); // Get the code and the number of bits used up code = (entry & 0x78) >>> 3; bits = entry & 0x07; if (code == 0) { // Pass // We always assume WhiteIsZero format for fax. if (!isWhite) { if(b2 > w) { b2 = w; warning("Decoded row "+(srcMinY+lines)+ " too long; ignoring extra samples."); } setToBlack(bitOffset, b2 - bitOffset); } bitOffset = a0 = b2; // Set pointer to only consume the correct number of bits. updatePointer(7 - bits); } else if (code == 1) { // Horizontal // Set pointer to only consume the correct number of bits. updatePointer(7 - bits); // identify the next 2 alternating color codes. int number; if (isWhite) { // Following are white and black runs number = decodeWhiteCodeWord(); bitOffset += number; cce[currIndex++] = bitOffset; number = decodeBlackCodeWord(); if(number > w - bitOffset) { number = w - bitOffset; warning("Decoded row "+(srcMinY+lines)+ " too long; ignoring extra samples."); } setToBlack(bitOffset, number); bitOffset += number; cce[currIndex++] = bitOffset; } else { // First a black run and then a white run follows number = decodeBlackCodeWord(); if(number > w - bitOffset) { number = w - bitOffset; warning("Decoded row "+(srcMinY+lines)+ " too long; ignoring extra samples."); } setToBlack(bitOffset, number); bitOffset += number; cce[currIndex++] = bitOffset; number = decodeWhiteCodeWord(); bitOffset += number; cce[currIndex++] = bitOffset; } a0 = bitOffset; } else if (code <= 8) { // Vertical a1 = b1 + (code - 5); cce[currIndex++] = a1; // We write the current color till a1 - 1 pos, // since a1 is where the next color starts if (!isWhite) { if(a1 > w) { a1 = w; warning("Decoded row "+(srcMinY+lines)+ " too long; ignoring extra samples."); } setToBlack(bitOffset, a1 - bitOffset); } bitOffset = a0 = a1; isWhite = !isWhite; updatePointer(7 - bits); } else if (code == 11) { int entranceCode = nextLesserThan8Bits(3); if (entranceCode != 7) { String msg = "Unsupported entrance code "+entranceCode+ " for extension mode at line "+(srcMinY+lines)+"."; warning(msg); } int zeros = 0; boolean exit = false; while (!exit) { while (nextLesserThan8Bits(1) != 1) { zeros++; } if (zeros > 5) { // Exit code // Zeros before exit code zeros = zeros - 6; if (!isWhite && (zeros > 0)) { cce[currIndex++] = bitOffset; } // Zeros before the exit code bitOffset += zeros; if (zeros > 0) { // Some zeros have been written isWhite = true; } // Read in the bit which specifies the color of // the following run if (nextLesserThan8Bits(1) == 0) { if (!isWhite) { cce[currIndex++] = bitOffset; } isWhite = true; } else { if (isWhite) { cce[currIndex++] = bitOffset; } isWhite = false; } exit = true; } if (zeros == 5) { if (!isWhite) { cce[currIndex++] = bitOffset; } bitOffset += zeros; // Last thing written was white isWhite = true; } else { bitOffset += zeros; cce[currIndex++] = bitOffset; setToBlack(bitOffset, 1); ++bitOffset; // Last thing written was black isWhite = false; } } } else { String msg = "Unknown coding mode encountered at line "+ (srcMinY+lines)+"."; warning(msg); } } // while bitOffset < w // Add the changing element beyond the current scanline for the // other color too, if not already added previously if (currIndex <= w) cce[currIndex++] = bitOffset; // Number of changing elements in this scanline. changingElemSize = currIndex; lineBitNum += bitsPerScanline; } // for lines < height } private void setToBlack(int bitNum, int numBits) { // bitNum is relative to current scanline so bump it by lineBitNum bitNum += lineBitNum; int lastBit = bitNum + numBits; int byteNum = bitNum >> 3; // Handle bits in first byte int shift = bitNum & 0x7; if (shift > 0) { int maskVal = 1 << (7 - shift); byte val = buffer[byteNum]; while (maskVal > 0 && bitNum < lastBit) { val |= maskVal; maskVal >>= 1; ++bitNum; } buffer[byteNum] = val; } // Fill in 8 bits at a time byteNum = bitNum >> 3; while (bitNum < lastBit - 7) { buffer[byteNum++] = (byte)255; bitNum += 8; } // Fill in remaining bits while (bitNum < lastBit) { byteNum = bitNum >> 3; buffer[byteNum] |= 1 << (7 - (bitNum & 0x7)); ++bitNum; } } // Returns run length private int decodeWhiteCodeWord() throws IIOException { int current, entry, bits, isT, twoBits, code = -1; int runLength = 0; boolean isWhite = true; while (isWhite) { current = nextNBits(10); entry = white[current]; // Get the 3 fields from the entry isT = entry & 0x0001; bits = (entry >>> 1) & 0x0f; if (bits == 12) { // Additional Make up code // Get the next 2 bits twoBits = nextLesserThan8Bits(2); // Consolidate the 2 new bits and last 2 bits into 4 bits current = ((current << 2) & 0x000c) | twoBits; entry = additionalMakeup[current]; bits = (entry >>> 1) & 0x07; // 3 bits 0000 0111 code = (entry >>> 4) & 0x0fff; // 12 bits runLength += code; updatePointer(4 - bits); } else if (bits == 0) { // ERROR throw new IIOException("Error 0"); } else if (bits == 15) { // EOL throw new IIOException("Error 1"); } else { // 11 bits - 0000 0111 1111 1111 = 0x07ff code = (entry >>> 5) & 0x07ff; runLength += code; updatePointer(10 - bits); if (isT == 0) { isWhite = false; } } } return runLength; } // Returns run length private int decodeBlackCodeWord() throws IIOException { int current, entry, bits, isT, twoBits, code = -1; int runLength = 0; boolean isWhite = false; while (!isWhite) { current = nextLesserThan8Bits(4); entry = initBlack[current]; // Get the 3 fields from the entry isT = entry & 0x0001; bits = (entry >>> 1) & 0x000f; code = (entry >>> 5) & 0x07ff; if (code == 100) { current = nextNBits(9); entry = black[current]; // Get the 3 fields from the entry isT = entry & 0x0001; bits = (entry >>> 1) & 0x000f; code = (entry >>> 5) & 0x07ff; if (bits == 12) { // Additional makeup codes updatePointer(5); current = nextLesserThan8Bits(4); entry = additionalMakeup[current]; bits = (entry >>> 1) & 0x07; // 3 bits 0000 0111 code = (entry >>> 4) & 0x0fff; // 12 bits runLength += code; updatePointer(4 - bits); } else if (bits == 15) { // EOL code throw new IIOException("Error 2"); } else { runLength += code; updatePointer(9 - bits); if (isT == 0) { isWhite = true; } } } else if (code == 200) { // Is a Terminating code current = nextLesserThan8Bits(2); entry = twoBitBlack[current]; code = (entry >>> 5) & 0x07ff; runLength += code; bits = (entry >>> 1) & 0x0f; updatePointer(2 - bits); isWhite = true; } else { // Is a Terminating code runLength += code; updatePointer(4 - bits); isWhite = true; } } return runLength; } private int findNextLine() throws IIOException, EOFException { // Set maximum and current bit index into the compressed data. int bitIndexMax = data.length*8 - 1; int bitIndexMax12 = bitIndexMax - 12; int bitIndex = bytePointer*8 + bitPointer; // Loop while at least 12 bits are available. while(bitIndex <= bitIndexMax12) { // Get the next 12 bits. int next12Bits = nextNBits(12); bitIndex += 12; // Loop while the 12 bits are not unity, i.e., while the EOL // has not been reached, and there is at least one bit left. while(next12Bits != 1 && bitIndex < bitIndexMax) { next12Bits = ((next12Bits & 0x000007ff) << 1) | (nextLesserThan8Bits(1) & 0x00000001); bitIndex++; } if(next12Bits == 1) { // now positioned just after EOL if(oneD == 1) { // two-dimensional coding if(bitIndex < bitIndexMax) { // check next bit against type of line being sought return nextLesserThan8Bits(1); } } else { return 1; } } } // EOL not found. throw new EOFException(); } private void getNextChangingElement(int a0, boolean isWhite, int[] ret) throws IIOException { // Local copies of instance variables int[] pce = this.prevChangingElems; int ces = this.changingElemSize; // If the previous match was at an odd element, we still // have to search the preceeding element. // int start = lastChangingElement & ~0x1; int start = lastChangingElement > 0 ? lastChangingElement - 1 : 0; if (isWhite) { start &= ~0x1; // Search even numbered elements } else { start |= 0x1; // Search odd numbered elements } int i = start; for (; i < ces; i += 2) { int temp = pce[i]; if (temp > a0) { lastChangingElement = i; ret[0] = temp; break; } } if (i + 1 < ces) { ret[1] = pce[i + 1]; } } private int nextNBits(int bitsToGet) throws IIOException { byte b, next, next2next; int l = data.length - 1; int bp = this.bytePointer; if (fillOrder == 1) { b = data[bp]; if (bp == l) { next = 0x00; next2next = 0x00; } else if ((bp + 1) == l) { next = data[bp + 1]; next2next = 0x00; } else { next = data[bp + 1]; next2next = data[bp + 2]; } } else if (fillOrder == 2) { b = flipTable[data[bp] & 0xff]; if (bp == l) { next = 0x00; next2next = 0x00; } else if ((bp + 1) == l) { next = flipTable[data[bp + 1] & 0xff]; next2next = 0x00; } else { next = flipTable[data[bp + 1] & 0xff]; next2next = flipTable[data[bp + 2] & 0xff]; } } else { throw new IIOException("Invalid FillOrder"); } int bitsLeft = 8 - bitPointer; int bitsFromNextByte = bitsToGet - bitsLeft; int bitsFromNext2NextByte = 0; if (bitsFromNextByte > 8) { bitsFromNext2NextByte = bitsFromNextByte - 8; bitsFromNextByte = 8; } bytePointer++; int i1 = (b & table1[bitsLeft]) << (bitsToGet - bitsLeft); int i2 = (next & table2[bitsFromNextByte]) >>> (8 - bitsFromNextByte); int i3 = 0; if (bitsFromNext2NextByte != 0) { i2 <<= bitsFromNext2NextByte; i3 = (next2next & table2[bitsFromNext2NextByte]) >>> (8 - bitsFromNext2NextByte); i2 |= i3; bytePointer++; bitPointer = bitsFromNext2NextByte; } else { if (bitsFromNextByte == 8) { bitPointer = 0; bytePointer++; } else { bitPointer = bitsFromNextByte; } } int i = i1 | i2; return i; } private int nextLesserThan8Bits(int bitsToGet) throws IIOException { byte b, next; int l = data.length - 1; int bp = this.bytePointer; if (fillOrder == 1) { b = data[bp]; if (bp == l) { next = 0x00; } else { next = data[bp + 1]; } } else if (fillOrder == 2) { b = flipTable[data[bp] & 0xff]; if (bp == l) { next = 0x00; } else { next = flipTable[data[bp + 1] & 0xff]; } } else { throw new IIOException("Invalid FillOrder"); } int bitsLeft = 8 - bitPointer; int bitsFromNextByte = bitsToGet - bitsLeft; int shift = bitsLeft - bitsToGet; int i1, i2; if (shift >= 0) { i1 = (b & table1[bitsLeft]) >>> shift; bitPointer += bitsToGet; if (bitPointer == 8) { bitPointer = 0; bytePointer++; } } else { i1 = (b & table1[bitsLeft]) << (-shift); i2 = (next & table2[bitsFromNextByte]) >>> (8 - bitsFromNextByte); i1 |= i2; bytePointer++; bitPointer = bitsFromNextByte; } return i1; } // Move pointer backwards by given amount of bits private void updatePointer(int bitsToMoveBack) { if (bitsToMoveBack > 8) { bytePointer -= bitsToMoveBack/8; bitsToMoveBack %= 8; } int i = bitPointer - bitsToMoveBack; if (i < 0) { bytePointer--; bitPointer = 8 + i; } else { bitPointer = i; } } // Forward warning message to reader private void warning(String msg) { if(this.reader instanceof TIFFImageReader) { ((TIFFImageReader)reader).forwardWarningMessage(msg); } } } ././@LongLink0000000000000000000000000000016400000000000011566 Lustar rootrootjai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/tiff/TIFFImageMetadataFormatResources.javajai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/tiff/TIFFImageMetadataForma0000664000175100017510000001207210203036165032424 0ustar tilletille/* * $RCSfile: TIFFImageMetadataFormatResources.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.1 $ * $Date: 2005-02-11 05:01:46 $ * $State: Exp $ */ package com.sun.media.imageioimpl.plugins.tiff; import java.util.ListResourceBundle; public class TIFFImageMetadataFormatResources extends ListResourceBundle { private static final Object[][] contents = { { "TIFFIFD", "An IFD (directory) containing fields" }, { "TIFFIFD/parentTagNumber", "The tag number of the field pointing to this IFD" }, { "TIFFIFD/parentTagName", "A mnemonic name for the field pointing to this IFD, if known" }, { "TIFFField", "A field containing data" }, { "TIFFField/number", "The tag number asociated with the field" }, { "TIFFField/name", "A mnemonic name associated with the field, if known" }, { "TIFFUndefined", "Uninterpreted byte data" }, { "TIFFUndefined/value", "A list of comma-separated byte values" }, { "TIFFBytes", "A sequence of TIFFByte nodes" }, { "TIFFByte", "An integral value between 0 and 255" }, { "TIFFByte/value", "The value" }, { "TIFFByte/description", "A description, if available" }, { "TIFFAsciis", "A sequence of TIFFAscii nodes" }, { "TIFFAscii", "A String value" }, { "TIFFAscii/value", "The value" }, { "TIFFShorts", "A sequence of TIFFShort nodes" }, { "TIFFShort", "An integral value between 0 and 65535" }, { "TIFFShort/value", "The value" }, { "TIFFShort/description", "A description, if available" }, { "TIFFSShorts", "A sequence of TIFFSShort nodes" }, { "TIFFSShort", "An integral value between -32768 and 32767" }, { "TIFFSShort/value", "The value" }, { "TIFFSShort/description", "A description, if available" }, { "TIFFLongs", "A sequence of TIFFLong nodes" }, { "TIFFLong", "An integral value between 0 and 4294967295" }, { "TIFFLong/value", "The value" }, { "TIFFLong/description", "A description, if available" }, { "TIFFSLongs", "A sequence of TIFFSLong nodes" }, { "TIFFSLong", "An integral value between -2147483648 and 2147483647" }, { "TIFFSLong/value", "The value" }, { "TIFFSLong/description", "A description, if available" }, { "TIFFRationals", "A sequence of TIFFRational nodes" }, { "TIFFRational", "A rational value consisting of an unsigned numerator and denominator" }, { "TIFFRational/value", "The numerator and denominator, separated by a slash" }, { "TIFFSRationals", "A sequence of TIFFSRational nodes" }, { "TIFFSRational", "A rational value consisting of a signed numerator and denominator" }, { "TIFFSRational/value", "The numerator and denominator, separated by a slash" }, { "TIFFFloats", "A sequence of TIFFFloat nodes" }, { "TIFFFloat", "A single-precision floating-point value" }, { "TIFFFloat/value", "The value" }, { "TIFFDoubles", "A sequence of TIFFDouble nodes" }, { "TIFFDouble", "A double-precision floating-point value" }, { "TIFFDouble/value", "The value" }, }; public TIFFImageMetadataFormatResources() { } public Object[][] getContents() { return contents; } } ././@LongLink0000000000000000000000000000014500000000000011565 Lustar rootrootjai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/tiff/TIFFLZWCompressor.javajai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/tiff/TIFFLZWCompressor.java0000664000175100017510000001040310203036165032421 0ustar tilletille/* * $RCSfile: TIFFLZWCompressor.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.1 $ * $Date: 2005-02-11 05:01:48 $ * $State: Exp $ */ package com.sun.media.imageioimpl.plugins.tiff; import java.io.IOException; import javax.imageio.stream.ImageOutputStream; import com.sun.media.imageio.plugins.tiff.BaselineTIFFTagSet; import com.sun.media.imageio.plugins.tiff.TIFFCompressor; import com.sun.media.imageioimpl.common.LZWCompressor; /** * LZW Compressor. */ public class TIFFLZWCompressor extends TIFFCompressor { int predictor; public TIFFLZWCompressor(int predictorValue) { super("LZW", BaselineTIFFTagSet.COMPRESSION_LZW, true); this.predictor = predictorValue; } public void setStream(ImageOutputStream stream) { super.setStream(stream); } public int encode(byte[] b, int off, int width, int height, int[] bitsPerSample, int scanlineStride) throws IOException { LZWCompressor lzwCompressor = new LZWCompressor(stream, 8, true); int samplesPerPixel = bitsPerSample.length; int bitsPerPixel = 0; for (int i = 0; i < samplesPerPixel; i++) { bitsPerPixel += bitsPerSample[i]; } int bytesPerRow = (bitsPerPixel*width + 7)/8; long initialStreamPosition = stream.getStreamPosition(); boolean usePredictor = predictor == BaselineTIFFTagSet.PREDICTOR_HORIZONTAL_DIFFERENCING; if(bytesPerRow == scanlineStride && !usePredictor) { lzwCompressor.compress(b, off, bytesPerRow*height); } else { byte[] rowBuf = usePredictor ? new byte[bytesPerRow] : null; for(int i = 0; i < height; i++) { if(usePredictor) { // Cannot modify b[] in place as it might be a data // array from the image being written so make a copy. System.arraycopy(b, off, rowBuf, 0, bytesPerRow); for(int j = bytesPerRow - 1; j >= samplesPerPixel; j--) { rowBuf[j] -= rowBuf[j - samplesPerPixel]; } lzwCompressor.compress(rowBuf, 0, bytesPerRow); } else { lzwCompressor.compress(b, off, bytesPerRow); } off += scanlineStride; } } lzwCompressor.flush(); int bytesWritten = (int)(stream.getStreamPosition() - initialStreamPosition); return bytesWritten; } } jai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/tiff/TIFFT4Compressor.java0000664000175100017510000002514510417024535032252 0ustar tilletille/* * $RCSfile: TIFFT4Compressor.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.2 $ * $Date: 2006-04-11 22:10:37 $ * $State: Exp $ */ package com.sun.media.imageioimpl.plugins.tiff; import com.sun.media.imageio.plugins.tiff.BaselineTIFFTagSet; import com.sun.media.imageio.plugins.tiff.TIFFCompressor; import com.sun.media.imageio.plugins.tiff.TIFFField; import com.sun.media.imageio.plugins.tiff.TIFFTag; import java.io.IOException; import javax.imageio.IIOException; import javax.imageio.metadata.IIOMetadata; /** * */ public class TIFFT4Compressor extends TIFFFaxCompressor { private boolean is1DMode = false; private boolean isEOLAligned = false; public TIFFT4Compressor() { super("CCITT T.4", BaselineTIFFTagSet.COMPRESSION_CCITT_T_4, true); } /** * Sets the value of the metadata field. * *

The implementation in this class also sets local options * from the T4_OPTIONS field if it exists, and if it doesn't, adds * it with default values.

* * @param metadata the IIOMetadata object for the * image being written. * * @see #getMetadata() */ public void setMetadata(IIOMetadata metadata) { super.setMetadata(metadata); if (metadata instanceof TIFFImageMetadata) { TIFFImageMetadata tim = (TIFFImageMetadata)metadata; TIFFField f = tim.getTIFFField(BaselineTIFFTagSet.TAG_T4_OPTIONS); if (f != null) { int options = f.getAsInt(0); is1DMode = (options & 0x1) == 0; isEOLAligned = (options & 0x4) == 0x4; } else { long[] oarray = new long[1]; oarray[0] = (isEOLAligned ? 0x4 : 0x0) | (is1DMode ? 0x0 : 0x1); BaselineTIFFTagSet base = BaselineTIFFTagSet.getInstance(); TIFFField T4Options = new TIFFField(base.getTag(BaselineTIFFTagSet.TAG_T4_OPTIONS), TIFFTag.TIFF_LONG, 1, oarray); tim.rootIFD.addTIFFField(T4Options); } } } /** * Encode a buffer of data using CCITT T.4 Compression also known as * Group 3 facsimile compression. * * @param is1DMode Whether to perform one-dimensional encoding. * @param isEOLAligned Whether EOL bit sequences should be padded. * @param data The row of data to compress. * @param lineStride Byte step between the same sample in different rows. * @param colOffset Bit offset within first data[rowOffset]. * @param width Number of bits in the row. * @param height Number of rows in the buffer. * @param compData The compressed data. * * @return The number of bytes saved in the compressed data array. */ public int encodeT4(boolean is1DMode, boolean isEOLAligned, byte[] data, int lineStride, int colOffset, int width, int height, byte[] compData) { // // ao, a1, a2 are bit indices in the current line // b1 and b2 are bit indices in the reference line (line above) // color is the current color (WHITE or BLACK) // byte[] refData = data; int lineAddr = 0; int outIndex = 0; initBitBuf(); int KParameter = 2; for(int numRows = 0; numRows < height; numRows++) { if(is1DMode || (numRows % KParameter) == 0) { // 1D encoding // Write EOL+1 outIndex += addEOL(is1DMode, isEOLAligned, true, compData, outIndex); // Encode row outIndex += encode1D(data, lineAddr, colOffset, width, compData, outIndex); } else { // 2D encoding. // Write EOL+0 outIndex += addEOL(is1DMode, isEOLAligned, false, compData, outIndex); // Set reference to previous line int refAddr = lineAddr - lineStride; // Encode row int a0 = colOffset; int last = a0 + width; int testbit = ((data[lineAddr + (a0>>>3)]&0xff) >>> (7-(a0 & 0x7))) & 0x1; int a1 = testbit != 0 ? a0 : nextState(data, lineAddr, a0, last); testbit = ((refData[refAddr + (a0>>>3)]&0xff) >>> (7-(a0 & 0x7))) & 0x1; int b1 = testbit != 0 ? a0 : nextState(refData, refAddr, a0, last); // The current color is set to WHITE at line start int color = WHITE; while(true) { int b2 = nextState(refData, refAddr, b1, last); if(b2 < a1) { // pass mode outIndex += add2DBits(compData, outIndex, pass, 0); a0 = b2; } else { int tmp = b1 - a1 + 3; if((tmp <= 6) && (tmp >= 0)) { // vertical mode outIndex += add2DBits(compData, outIndex, vert, tmp); a0 = a1; } else { // horizontal mode int a2 = nextState(data, lineAddr, a1, last); outIndex += add2DBits(compData, outIndex, horz, 0); outIndex += add1DBits(compData, outIndex, a1-a0, color); outIndex += add1DBits(compData, outIndex, a2-a1, color^1); a0 = a2; } } if(a0 >= last) { break; } color = ((data[lineAddr + (a0>>>3)]&0xff) >>> (7-(a0 & 0x7))) & 0x1; a1 = nextState(data, lineAddr, a0, last); b1 = nextState(refData, refAddr, a0, last); testbit = ((refData[refAddr + (b1>>>3)]&0xff) >>> (7-(b1 & 0x7))) & 0x1; if(testbit == color) { b1 = nextState(refData, refAddr, b1, last); } } } // Skip to next line. lineAddr += lineStride; } for(int i = 0; i < 6; i++) { outIndex += addEOL(is1DMode, isEOLAligned, true, compData, outIndex); } // // flush all pending bits // while(ndex > 0) { compData[outIndex++] = (byte)(bits >>> 24); bits <<= 8; ndex -= 8; } // Flip the bytes if inverse fill was requested. if(inverseFill) { for(int i = 0; i < outIndex; i++) { compData[i] = TIFFFaxDecompressor.flipTable[compData[i]&0xff]; } } return outIndex; } public int encode(byte[] b, int off, int width, int height, int[] bitsPerSample, int scanlineStride) throws IOException { if (bitsPerSample.length != 1 || bitsPerSample[0] != 1) { throw new IIOException( "Bits per sample must be 1 for T4 compression!"); } // This initial buffer size is based on an alternating 1-0 // pattern generating the most bits when converted to code // words: 9 bits out for each pair of bits in. So the number // of bit pairs is determined, multiplied by 9, converted to // bytes, and a ceil() is taken to account for fill bits at the // end of each line. The "2" addend accounts for the case // of the pattern beginning with black. The buffer is intended // to hold only a single row. int maxBits = 9*((width + 1)/2) + 2; int bufSize = (maxBits + 7)/8; // Calculate the maximum row as the G3-1D size plus the EOL, // multiply this by the number of rows in the tile, and add // 6 EOLs for the RTC (return to control). bufSize = height*(bufSize + 2) + 12; byte[] compData = new byte[bufSize]; int bytes = encodeT4(is1DMode, isEOLAligned, b, scanlineStride, 8*off, width, height, compData); stream.write(compData, 0, bytes); return bytes; } } jai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/tiff/properties0000664000175100017510000000050210203036165030472 0ustar tilletille# # $RCSfile: properties,v $ # # Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved. # # Use is subject to license terms. # # $Revision: 1.1 $ # $Date: 2005-02-11 05:01:51 $ # $State: Exp $ # # Internationalization file for com.sun.media.imageioimpl.plugins.tiff TIFFDeflateDecompressor0=Error inflating data. ././@LongLink0000000000000000000000000000014600000000000011566 Lustar rootrootjai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/tiff/TIFFImageReaderSpi.javajai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/tiff/TIFFImageReaderSpi.jav0000664000175100017510000001066010413303155032354 0ustar tilletille/* * $RCSfile: TIFFImageReaderSpi.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.2 $ * $Date: 2006-03-31 19:43:41 $ * $State: Exp $ */ package com.sun.media.imageioimpl.plugins.tiff; import java.io.IOException; import java.util.Locale; import javax.imageio.ImageReader; import javax.imageio.spi.ImageReaderSpi; import javax.imageio.spi.ServiceRegistry; import javax.imageio.stream.ImageInputStream; import com.sun.media.imageioimpl.common.PackageUtil; public class TIFFImageReaderSpi extends ImageReaderSpi { private static final String[] names = { "tif", "TIF", "tiff", "TIFF" }; private static final String[] suffixes = { "tif", "tiff" }; private static final String[] MIMETypes = { "image/tiff" }; private static final String readerClassName = "com.sun.media.imageioimpl.plugins.tiff.TIFFImageReader"; private static final String[] writerSpiNames = { "com.sun.media.imageioimpl.plugins.tiff.TIFFImageWriterSpi" }; private boolean registered = false; public TIFFImageReaderSpi() { super(PackageUtil.getVendor(), PackageUtil.getVersion(), names, suffixes, MIMETypes, readerClassName, STANDARD_INPUT_TYPE, writerSpiNames, false, TIFFStreamMetadata.nativeMetadataFormatName, "com.sun.media.imageioimpl.plugins.tiff.TIFFStreamMetadataFormat", null, null, true, TIFFImageMetadata.nativeMetadataFormatName, "com.sun.media.imageioimpl.plugins.tiff.TIFFImageMetadataFormat", null, null ); } public String getDescription(Locale locale) { String desc = PackageUtil.getSpecificationTitle() + " TIFF Image Reader"; return desc; } public boolean canDecodeInput(Object input) throws IOException { if (!(input instanceof ImageInputStream)) { return false; } ImageInputStream stream = (ImageInputStream)input; byte[] b = new byte[4]; stream.mark(); stream.readFully(b); stream.reset(); return ((b[0] == (byte)0x49 && b[1] == (byte)0x49 && b[2] == (byte)0x2a && b[3] == (byte)0x00) || (b[0] == (byte)0x4d && b[1] == (byte)0x4d && b[2] == (byte)0x00 && b[3] == (byte)0x2a)); } public ImageReader createReaderInstance(Object extension) { return new TIFFImageReader(this); } public void onRegistration(ServiceRegistry registry, Class category) { if (registered) { return; } registered = true; } } jai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/tiff/TIFFPackBitsUtil.java0000664000175100017510000000731210203036165032233 0ustar tilletille/* * $RCSfile: TIFFPackBitsUtil.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.1 $ * $Date: 2005-02-11 05:01:49 $ * $State: Exp $ */ package com.sun.media.imageioimpl.plugins.tiff; import java.awt.Rectangle; import java.io.IOException; import javax.imageio.ImageReader; import com.sun.media.imageio.plugins.tiff.BaselineTIFFTagSet; import com.sun.media.imageio.plugins.tiff.TIFFTag; public class TIFFPackBitsUtil { private static final boolean debug = false; byte[] dstData = new byte[8192]; int dstIndex = 0; public TIFFPackBitsUtil() { } private void ensureCapacity(int bytesToAdd) { if (dstIndex + bytesToAdd > dstData.length) { byte[] newDstData = new byte[Math.max((int)(dstData.length*1.2f), dstIndex + bytesToAdd)]; System.arraycopy(dstData, 0, newDstData, 0, dstData.length); dstData = newDstData; } } public byte[] decode(byte[] srcData) throws IOException { int inIndex = 0; while (inIndex < srcData.length) { byte b = srcData[inIndex++]; if (b >= 0 && b <= 127) { // second test not needed? // Literal run packet ensureCapacity(b + 1); for (int i = 0; i < b + 1; i++) { dstData[dstIndex++] = srcData[inIndex++]; } } else if (b <= -1 && b >= -127) { // 2-byte encoded run packet byte repeat = srcData[inIndex++]; ensureCapacity(-b + 1); for (int i = 0; i < (-b + 1); i++) { dstData[dstIndex++] = repeat; } } else { // No-op packet, do nothing ++inIndex; } } byte[] newDstData = new byte[dstIndex]; System.arraycopy(dstData, 0, newDstData, 0, dstIndex); return newDstData; } } jai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/tiff/TIFFLZWUtil.java0000664000175100017510000001612510203036165031211 0ustar tilletille/* * $RCSfile: TIFFLZWUtil.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.1 $ * $Date: 2005-02-11 05:01:48 $ * $State: Exp $ */ package com.sun.media.imageioimpl.plugins.tiff; import java.awt.Rectangle; import java.io.IOException; import javax.imageio.IIOException; import javax.imageio.ImageReader; import com.sun.media.imageio.plugins.tiff.BaselineTIFFTagSet; import com.sun.media.imageio.plugins.tiff.TIFFTag; public class TIFFLZWUtil { private static final boolean debug = false; public TIFFLZWUtil() { } byte[] srcData; int srcIndex; byte[] dstData; int dstIndex = 0; byte stringTable[][]; int tableIndex, bitsToGet = 9; int predictor, samplesPerPixel; int nextData = 0; int nextBits = 0; private static final int andTable[] = { 511, 1023, 2047, 4095 }; public byte[] decode(byte[] data, int predictor, int samplesPerPixel, int width, int height) throws IOException { if (data[0] == (byte)0x00 && data[1] == (byte)0x01) { throw new IIOException("TIFF 5.0-style LZW compression is not supported!"); } this.srcData = data; this.srcIndex = 0; this.nextData = 0; this.nextBits = 0; this.dstData = new byte[8192]; this.dstIndex = 0; initializeStringTable(); int code, oldCode = 0; byte[] string; while ((code = getNextCode()) != 257) { if (code == 256) { initializeStringTable(); code = getNextCode(); if (code == 257) { break; } writeString(stringTable[code]); oldCode = code; } else { if (code < tableIndex) { string = stringTable[code]; writeString(string); addStringToTable(stringTable[oldCode], string[0]); oldCode = code; } else { string = stringTable[oldCode]; string = composeString(string, string[0]); writeString(string); addStringToTable(string); oldCode = code; } } } if (predictor == 2) { int count; for (int j = 0; j < height; j++) { count = samplesPerPixel * (j * width + 1); for (int i = samplesPerPixel; i < width * samplesPerPixel; i++) { dstData[count] += dstData[count - samplesPerPixel]; count++; } } } byte[] newDstData = new byte[dstIndex]; System.arraycopy(dstData, 0, newDstData, 0, dstIndex); return newDstData; } /** * Initialize the string table. */ public void initializeStringTable() { stringTable = new byte[4096][]; for (int i = 0; i < 256; i++) { stringTable[i] = new byte[1]; stringTable[i][0] = (byte)i; } tableIndex = 258; bitsToGet = 9; } private void ensureCapacity(int bytesToAdd) { if (dstIndex + bytesToAdd > dstData.length) { byte[] newDstData = new byte[Math.max((int)(dstData.length*1.2f), dstIndex + bytesToAdd)]; System.arraycopy(dstData, 0, newDstData, 0, dstData.length); dstData = newDstData; } } /** * Write out the string just uncompressed. */ public void writeString(byte string[]) { ensureCapacity(string.length); for (int i = 0; i < string.length; i++) { dstData[dstIndex++] = string[i]; } } /** * Add a new string to the string table. */ public void addStringToTable(byte oldString[], byte newString) { int length = oldString.length; byte string[] = new byte[length + 1]; System.arraycopy(oldString, 0, string, 0, length); string[length] = newString; // Add this new String to the table stringTable[tableIndex++] = string; if (tableIndex == 511) { bitsToGet = 10; } else if (tableIndex == 1023) { bitsToGet = 11; } else if (tableIndex == 2047) { bitsToGet = 12; } } /** * Add a new string to the string table. */ public void addStringToTable(byte string[]) { // Add this new String to the table stringTable[tableIndex++] = string; if (tableIndex == 511) { bitsToGet = 10; } else if (tableIndex == 1023) { bitsToGet = 11; } else if (tableIndex == 2047) { bitsToGet = 12; } } /** * Append newString to the end of oldString. */ public byte[] composeString(byte oldString[], byte newString) { int length = oldString.length; byte string[] = new byte[length + 1]; System.arraycopy(oldString, 0, string, 0, length); string[length] = newString; return string; } // Returns the next 9, 10, 11 or 12 bits public int getNextCode() { // Attempt to get the next code. The exception is caught to make // this robust to cases wherein the EndOfInformation code has been // omitted from a strip. Examples of such cases have been observed // in practice. try { nextData = (nextData << 8) | (srcData[srcIndex++] & 0xff); nextBits += 8; if (nextBits < bitsToGet) { nextData = (nextData << 8) | (srcData[srcIndex++] & 0xff); nextBits += 8; } int code = (nextData >> (nextBits - bitsToGet)) & andTable[bitsToGet - 9]; nextBits -= bitsToGet; return code; } catch (ArrayIndexOutOfBoundsException e) { // Strip not terminated as expected: return EndOfInformation code. return 257; } } } ././@LongLink0000000000000000000000000000015300000000000011564 Lustar rootrootjai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/tiff/TIFFDeflateDecompressor.javajai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/tiff/TIFFDeflateDecompresso0000664000175100017510000001241510203036165032525 0ustar tilletille/* * $RCSfile: TIFFDeflateDecompressor.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.1 $ * $Date: 2005-02-11 05:01:45 $ * $State: Exp $ */ package com.sun.media.imageioimpl.plugins.tiff; import java.io.IOException; import java.util.zip.DataFormatException; import java.util.zip.Inflater; import javax.imageio.IIOException; import com.sun.media.imageio.plugins.tiff.BaselineTIFFTagSet; import com.sun.media.imageio.plugins.tiff.TIFFDecompressor; public class TIFFDeflateDecompressor extends TIFFDecompressor { private static final boolean DEBUG = false; Inflater inflater = null; int predictor; public TIFFDeflateDecompressor(int predictor) throws IIOException { inflater = new Inflater(); if (predictor != BaselineTIFFTagSet.PREDICTOR_NONE && predictor != BaselineTIFFTagSet.PREDICTOR_HORIZONTAL_DIFFERENCING) { throw new IIOException("Illegal value for Predictor in " + "TIFF file"); } if(DEBUG) { System.out.println("Using horizontal differencing predictor"); } this.predictor = predictor; } public synchronized void decodeRaw(byte[] b, int dstOffset, int bitsPerPixel, int scanlineStride) throws IOException { // Check bitsPerSample. if (predictor == BaselineTIFFTagSet.PREDICTOR_HORIZONTAL_DIFFERENCING) { int len = bitsPerSample.length; for(int i = 0; i < len; i++) { if(bitsPerSample[i] != 8) { throw new IIOException (bitsPerSample[i] + "-bit samples "+ "are not supported for Horizontal "+ "differencing Predictor"); } } } // Seek to current tile data offset. stream.seek(offset); // Read the deflated data. byte[] srcData = new byte[byteCount]; stream.readFully(srcData); int bytesPerRow = (srcWidth*bitsPerPixel + 7)/8; byte[] buf; int bufOffset; if(bytesPerRow == scanlineStride) { buf = b; bufOffset = dstOffset; } else { buf = new byte[bytesPerRow*srcHeight]; bufOffset = 0; } // Set the input to the Inflater. inflater.setInput(srcData); // Inflate the data. try { inflater.inflate(buf, bufOffset, bytesPerRow*srcHeight); } catch(DataFormatException dfe) { throw new IIOException(I18N.getString("TIFFDeflateDecompressor0"), dfe); } // Reset the Inflater. inflater.reset(); if (predictor == BaselineTIFFTagSet.PREDICTOR_HORIZONTAL_DIFFERENCING) { for (int j = 0; j < srcHeight; j++) { int count = bufOffset + samplesPerPixel * (j * srcWidth + 1); for (int i=samplesPerPixel; i If tileWidth < 0, the results of this method * are undefined. If tileWidth == 0, an * ArithmeticException will be thrown. * * @throws ArithmeticException If tileWidth == 0. */ public static int XToTileX(int x, int tileGridXOffset, int tileWidth) { x -= tileGridXOffset; if (x < 0) { x += 1 - tileWidth; // force round to -infinity (ceiling) } return x/tileWidth; } /** * Converts a pixel's Y coordinate into a vertical tile index * relative to a given tile grid layout specified by its Y offset * and tile height. * *

If tileHeight < 0, the results of this method * are undefined. If tileHeight == 0, an * ArithmeticException will be thrown. * * @throws ArithmeticException If tileHeight == 0. */ public static int YToTileY(int y, int tileGridYOffset, int tileHeight) { y -= tileGridYOffset; if (y < 0) { y += 1 - tileHeight; // force round to -infinity (ceiling) } return y/tileHeight; } public TIFFImageWriter(ImageWriterSpi originatingProvider) { super(originatingProvider); } public ImageWriteParam getDefaultWriteParam() { return new TIFFImageWriteParam(getLocale()); } public void setOutput(Object output) { super.setOutput(output); if (output != null) { if (!(output instanceof ImageOutputStream)) { throw new IllegalArgumentException ("output not an ImageOutputStream!"); } this.stream = (ImageOutputStream)output; // // The output is expected to be positioned at a TIFF header // or at some arbitrary location which may or may not be // the EOF. In the former case the writer should be able // either to overwrite the existing sequence or append to it. // // Set the position of the header and the next available space. try { headerPosition = this.stream.getStreamPosition(); try { // Read byte order and magic number. byte[] b = new byte[4]; stream.readFully(b); // Check bytes for TIFF header. if((b[0] == (byte)0x49 && b[1] == (byte)0x49 && b[2] == (byte)0x2a && b[3] == (byte)0x00) || (b[0] == (byte)0x4d && b[1] == (byte)0x4d && b[2] == (byte)0x00 && b[3] == (byte)0x2a)) { // TIFF header. this.nextSpace = stream.length(); } else { // Neither TIFF header nor EOF: overwrite. this.nextSpace = headerPosition; } } catch(IOException io) { // thrown by readFully() // At EOF or not at a TIFF header. this.nextSpace = headerPosition; } stream.seek(headerPosition); } catch(IOException ioe) { // thrown by getStreamPosition() // Assume it's at zero. this.nextSpace = headerPosition = 0L; } } else { this.stream = null; } } public IIOMetadata getDefaultStreamMetadata(ImageWriteParam param) { return new TIFFStreamMetadata(); } public IIOMetadata getDefaultImageMetadata(ImageTypeSpecifier imageType, ImageWriteParam param) { List tagSets = new ArrayList(1); tagSets.add(BaselineTIFFTagSet.getInstance()); // XXX Should add Fax/EXIF/GeoTIFF TagSets? TIFFImageMetadata imageMetadata = new TIFFImageMetadata(tagSets); if(imageType != null) { TIFFImageMetadata im = (TIFFImageMetadata)convertImageMetadata(imageMetadata, imageType, param); if(im != null) { imageMetadata = im; } } return imageMetadata; } public IIOMetadata convertStreamMetadata(IIOMetadata inData, ImageWriteParam param) { // Check arguments. if(inData == null) { throw new IllegalArgumentException("inData == null!"); } // Note: param is irrelevant as it does not contain byte order. TIFFStreamMetadata outData = null; if(inData instanceof TIFFStreamMetadata) { outData = new TIFFStreamMetadata(); outData.byteOrder = ((TIFFStreamMetadata)inData).byteOrder; return outData; } else if(Arrays.asList(inData.getMetadataFormatNames()).contains( TIFFStreamMetadata.nativeMetadataFormatName)) { outData = new TIFFStreamMetadata(); String format = TIFFStreamMetadata.nativeMetadataFormatName; try { outData.mergeTree(format, inData.getAsTree(format)); } catch(IIOInvalidTreeException e) { // XXX Warning } } return outData; } public IIOMetadata convertImageMetadata(IIOMetadata inData, ImageTypeSpecifier imageType, ImageWriteParam param) { // Check arguments. if(inData == null) { throw new IllegalArgumentException("inData == null!"); } if(imageType == null) { throw new IllegalArgumentException("imageType == null!"); } TIFFImageMetadata outData = null; // Obtain a TIFFImageMetadata object. if(inData instanceof TIFFImageMetadata) { // Create a new metadata object from a clone of the input IFD. TIFFIFD inIFD = ((TIFFImageMetadata)inData).getRootIFD(); outData = new TIFFImageMetadata(inIFD.getShallowClone()); } else if(Arrays.asList(inData.getMetadataFormatNames()).contains( TIFFImageMetadata.nativeMetadataFormatName)) { // Initialize from the native metadata form of the input tree. try { outData = convertNativeImageMetadata(inData); } catch(IIOInvalidTreeException e) { // XXX Warning } } else if(inData.isStandardMetadataFormatSupported()) { // Initialize from the standard metadata form of the input tree. try { outData = convertStandardImageMetadata(inData); } catch(IIOInvalidTreeException e) { // XXX Warning } } // Update the metadata per the image type and param. if(outData != null) { TIFFImageWriter bogusWriter = new TIFFImageWriter(this.originatingProvider); bogusWriter.imageMetadata = outData; bogusWriter.param = param; SampleModel sm = imageType.getSampleModel(); try { bogusWriter.setupMetadata(imageType.getColorModel(), sm, sm.getWidth(), sm.getHeight()); return bogusWriter.imageMetadata; } catch(IIOException e) { // XXX Warning return null; } } return outData; } /** * Converts a standard javax_imageio_1.0 tree to a * TIFFImageMetadata object. * * @param inData The metadata object. * @return a TIFFImageMetadata or null if * the standard tree derived from the input object is null. * @throws IllegalArgumentException if inData is * null or does not support the standard metadata format. * @throws IIOInvalidTreeException if inData generates an * invalid standard metadata tree. */ private TIFFImageMetadata convertStandardImageMetadata(IIOMetadata inData) throws IIOInvalidTreeException { if(inData == null) { throw new IllegalArgumentException("inData == null!"); } else if(!inData.isStandardMetadataFormatSupported()) { throw new IllegalArgumentException ("inData does not support standard metadata format!"); } TIFFImageMetadata outData = null; String formatName = IIOMetadataFormatImpl.standardMetadataFormatName; Node tree = inData.getAsTree(formatName); if (tree != null) { List tagSets = new ArrayList(1); tagSets.add(BaselineTIFFTagSet.getInstance()); outData = new TIFFImageMetadata(tagSets); outData.setFromTree(formatName, tree); } return outData; } /** * Converts a native * com_sun_media_imageio_plugins_tiff_image_1.0 tree to a * TIFFImageMetadata object. * * @param inData The metadata object. * @return a TIFFImageMetadata or null if * the native tree derived from the input object is null. * @throws IllegalArgumentException if inData is * null or does not support the native metadata format. * @throws IIOInvalidTreeException if inData generates an * invalid native metadata tree. */ private TIFFImageMetadata convertNativeImageMetadata(IIOMetadata inData) throws IIOInvalidTreeException { if(inData == null) { throw new IllegalArgumentException("inData == null!"); } else if(!Arrays.asList(inData.getMetadataFormatNames()).contains( TIFFImageMetadata.nativeMetadataFormatName)) { throw new IllegalArgumentException ("inData does not support native metadata format!"); } TIFFImageMetadata outData = null; String formatName = TIFFImageMetadata.nativeMetadataFormatName; Node tree = inData.getAsTree(formatName); if (tree != null) { List tagSets = new ArrayList(1); tagSets.add(BaselineTIFFTagSet.getInstance()); outData = new TIFFImageMetadata(tagSets); outData.setFromTree(formatName, tree); } return outData; } /** * Sets up the output metadata adding, removing, and overriding fields * as needed. The destination image dimensions are provided as parameters * because these might differ from those of the source due to subsampling. * * @param cm The ColorModel of the image being written. * @param sm The SampleModel of the image being written. * @param destWidth The width of the written image after subsampling. * @param destHeight The height of the written image after subsampling. */ void setupMetadata(ColorModel cm, SampleModel sm, int destWidth, int destHeight) throws IIOException { // Get initial IFD from metadata // Always emit these fields: // // Override values from metadata: // // planarConfiguration -> chunky (planar not supported on output) // // Override values from metadata with image-derived values: // // bitsPerSample (if not bilivel) // colorMap (if palette color) // photometricInterpretation (derive from image) // imageLength // imageWidth // // rowsPerStrip \ / tileLength // stripOffsets | OR | tileOffsets // stripByteCounts / | tileByteCounts // \ tileWidth // // // Override values from metadata with write param values: // // compression // Use values from metadata if present for these fields, // otherwise use defaults: // // resolutionUnit // XResolution (take from metadata if present) // YResolution // rowsPerStrip // sampleFormat TIFFIFD rootIFD = imageMetadata.getRootIFD(); BaselineTIFFTagSet base = BaselineTIFFTagSet.getInstance(); // If PlanarConfiguration field present, set value to chunky. TIFFField f = rootIFD.getTIFFField(BaselineTIFFTagSet.TAG_PLANAR_CONFIGURATION); if(f != null && f.getAsInt(0) != BaselineTIFFTagSet.PLANAR_CONFIGURATION_CHUNKY) { // XXX processWarningOccurred() TIFFField planarConfigurationField = new TIFFField(base.getTag(BaselineTIFFTagSet.TAG_PLANAR_CONFIGURATION), BaselineTIFFTagSet.PLANAR_CONFIGURATION_CHUNKY); rootIFD.addTIFFField(planarConfigurationField); } char[] extraSamples = null; this.photometricInterpretation = -1; boolean forcePhotometricInterpretation = false; f = rootIFD.getTIFFField(BaselineTIFFTagSet.TAG_PHOTOMETRIC_INTERPRETATION); if (f != null) { photometricInterpretation = f.getAsInt(0); if(photometricInterpretation == BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_PALETTE_COLOR && !(cm instanceof IndexColorModel)) { photometricInterpretation = -1; } else { forcePhotometricInterpretation = true; } } // f = rootIFD.getTIFFField(BaselineTIFFTagSet.TAG_EXTRA_SAMPLES); // if (f != null) { // extraSamples = f.getAsChars(); // } // f = rootIFD.getTIFFField(BaselineTIFFTagSet.TAG_BITS_PER_SAMPLE); // if (f != null) { // bitsPerSample = f.getAsChars(); // } int[] sampleSize = sm.getSampleSize(); int numBands = sm.getNumBands(); int numExtraSamples = 0; // Check that numBands > 1 here because TIFF requires that // SamplesPerPixel = numBands + numExtraSamples and numBands // cannot be zero. if (numBands > 1 && cm != null && cm.hasAlpha()) { --numBands; numExtraSamples = 1; extraSamples = new char[1]; if (cm.isAlphaPremultiplied()) { extraSamples[0] = BaselineTIFFTagSet.EXTRA_SAMPLES_ASSOCIATED_ALPHA; } else { extraSamples[0] = BaselineTIFFTagSet.EXTRA_SAMPLES_UNASSOCIATED_ALPHA; } } if (numBands == 3) { this.nativePhotometricInterpretation = BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_RGB; if (photometricInterpretation == -1) { photometricInterpretation = BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_RGB; } } else if (sm.getNumBands() == 1 && cm instanceof IndexColorModel) { IndexColorModel icm = (IndexColorModel)cm; int r0 = icm.getRed(0); int r1 = icm.getRed(1); if (icm.getMapSize() == 2 && (r0 == icm.getGreen(0)) && (r0 == icm.getBlue(0)) && (r1 == icm.getGreen(1)) && (r1 == icm.getBlue(1)) && (r0 == 0 || r0 == 255) && (r1 == 0 || r1 == 255) && (r0 != r1)) { // Black/white image if (r0 == 0) { nativePhotometricInterpretation = BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_BLACK_IS_ZERO; } else { nativePhotometricInterpretation = BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_WHITE_IS_ZERO; } // If photometricInterpretation is already set to // WhiteIsZero or BlackIsZero, leave it alone if (photometricInterpretation != BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_BLACK_IS_ZERO && photometricInterpretation != BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_WHITE_IS_ZERO) { photometricInterpretation = r0 == 0 ? BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_BLACK_IS_ZERO : BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_WHITE_IS_ZERO; } } else { nativePhotometricInterpretation = photometricInterpretation = BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_PALETTE_COLOR; } } else { if(cm != null) { switch(cm.getColorSpace().getType()) { case ColorSpace.TYPE_Lab: nativePhotometricInterpretation = BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_CIELAB; break; case ColorSpace.TYPE_YCbCr: nativePhotometricInterpretation = BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_Y_CB_CR; break; case ColorSpace.TYPE_CMYK: nativePhotometricInterpretation = BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_CMYK; break; default: nativePhotometricInterpretation = BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_BLACK_IS_ZERO; } } else { nativePhotometricInterpretation = BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_BLACK_IS_ZERO; } if (photometricInterpretation == -1) { photometricInterpretation = nativePhotometricInterpretation; } } // Set the compressor and color converter. this.compressor = null; this.colorConverter = null; if (param instanceof TIFFImageWriteParam) { TIFFImageWriteParam tparam = (TIFFImageWriteParam)param; if(tparam.getCompressionMode() == tparam.MODE_EXPLICIT) { compressor = tparam.getTIFFCompressor(); String compressionType = param.getCompressionType(); if(compressor != null && !compressor.getCompressionType().equals(compressionType)) { // Unset the TIFFCompressor if its compression type is // not the one selected. compressor = null; } } else { // Compression mode not MODE_EXPLICIT. compressor = null; } colorConverter = tparam.getColorConverter(); if (colorConverter != null) { photometricInterpretation = tparam.getPhotometricInterpretation(); } } // Emit compression tag int compressionMode = param instanceof TIFFImageWriteParam ? param.getCompressionMode() : ImageWriteParam.MODE_DEFAULT; switch(compressionMode) { case ImageWriteParam.MODE_EXPLICIT: { String compressionType = param.getCompressionType(); if (compressionType == null) { this.compression = BaselineTIFFTagSet.COMPRESSION_NONE; } else { // Determine corresponding compression tag value. int len = compressionTypes.length; for (int i = 0; i < len; i++) { if (compressionType.equals(compressionTypes[i])) { this.compression = compressionNumbers[i]; } } } // Ensure the compressor, if any, matches compression setting // with the precedence described in TIFFImageWriteParam. if(compressor != null && compressor.getCompressionTagValue() != this.compression) { // Does not match: unset the compressor. compressor = null; } } break; case ImageWriteParam.MODE_COPY_FROM_METADATA: { TIFFField compField = rootIFD.getTIFFField(BaselineTIFFTagSet.TAG_COMPRESSION); if(compField != null) { this.compression = compField.getAsInt(0); break; } } case ImageWriteParam.MODE_DEFAULT: case ImageWriteParam.MODE_DISABLED: default: this.compression = BaselineTIFFTagSet.COMPRESSION_NONE; } TIFFField predictorField = rootIFD.getTIFFField(BaselineTIFFTagSet.TAG_PREDICTOR); if (predictorField != null) { this.predictor = predictorField.getAsInt(0); // We only support Horizontal Predictor for a bitDepth of 8 if (sampleSize[0] != 8 || // Check the value of the tag for validity (predictor != BaselineTIFFTagSet.PREDICTOR_NONE && predictor != BaselineTIFFTagSet.PREDICTOR_HORIZONTAL_DIFFERENCING)) { // XXX processWarningOccured ??? // Set to default predictor = BaselineTIFFTagSet.PREDICTOR_NONE; // Emit this changed predictor value to metadata TIFFField newPredictorField = new TIFFField(base.getTag(BaselineTIFFTagSet.TAG_PREDICTOR), predictor); rootIFD.addTIFFField(newPredictorField); } // XXX Do we need to ensure that predictor is not passed on if // the compression is not either Deflate or LZW? } TIFFField compressionField = new TIFFField(base.getTag(BaselineTIFFTagSet.TAG_COMPRESSION), compression); rootIFD.addTIFFField(compressionField); // Set EXIF flag. Note that there is no way to determine definitively // when an uncompressed thumbnail is being written as the EXIF IFD // pointer field is optional for thumbnails. boolean isEXIF = false; if(numBands == 3 && sampleSize[0] == 8 && sampleSize[1] == 8 && sampleSize[2] == 8) { // Three bands with 8 bits per sample. if(rootIFD.getTIFFField(EXIFParentTIFFTagSet.TAG_EXIF_IFD_POINTER) != null) { // EXIF IFD pointer present. if(compression == BaselineTIFFTagSet.COMPRESSION_NONE && (photometricInterpretation == BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_RGB || photometricInterpretation == BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_Y_CB_CR)) { // Uncompressed RGB or YCbCr. isEXIF = true; } else if(compression == BaselineTIFFTagSet.COMPRESSION_OLD_JPEG) { // Compressed. isEXIF = true; } } else if(compressionMode == ImageWriteParam.MODE_EXPLICIT && EXIF_JPEG_COMPRESSION_TYPE.equals (param.getCompressionType())) { // EXIF IFD pointer absent but EXIF JPEG compression set. isEXIF = true; } } // Initialize JPEG interchange format flag which is used to // indicate that the image is stored as a single JPEG stream. // This flag is separated from the 'isEXIF' flag in case JPEG // interchange format is eventually supported for non-EXIF images. boolean isJPEGInterchange = isEXIF && compression == BaselineTIFFTagSet.COMPRESSION_OLD_JPEG; if (compressor == null) { if (compression == BaselineTIFFTagSet.COMPRESSION_CCITT_RLE) { if(PackageUtil.isCodecLibAvailable()) { try { compressor = new TIFFCodecLibRLECompressor(); if(DEBUG) { System.out.println ("Using codecLib RLE compressor"); } } catch(RuntimeException e) { if(DEBUG) { System.out.println(e); } } } if(compressor == null) { compressor = new TIFFRLECompressor(); if(DEBUG) { System.out.println("Using Java RLE compressor"); } } if (!forcePhotometricInterpretation) { photometricInterpretation = BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_WHITE_IS_ZERO; } } else if (compression == BaselineTIFFTagSet.COMPRESSION_CCITT_T_4) { if(PackageUtil.isCodecLibAvailable()) { try { compressor = new TIFFCodecLibT4Compressor(); if(DEBUG) { System.out.println ("Using codecLib T.4 compressor"); } } catch(RuntimeException e) { if(DEBUG) { System.out.println(e); } } } if(compressor == null) { compressor = new TIFFT4Compressor(); if(DEBUG) { System.out.println("Using Java T.4 compressor"); } } if (!forcePhotometricInterpretation) { photometricInterpretation = BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_WHITE_IS_ZERO; } } else if (compression == BaselineTIFFTagSet.COMPRESSION_CCITT_T_6) { if(PackageUtil.isCodecLibAvailable()) { try { compressor = new TIFFCodecLibT6Compressor(); if(DEBUG) { System.out.println ("Using codecLib T.6 compressor"); } } catch(RuntimeException e) { if(DEBUG) { System.out.println(e); } } } if(compressor == null) { compressor = new TIFFT6Compressor(); if(DEBUG) { System.out.println("Using Java T.6 compressor"); } } if (!forcePhotometricInterpretation) { photometricInterpretation = BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_WHITE_IS_ZERO; } } else if (compression == BaselineTIFFTagSet.COMPRESSION_LZW) { compressor = new TIFFLZWCompressor(predictor); } else if (compression == BaselineTIFFTagSet.COMPRESSION_OLD_JPEG) { if(isEXIF) { compressor = new TIFFEXIFJPEGCompressor(param); } else { throw new IIOException ("Old JPEG compression not supported!"); } } else if (compression == BaselineTIFFTagSet.COMPRESSION_JPEG) { if(numBands == 3 && sampleSize[0] == 8 && sampleSize[1] == 8 && sampleSize[2] == 8) { photometricInterpretation = BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_Y_CB_CR; } else if(numBands == 1 && sampleSize[0] == 8) { photometricInterpretation = BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_BLACK_IS_ZERO; } else { throw new IIOException ("JPEG compression supported for 1- and 3-band byte images only!"); } compressor = new TIFFJPEGCompressor(param); } else if (compression == BaselineTIFFTagSet.COMPRESSION_ZLIB) { compressor = new TIFFZLibCompressor(param, predictor); } else if (compression == BaselineTIFFTagSet.COMPRESSION_PACKBITS) { compressor = new TIFFPackBitsCompressor(); } else if (compression == BaselineTIFFTagSet.COMPRESSION_DEFLATE) { compressor = new TIFFDeflateCompressor(param, predictor); } else { // Determine inverse fill setting. f = rootIFD.getTIFFField(BaselineTIFFTagSet.TAG_FILL_ORDER); boolean inverseFill = (f != null && f.getAsInt(0) == 2); if(inverseFill) { compressor = new TIFFLSBCompressor(); } else { compressor = new TIFFNullCompressor(); } } // compression == ? } // compressor == null if(DEBUG) { if(param != null && param.getCompressionMode() == param.MODE_EXPLICIT) { System.out.println("compressionType = "+ param.getCompressionType()); } if(compressor != null) { System.out.println("compressor = "+ compressor.getClass().getName()); } } if (colorConverter == null) { if(cm != null && cm.getColorSpace().getType() == ColorSpace.TYPE_RGB) { // // Perform color conversion only if image has RGB color space. // if (photometricInterpretation == BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_Y_CB_CR && compression != BaselineTIFFTagSet.COMPRESSION_JPEG) { // // Convert RGB to YCbCr only if compression type is not // JPEG in which case this is handled implicitly by the // compressor. // colorConverter = new TIFFYCbCrColorConverter(imageMetadata); } else if (photometricInterpretation == BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_CIELAB) { colorConverter = new TIFFCIELabColorConverter(); } } } // // Cannot at this time do YCbCr subsampling so set the // YCbCrSubsampling field value to [1, 1] and the YCbCrPositioning // field value to "cosited". // if(photometricInterpretation == BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_Y_CB_CR && compression != BaselineTIFFTagSet.COMPRESSION_JPEG) { // Remove old subsampling and positioning fields. rootIFD.removeTIFFField (BaselineTIFFTagSet.TAG_Y_CB_CR_SUBSAMPLING); rootIFD.removeTIFFField (BaselineTIFFTagSet.TAG_Y_CB_CR_POSITIONING); // Add unity chrominance subsampling factors. rootIFD.addTIFFField (new TIFFField (base.getTag(BaselineTIFFTagSet.TAG_Y_CB_CR_SUBSAMPLING), TIFFTag.TIFF_SHORT, 2, new char[] {(char)1, (char)1})); // Add cosited positioning. rootIFD.addTIFFField (new TIFFField (base.getTag(BaselineTIFFTagSet.TAG_Y_CB_CR_POSITIONING), TIFFTag.TIFF_SHORT, 1, new char[] { (char)BaselineTIFFTagSet.Y_CB_CR_POSITIONING_COSITED })); } TIFFField photometricInterpretationField = new TIFFField( base.getTag(BaselineTIFFTagSet.TAG_PHOTOMETRIC_INTERPRETATION), photometricInterpretation); rootIFD.addTIFFField(photometricInterpretationField); this.bitsPerSample = new char[numBands + numExtraSamples]; this.bitDepth = 0; for (int i = 0; i < numBands; i++) { this.bitDepth = Math.max(bitDepth, sampleSize[i]); } if (bitDepth == 3) { bitDepth = 4; } else if (bitDepth > 4 && bitDepth < 8) { bitDepth = 8; } else if (bitDepth > 8 && bitDepth < 16) { bitDepth = 16; } else if (bitDepth > 16) { bitDepth = 32; } for (int i = 0; i < bitsPerSample.length; i++) { bitsPerSample[i] = (char)bitDepth; } // Emit BitsPerSample. If the image is bilevel, emit if and only // if already in the metadata and correct (count and value == 1). if (bitsPerSample.length != 1 || bitsPerSample[0] != 1) { TIFFField bitsPerSampleField = new TIFFField( base.getTag(BaselineTIFFTagSet.TAG_BITS_PER_SAMPLE), TIFFTag.TIFF_SHORT, bitsPerSample.length, bitsPerSample); rootIFD.addTIFFField(bitsPerSampleField); } else { // bitsPerSample.length == 1 && bitsPerSample[0] == 1 TIFFField bitsPerSampleField = rootIFD.getTIFFField(BaselineTIFFTagSet.TAG_BITS_PER_SAMPLE); if(bitsPerSampleField != null) { int[] bps = bitsPerSampleField.getAsInts(); if(bps == null || bps.length != 1 || bps[0] != 1) { rootIFD.removeTIFFField(BaselineTIFFTagSet.TAG_BITS_PER_SAMPLE); } } } // Prepare SampleFormat field. f = rootIFD.getTIFFField(BaselineTIFFTagSet.TAG_SAMPLE_FORMAT); if(f == null && (bitDepth == 16 || bitDepth == 32)) { // Set up default content for 16- and 32-bit cases. char sampleFormatValue; int dataType = sm.getDataType(); if(bitDepth == 16 && dataType == DataBuffer.TYPE_USHORT) { sampleFormatValue = (char)BaselineTIFFTagSet.SAMPLE_FORMAT_UNSIGNED_INTEGER; } else if(bitDepth == 32 && dataType == DataBuffer.TYPE_FLOAT) { sampleFormatValue = (char)BaselineTIFFTagSet.SAMPLE_FORMAT_FLOATING_POINT; } else { sampleFormatValue = BaselineTIFFTagSet.SAMPLE_FORMAT_SIGNED_INTEGER; } this.sampleFormat = (int)sampleFormatValue; char[] sampleFormatArray = new char[bitsPerSample.length]; Arrays.fill(sampleFormatArray, sampleFormatValue); // Update the metadata. TIFFTag sampleFormatTag = base.getTag(BaselineTIFFTagSet.TAG_SAMPLE_FORMAT); TIFFField sampleFormatField = new TIFFField(sampleFormatTag, TIFFTag.TIFF_SHORT, sampleFormatArray.length, sampleFormatArray); rootIFD.addTIFFField(sampleFormatField); } else if(f != null) { // Get whatever was provided. sampleFormat = f.getAsInt(0); } else { // Set default value for internal use only. sampleFormat = BaselineTIFFTagSet.SAMPLE_FORMAT_UNDEFINED; } if (extraSamples != null) { TIFFField extraSamplesField = new TIFFField( base.getTag(BaselineTIFFTagSet.TAG_EXTRA_SAMPLES), TIFFTag.TIFF_SHORT, extraSamples.length, extraSamples); rootIFD.addTIFFField(extraSamplesField); } else { rootIFD.removeTIFFField(BaselineTIFFTagSet.TAG_EXTRA_SAMPLES); } TIFFField samplesPerPixelField = new TIFFField( base.getTag(BaselineTIFFTagSet.TAG_SAMPLES_PER_PIXEL), bitsPerSample.length); rootIFD.addTIFFField(samplesPerPixelField); // Emit ColorMap if image is of palette color type if (photometricInterpretation == BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_PALETTE_COLOR && cm instanceof IndexColorModel) { char[] colorMap = new char[3*(1 << bitsPerSample[0])]; IndexColorModel icm = (IndexColorModel)cm; // mapSize is determined by BitsPerSample, not by incoming ICM. int mapSize = 1 << bitsPerSample[0]; int indexBound = Math.min(mapSize, icm.getMapSize()); for (int i = 0; i < indexBound; i++) { colorMap[i] = (char)((icm.getRed(i)*65535)/255); colorMap[mapSize + i] = (char)((icm.getGreen(i)*65535)/255); colorMap[2*mapSize + i] = (char)((icm.getBlue(i)*65535)/255); } TIFFField colorMapField = new TIFFField( base.getTag(BaselineTIFFTagSet.TAG_COLOR_MAP), TIFFTag.TIFF_SHORT, colorMap.length, colorMap); rootIFD.addTIFFField(colorMapField); } else { rootIFD.removeTIFFField(BaselineTIFFTagSet.TAG_COLOR_MAP); } // Emit ICCProfile if there is no ICCProfile field already in the // metadata and the ColorSpace is non-standard ICC. if(cm != null && rootIFD.getTIFFField(BaselineTIFFTagSet.TAG_ICC_PROFILE) == null && ImageUtil.isNonStandardICCColorSpace(cm.getColorSpace())) { ICC_ColorSpace iccColorSpace = (ICC_ColorSpace)cm.getColorSpace(); byte[] iccProfileData = iccColorSpace.getProfile().getData(); TIFFField iccProfileField = new TIFFField(base.getTag(BaselineTIFFTagSet.TAG_ICC_PROFILE), TIFFTag.TIFF_UNDEFINED, iccProfileData.length, iccProfileData); rootIFD.addTIFFField(iccProfileField); } // Always emit XResolution and YResolution. TIFFField XResolutionField = rootIFD.getTIFFField(BaselineTIFFTagSet.TAG_X_RESOLUTION); TIFFField YResolutionField = rootIFD.getTIFFField(BaselineTIFFTagSet.TAG_Y_RESOLUTION); if(XResolutionField == null && YResolutionField == null) { long[][] resRational = new long[1][2]; resRational[0] = new long[2]; TIFFField ResolutionUnitField = rootIFD.getTIFFField(BaselineTIFFTagSet.TAG_RESOLUTION_UNIT); // Don't force dimensionless if one of the other dimensional // quantities is present. if(ResolutionUnitField == null && rootIFD.getTIFFField(BaselineTIFFTagSet.TAG_X_POSITION) == null && rootIFD.getTIFFField(BaselineTIFFTagSet.TAG_Y_POSITION) == null) { // Set resolution to unit and units to dimensionless. resRational[0][0] = 1; resRational[0][1] = 1; ResolutionUnitField = new TIFFField(rootIFD.getTag (BaselineTIFFTagSet.TAG_RESOLUTION_UNIT), BaselineTIFFTagSet.RESOLUTION_UNIT_NONE); rootIFD.addTIFFField(ResolutionUnitField); } else { // Set resolution to a value which would make the maximum // image dimension equal to 4 inches as arbitrarily stated // in the description of ResolutionUnit in the TIFF 6.0 // specification. If the ResolutionUnit field specifies // "none" then set the resolution to unity (1/1). int resolutionUnit = ResolutionUnitField != null ? ResolutionUnitField.getAsInt(0) : BaselineTIFFTagSet.RESOLUTION_UNIT_INCH; int maxDimension = Math.max(destWidth, destHeight); switch(resolutionUnit) { case BaselineTIFFTagSet.RESOLUTION_UNIT_INCH: resRational[0][0] = maxDimension; resRational[0][1] = 4; break; case BaselineTIFFTagSet.RESOLUTION_UNIT_CENTIMETER: resRational[0][0] = 100L*maxDimension; // divide out 100 resRational[0][1] = 4*254; // 2.54 cm/inch * 100 break; default: resRational[0][0] = 1; resRational[0][1] = 1; } } XResolutionField = new TIFFField(rootIFD.getTag(BaselineTIFFTagSet.TAG_X_RESOLUTION), TIFFTag.TIFF_RATIONAL, 1, resRational); rootIFD.addTIFFField(XResolutionField); YResolutionField = new TIFFField(rootIFD.getTag(BaselineTIFFTagSet.TAG_Y_RESOLUTION), TIFFTag.TIFF_RATIONAL, 1, resRational); rootIFD.addTIFFField(YResolutionField); } else if(XResolutionField == null && YResolutionField != null) { // Set XResolution to YResolution. long[] yResolution = (long[])YResolutionField.getAsRational(0).clone(); XResolutionField = new TIFFField(rootIFD.getTag(BaselineTIFFTagSet.TAG_X_RESOLUTION), TIFFTag.TIFF_RATIONAL, 1, yResolution); rootIFD.addTIFFField(XResolutionField); } else if(XResolutionField != null && YResolutionField == null) { // Set YResolution to XResolution. long[] xResolution = (long[])XResolutionField.getAsRational(0).clone(); YResolutionField = new TIFFField(rootIFD.getTag(BaselineTIFFTagSet.TAG_Y_RESOLUTION), TIFFTag.TIFF_RATIONAL, 1, xResolution); rootIFD.addTIFFField(YResolutionField); } // Set mandatory fields, overriding metadata passed in int width = destWidth; TIFFField imageWidthField = new TIFFField(base.getTag(BaselineTIFFTagSet.TAG_IMAGE_WIDTH), width); rootIFD.addTIFFField(imageWidthField); int height = destHeight; TIFFField imageLengthField = new TIFFField(base.getTag(BaselineTIFFTagSet.TAG_IMAGE_LENGTH), height); rootIFD.addTIFFField(imageLengthField); // Determine rowsPerStrip int rowsPerStrip; TIFFField rowsPerStripField = rootIFD.getTIFFField(BaselineTIFFTagSet.TAG_ROWS_PER_STRIP); if (rowsPerStripField != null) { rowsPerStrip = rowsPerStripField.getAsInt(0); if(rowsPerStrip < 0) { rowsPerStrip = height; } } else { int bitsPerPixel = bitDepth*(numBands + numExtraSamples); int bytesPerRow = (bitsPerPixel*width + 7)/8; rowsPerStrip = Math.max(Math.max(DEFAULT_BYTES_PER_STRIP/bytesPerRow, 1), 8); } rowsPerStrip = Math.min(rowsPerStrip, height); // Tiling flag. boolean useTiling = false; // Analyze tiling parameters int tilingMode = param instanceof TIFFImageWriteParam ? param.getTilingMode() : ImageWriteParam.MODE_DEFAULT; if (tilingMode == ImageWriteParam.MODE_DISABLED || tilingMode == ImageWriteParam.MODE_DEFAULT) { this.tileWidth = width; this.tileLength = rowsPerStrip; useTiling = false; } else if (tilingMode == ImageWriteParam.MODE_EXPLICIT) { tileWidth = param.getTileWidth(); tileLength = param.getTileHeight(); useTiling = true; } else if (tilingMode == ImageWriteParam.MODE_COPY_FROM_METADATA) { f = rootIFD.getTIFFField(BaselineTIFFTagSet.TAG_TILE_WIDTH); if (f == null) { tileWidth = width; useTiling = false; } else { tileWidth = f.getAsInt(0); useTiling = true; } f = rootIFD.getTIFFField(BaselineTIFFTagSet.TAG_TILE_LENGTH); if (f == null) { tileLength = rowsPerStrip; } else { tileLength = f.getAsInt(0); useTiling = true; } } else { throw new IIOException("Illegal value of tilingMode!"); } if(compression == BaselineTIFFTagSet.COMPRESSION_JPEG) { // Reset tile size per TTN2 spec for JPEG compression. int subX; int subY; if(numBands == 1) { subX = subY = 1; } else { subX = subY = TIFFJPEGCompressor.CHROMA_SUBSAMPLING; } if(useTiling) { int MCUMultipleX = 8*subX; int MCUMultipleY = 8*subY; tileWidth = Math.max(MCUMultipleX*((tileWidth + MCUMultipleX/2)/MCUMultipleX), MCUMultipleX); tileLength = Math.max(MCUMultipleY*((tileLength + MCUMultipleY/2)/MCUMultipleY), MCUMultipleY); } else if(rowsPerStrip < height) { int MCUMultiple = 8*Math.max(subX, subY); rowsPerStrip = tileLength = Math.max(MCUMultiple*((tileLength + MCUMultiple/2)/MCUMultiple), MCUMultiple); } } else if(isJPEGInterchange) { // Force tile size to equal image size. tileWidth = width; tileLength = height; } else if(useTiling) { // Round tile size to multiple of 16 per TIFF 6.0 specification // (see pages 67-68 of version 6.0.1 from Adobe). int tileWidthRemainder = tileWidth % 16; if(tileWidthRemainder != 0) { // Round to nearest multiple of 16 not less than 16. tileWidth = Math.max(16*((tileWidth + 8)/16), 16); // XXX insert processWarningOccurred(int,String); } int tileLengthRemainder = tileLength % 16; if(tileLengthRemainder != 0) { // Round to nearest multiple of 16 not less than 16. tileLength = Math.max(16*((tileLength + 8)/16), 16); // XXX insert processWarningOccurred(int,String); } } this.tilesAcross = (width + tileWidth - 1)/tileWidth; this.tilesDown = (height + tileLength - 1)/tileLength; if (!useTiling) { this.isTiled = false; rootIFD.removeTIFFField(BaselineTIFFTagSet.TAG_TILE_WIDTH); rootIFD.removeTIFFField(BaselineTIFFTagSet.TAG_TILE_LENGTH); rootIFD.removeTIFFField(BaselineTIFFTagSet.TAG_TILE_OFFSETS); rootIFD.removeTIFFField(BaselineTIFFTagSet.TAG_TILE_BYTE_COUNTS); rowsPerStripField = new TIFFField(base.getTag(BaselineTIFFTagSet.TAG_ROWS_PER_STRIP), rowsPerStrip); rootIFD.addTIFFField(rowsPerStripField); TIFFField stripOffsetsField = new TIFFField( base.getTag(BaselineTIFFTagSet.TAG_STRIP_OFFSETS), TIFFTag.TIFF_LONG, tilesDown); rootIFD.addTIFFField(stripOffsetsField); TIFFField stripByteCountsField = new TIFFField( base.getTag(BaselineTIFFTagSet.TAG_STRIP_BYTE_COUNTS), TIFFTag.TIFF_LONG, tilesDown); rootIFD.addTIFFField(stripByteCountsField); } else { this.isTiled = true; rootIFD.removeTIFFField(BaselineTIFFTagSet.TAG_ROWS_PER_STRIP); rootIFD.removeTIFFField(BaselineTIFFTagSet.TAG_STRIP_OFFSETS); rootIFD.removeTIFFField(BaselineTIFFTagSet.TAG_STRIP_BYTE_COUNTS); TIFFField tileWidthField = new TIFFField(base.getTag(BaselineTIFFTagSet.TAG_TILE_WIDTH), tileWidth); rootIFD.addTIFFField(tileWidthField); TIFFField tileLengthField = new TIFFField(base.getTag(BaselineTIFFTagSet.TAG_TILE_LENGTH), tileLength); rootIFD.addTIFFField(tileLengthField); TIFFField tileOffsetsField = new TIFFField( base.getTag(BaselineTIFFTagSet.TAG_TILE_OFFSETS), TIFFTag.TIFF_LONG, tilesDown*tilesAcross); rootIFD.addTIFFField(tileOffsetsField); TIFFField tileByteCountsField = new TIFFField( base.getTag(BaselineTIFFTagSet.TAG_TILE_BYTE_COUNTS), TIFFTag.TIFF_LONG, tilesDown*tilesAcross); rootIFD.addTIFFField(tileByteCountsField); } if(isEXIF) { // // Ensure presence of mandatory fields and absence of prohibited // fields and those that duplicate information in JPEG marker // segments per tables 14-18 of the EXIF 2.2 specification. // // If an empty image is being written or inserted then infer // that the primary IFD is being set up. boolean isPrimaryIFD = isEncodingEmpty(); // Handle TIFF fields in order of increasing tag number. if(compression == BaselineTIFFTagSet.COMPRESSION_OLD_JPEG) { // ImageWidth rootIFD.removeTIFFField(BaselineTIFFTagSet.TAG_IMAGE_WIDTH); // ImageLength rootIFD.removeTIFFField(BaselineTIFFTagSet.TAG_IMAGE_LENGTH); // BitsPerSample rootIFD.removeTIFFField(BaselineTIFFTagSet.TAG_BITS_PER_SAMPLE); // Compression if(isPrimaryIFD) { rootIFD.removeTIFFField (BaselineTIFFTagSet.TAG_COMPRESSION); } // PhotometricInterpretation rootIFD.removeTIFFField(BaselineTIFFTagSet.TAG_PHOTOMETRIC_INTERPRETATION); // StripOffsets rootIFD.removeTIFFField(BaselineTIFFTagSet.TAG_STRIP_OFFSETS); // SamplesPerPixel rootIFD.removeTIFFField(BaselineTIFFTagSet.TAG_SAMPLES_PER_PIXEL); // RowsPerStrip rootIFD.removeTIFFField(BaselineTIFFTagSet.TAG_ROWS_PER_STRIP); // StripByteCounts rootIFD.removeTIFFField(BaselineTIFFTagSet.TAG_STRIP_BYTE_COUNTS); // XResolution and YResolution are handled above for all TIFFs. // PlanarConfiguration rootIFD.removeTIFFField(BaselineTIFFTagSet.TAG_PLANAR_CONFIGURATION); // ResolutionUnit if(rootIFD.getTIFFField (BaselineTIFFTagSet.TAG_RESOLUTION_UNIT) == null) { f = new TIFFField(base.getTag (BaselineTIFFTagSet.TAG_RESOLUTION_UNIT), BaselineTIFFTagSet.RESOLUTION_UNIT_INCH); rootIFD.addTIFFField(f); } if(isPrimaryIFD) { // JPEGInterchangeFormat rootIFD.removeTIFFField (BaselineTIFFTagSet.TAG_JPEG_INTERCHANGE_FORMAT); // JPEGInterchangeFormatLength rootIFD.removeTIFFField (BaselineTIFFTagSet.TAG_JPEG_INTERCHANGE_FORMAT_LENGTH); // YCbCrSubsampling rootIFD.removeTIFFField (BaselineTIFFTagSet.TAG_Y_CB_CR_SUBSAMPLING); // YCbCrPositioning if(rootIFD.getTIFFField (BaselineTIFFTagSet.TAG_Y_CB_CR_POSITIONING) == null) { f = new TIFFField (base.getTag (BaselineTIFFTagSet.TAG_Y_CB_CR_POSITIONING), TIFFTag.TIFF_SHORT, 1, new char[] { (char)BaselineTIFFTagSet.Y_CB_CR_POSITIONING_CENTERED }); rootIFD.addTIFFField(f); } } else { // Thumbnail IFD // JPEGInterchangeFormat f = new TIFFField (base.getTag (BaselineTIFFTagSet.TAG_JPEG_INTERCHANGE_FORMAT), TIFFTag.TIFF_LONG, 1); rootIFD.addTIFFField(f); // JPEGInterchangeFormatLength f = new TIFFField (base.getTag (BaselineTIFFTagSet.TAG_JPEG_INTERCHANGE_FORMAT_LENGTH), TIFFTag.TIFF_LONG, 1); rootIFD.addTIFFField(f); // YCbCrSubsampling rootIFD.removeTIFFField (BaselineTIFFTagSet.TAG_Y_CB_CR_SUBSAMPLING); } } else { // Uncompressed // ImageWidth through PlanarConfiguration are set above. // XResolution and YResolution are handled above for all TIFFs. // ResolutionUnit if(rootIFD.getTIFFField (BaselineTIFFTagSet.TAG_RESOLUTION_UNIT) == null) { f = new TIFFField(base.getTag (BaselineTIFFTagSet.TAG_RESOLUTION_UNIT), BaselineTIFFTagSet.RESOLUTION_UNIT_INCH); rootIFD.addTIFFField(f); } // JPEGInterchangeFormat rootIFD.removeTIFFField (BaselineTIFFTagSet.TAG_JPEG_INTERCHANGE_FORMAT); // JPEGInterchangeFormatLength rootIFD.removeTIFFField (BaselineTIFFTagSet.TAG_JPEG_INTERCHANGE_FORMAT_LENGTH); if(photometricInterpretation == BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_RGB) { // YCbCrCoefficients rootIFD.removeTIFFField (BaselineTIFFTagSet.TAG_Y_CB_CR_COEFFICIENTS); // YCbCrSubsampling rootIFD.removeTIFFField (BaselineTIFFTagSet.TAG_Y_CB_CR_SUBSAMPLING); // YCbCrPositioning rootIFD.removeTIFFField (BaselineTIFFTagSet.TAG_Y_CB_CR_POSITIONING); } } // Get EXIF tags. TIFFTagSet exifTags = EXIFTIFFTagSet.getInstance(); // Retrieve or create the EXIF IFD. TIFFIFD exifIFD = null; f = rootIFD.getTIFFField (EXIFParentTIFFTagSet.TAG_EXIF_IFD_POINTER); if(f != null) { // Retrieve the EXIF IFD. exifIFD = (TIFFIFD)f.getData(); } else if(isPrimaryIFD) { // Create the EXIF IFD. List exifTagSets = new ArrayList(1); exifTagSets.add(exifTags); exifIFD = new TIFFIFD(exifTagSets); // Add it to the root IFD. TIFFTagSet tagSet = EXIFParentTIFFTagSet.getInstance(); TIFFTag exifIFDTag = tagSet.getTag(EXIFParentTIFFTagSet.TAG_EXIF_IFD_POINTER); rootIFD.addTIFFField(new TIFFField(exifIFDTag, TIFFTag.TIFF_LONG, 1, exifIFD)); } if(exifIFD != null) { // Handle EXIF private fields in order of increasing // tag number. // ExifVersion if(exifIFD.getTIFFField (EXIFTIFFTagSet.TAG_EXIF_VERSION) == null) { f = new TIFFField (exifTags.getTag(EXIFTIFFTagSet.TAG_EXIF_VERSION), TIFFTag.TIFF_UNDEFINED, 4, EXIFTIFFTagSet.EXIF_VERSION_2_2); exifIFD.addTIFFField(f); } if(compression == BaselineTIFFTagSet.COMPRESSION_OLD_JPEG) { // ComponentsConfiguration if(exifIFD.getTIFFField (EXIFTIFFTagSet.TAG_COMPONENTS_CONFIGURATION) == null) { f = new TIFFField (exifTags.getTag (EXIFTIFFTagSet.TAG_COMPONENTS_CONFIGURATION), TIFFTag.TIFF_UNDEFINED, 4, new byte[] { (byte)EXIFTIFFTagSet.COMPONENTS_CONFIGURATION_Y, (byte)EXIFTIFFTagSet.COMPONENTS_CONFIGURATION_CB, (byte)EXIFTIFFTagSet.COMPONENTS_CONFIGURATION_CR, (byte)0 }); exifIFD.addTIFFField(f); } } else { // ComponentsConfiguration exifIFD.removeTIFFField (EXIFTIFFTagSet.TAG_COMPONENTS_CONFIGURATION); // CompressedBitsPerPixel exifIFD.removeTIFFField (EXIFTIFFTagSet.TAG_COMPRESSED_BITS_PER_PIXEL); } // FlashpixVersion if(exifIFD.getTIFFField (EXIFTIFFTagSet.TAG_FLASHPIX_VERSION) == null) { f = new TIFFField (exifTags.getTag(EXIFTIFFTagSet.TAG_FLASHPIX_VERSION), TIFFTag.TIFF_UNDEFINED, 4, new byte[] {(byte)'0', (byte)'1', (byte)'0', (byte)'0'}); exifIFD.addTIFFField(f); } // ColorSpace if(exifIFD.getTIFFField (EXIFTIFFTagSet.TAG_COLOR_SPACE) == null) { f = new TIFFField (exifTags.getTag(EXIFTIFFTagSet.TAG_COLOR_SPACE), TIFFTag.TIFF_SHORT, 1, new char[] { (char)EXIFTIFFTagSet.COLOR_SPACE_SRGB }); exifIFD.addTIFFField(f); } if(compression == BaselineTIFFTagSet.COMPRESSION_OLD_JPEG) { // PixelXDimension if(exifIFD.getTIFFField (EXIFTIFFTagSet.TAG_PIXEL_X_DIMENSION) == null) { f = new TIFFField (exifTags.getTag(EXIFTIFFTagSet.TAG_PIXEL_X_DIMENSION), width); exifIFD.addTIFFField(f); } // PixelYDimension if(exifIFD.getTIFFField (EXIFTIFFTagSet.TAG_PIXEL_Y_DIMENSION) == null) { f = new TIFFField (exifTags.getTag(EXIFTIFFTagSet.TAG_PIXEL_Y_DIMENSION), height); exifIFD.addTIFFField(f); } } else { exifIFD.removeTIFFField (EXIFTIFFTagSet.TAG_INTEROPERABILITY_IFD_POINTER); } } } // if(isEXIF) } /** @param tileRect The area to be written which might be outside the image. */ private int writeTile(Rectangle tileRect, TIFFCompressor compressor) throws IOException { // Determine the rectangle which will actually be written // and set the padding flag. Padding will occur only when the // image is written as a tiled TIFF and the tile bounds are not // contained within the image bounds. Rectangle activeRect; boolean isPadded; Rectangle imageBounds = new Rectangle(image.getMinX(), image.getMinY(), image.getWidth(), image.getHeight()); if(!isTiled) { // Stripped activeRect = tileRect.intersection(imageBounds); tileRect = activeRect; isPadded = false; } else if(imageBounds.contains(tileRect)) { // Tiled, tile within image bounds activeRect = tileRect; isPadded = false; } else { // Tiled, tile not within image bounds activeRect = imageBounds.intersection(tileRect); isPadded = true; } // Shouldn't happen, but return early if empty intersection. if(activeRect.isEmpty()) { return 0; } int minX = tileRect.x; int minY = tileRect.y; int width = tileRect.width; int height = tileRect.height; if(isImageSimple) { SampleModel sm = image.getSampleModel(); // Read only data from the active rectangle. Raster raster = image.getData(activeRect); // If padding is required, create a larger Raster and fill // it from the active rectangle. if(isPadded) { WritableRaster wr = raster.createCompatibleWritableRaster(minX, minY, width, height); wr.setRect(raster); raster = wr; } if(isBilevel) { /* XXX MultiPixelPackedSampleModel mppsm = (MultiPixelPackedSampleModel)raster.getSampleModel(); byte[] buf; int off; int lineStride; if(mppsm.getDataBitOffset() == 0 && raster.getDataBuffer() instanceof DataBufferByte) { buf = ((DataBufferByte)raster.getDataBuffer()).getData(); off = mppsm.getOffset(tileRect.x - raster.getSampleModelTranslateX(), tileRect.y - raster.getSampleModelTranslateY()); lineStride = mppsm.getScanlineStride(); } else { buf = ImageUtil.getPackedBinaryData(raster, tileRect); off = 0; lineStride = (tileRect.width + 7)/8; } */ byte[] buf = ImageUtil.getPackedBinaryData(raster, tileRect); if(isInverted) { DataBuffer dbb = raster.getDataBuffer(); if(dbb instanceof DataBufferByte && buf == ((DataBufferByte)dbb).getData()) { byte[] bbuf = new byte[buf.length]; int len = buf.length; for(int i = 0; i < len; i++) { bbuf[i] = (byte)(buf[i] ^ 0xff); } buf = bbuf; } else { int len = buf.length; for(int i = 0; i < len; i++) { buf[i] ^= 0xff; } } } if(DEBUG) { System.out.println("Optimized bilevel case"); } return compressor.encode(buf, 0, width, height, sampleSize, (tileRect.width + 7)/8); } else if(bitDepth == 8 && sm.getDataType() == DataBuffer.TYPE_BYTE) { ComponentSampleModel csm = (ComponentSampleModel)raster.getSampleModel(); byte[] buf = ((DataBufferByte)raster.getDataBuffer()).getData(); int off = csm.getOffset(minX - raster.getSampleModelTranslateX(), minY - raster.getSampleModelTranslateY()); if(DEBUG) { System.out.println("Optimized component case"); } return compressor.encode(buf, off, width, height, sampleSize, csm.getScanlineStride()); } } // Set offsets and skips based on source subsampling factors int xOffset = minX; int xSkip = periodX; int yOffset = minY; int ySkip = periodY; // Early exit if no data for this pass int hpixels = (width + xSkip - 1)/xSkip; int vpixels = (height + ySkip - 1)/ySkip; if (hpixels == 0 || vpixels == 0) { return 0; } // Convert X offset and skip from pixels to samples xOffset *= numBands; xSkip *= numBands; // Initialize sizes int samplesPerByte = 8/bitDepth; int numSamples = width*numBands; int bytesPerRow = hpixels*numBands; // Update number of bytes per row. if (bitDepth < 8) { bytesPerRow = (bytesPerRow + samplesPerByte - 1)/samplesPerByte; } else if (bitDepth == 16) { bytesPerRow *= 2; } else if (bitDepth == 32) { bytesPerRow *= 4; } // Create row buffers int[] samples = null; float[] fsamples = null; if(sampleFormat == BaselineTIFFTagSet.SAMPLE_FORMAT_FLOATING_POINT) { fsamples = new float[numSamples]; } else { samples = new int[numSamples]; } // Create tile buffer byte[] currTile = new byte[bytesPerRow*vpixels]; // Sub-optimal case: shy of "isImageSimple" only by virtue of // not being contiguous. if(!isInverted && // no inversion !isRescaling && // no value rescaling sourceBands == null && // no subbanding periodX == 1 && periodY == 1 && // no subsampling colorConverter == null) { SampleModel sm = image.getSampleModel(); if(sm instanceof ComponentSampleModel && // component bitDepth == 8 && // 8 bits/sample sm.getDataType() == DataBuffer.TYPE_BYTE) { // byte type if(DEBUG) { System.out.println("Sub-optimal byte component case"); System.out.println(sm.getClass().getName()); } // Read only data from the active rectangle. Raster raster = image.getData(activeRect); // If padding is required, create a larger Raster and fill // it from the active rectangle. if(isPadded) { WritableRaster wr = raster.createCompatibleWritableRaster(minX, minY, width, height); wr.setRect(raster); raster = wr; } // Get SampleModel info. ComponentSampleModel csm = (ComponentSampleModel)raster.getSampleModel(); int[] bankIndices = csm.getBankIndices(); byte[][] bankData = ((DataBufferByte)raster.getDataBuffer()).getBankData(); int lineStride = csm.getScanlineStride(); int pixelStride = csm.getPixelStride(); // Copy the data into a contiguous pixel interleaved buffer. for(int k = 0; k < numBands; k++) { byte[] bandData = bankData[bankIndices[k]]; int lineOffset = csm.getOffset(raster.getMinX() - raster.getSampleModelTranslateX(), raster.getMinY() - raster.getSampleModelTranslateY(), k); int idx = k; for(int j = 0; j < vpixels; j++) { int offset = lineOffset; for(int i = 0; i < hpixels; i++) { currTile[idx] = bandData[offset]; idx += numBands; offset += pixelStride; } lineOffset += lineStride; } } // Compressor and return. return compressor.encode(currTile, 0, width, height, sampleSize, width*numBands); } } if(DEBUG) { System.out.println("Unoptimized case for bit depth "+bitDepth); SampleModel sm = image.getSampleModel(); System.out.println("isRescaling = "+isRescaling); System.out.println("sourceBands = "+sourceBands); System.out.println("periodX = "+periodX); System.out.println("periodY = "+periodY); System.out.println(sm.getClass().getName()); System.out.println(sm.getDataType()); if(sm instanceof ComponentSampleModel) { ComponentSampleModel csm = (ComponentSampleModel)sm; System.out.println(csm.getNumBands()); System.out.println(csm.getPixelStride()); int[] bankIndices = csm.getBankIndices(); for(int b = 0; b < numBands; b++) { System.out.print(bankIndices[b]+" "); } int[] bandOffsets = csm.getBandOffsets(); for(int b = 0; b < numBands; b++) { System.out.print(bandOffsets[b]+" "); } System.out.println(""); } } int tcount = 0; // Save active rectangle variables. int activeMinX = activeRect.x; int activeMinY = activeRect.y; int activeMaxY = activeMinY + activeRect.height - 1; int activeWidth = activeRect.width; // Set a SampleModel for use in padding. SampleModel rowSampleModel = null; if(isPadded) { rowSampleModel = image.getSampleModel().createCompatibleSampleModel(width, 1); } for (int row = yOffset; row < yOffset + height; row += ySkip) { Raster ras = null; if(isPadded) { // Create a raster for the entire row. WritableRaster wr = Raster.createWritableRaster(rowSampleModel, new Point(minX, row)); // Populate the raster from the active sub-row, if any. if(row >= activeMinY && row <= activeMaxY) { Rectangle rect = new Rectangle(activeMinX, row, activeWidth, 1); ras = image.getData(rect); wr.setRect(ras); } // Update the raster variable. ras = wr; } else { Rectangle rect = new Rectangle(minX, row, width, 1); ras = image.getData(rect); } if (sourceBands != null) { ras = ras.createChild(minX, row, width, 1, minX, row, sourceBands); } if(sampleFormat == BaselineTIFFTagSet.SAMPLE_FORMAT_FLOATING_POINT) { ras.getPixels(minX, row, width, 1, fsamples); } else { ras.getPixels(minX, row, width, 1, samples); if ((nativePhotometricInterpretation == BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_BLACK_IS_ZERO && photometricInterpretation == BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_WHITE_IS_ZERO) || (nativePhotometricInterpretation == BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_WHITE_IS_ZERO && photometricInterpretation == BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_BLACK_IS_ZERO)) { int bitMask = (1 << bitDepth) - 1; for (int s = 0; s < numSamples; s++) { samples[s] ^= bitMask; } } } if (colorConverter != null) { int idx = 0; float[] result = new float[3]; if(sampleFormat == BaselineTIFFTagSet.SAMPLE_FORMAT_FLOATING_POINT) { for (int i = 0; i < width; i++) { float r = fsamples[idx]; float g = fsamples[idx + 1]; float b = fsamples[idx + 2]; colorConverter.fromRGB(r, g, b, result); fsamples[idx] = result[0]; fsamples[idx + 1] = result[1]; fsamples[idx + 2] = result[2]; idx += 3; } } else { for (int i = 0; i < width; i++) { float r = (float)samples[idx]; float g = (float)samples[idx + 1]; float b = (float)samples[idx + 2]; colorConverter.fromRGB(r, g, b, result); samples[idx] = (int)(result[0]); samples[idx + 1] = (int)(result[1]); samples[idx + 2] = (int)(result[2]); idx += 3; } } } int tmp = 0; int pos = 0; switch (bitDepth) { case 1: case 2: case 4: // Image can only have a single band if(isRescaling) { for (int s = 0; s < numSamples; s += xSkip) { byte val = scale0[samples[s]]; tmp = (tmp << bitDepth) | val; if (++pos == samplesPerByte) { currTile[tcount++] = (byte)tmp; tmp = 0; pos = 0; } } } else { for (int s = 0; s < numSamples; s += xSkip) { byte val = (byte)samples[s]; tmp = (tmp << bitDepth) | val; if (++pos == samplesPerByte) { currTile[tcount++] = (byte)tmp; tmp = 0; pos = 0; } } } // Left shift the last byte if (pos != 0) { tmp <<= ((8/bitDepth) - pos)*bitDepth; currTile[tcount++] = (byte)tmp; } break; case 8: if (numBands == 1) { if(isRescaling) { for (int s = 0; s < numSamples; s += xSkip) { currTile[tcount++] = scale0[samples[s]]; } } else { for (int s = 0; s < numSamples; s += xSkip) { currTile[tcount++] = (byte)samples[s]; } } } else { if(isRescaling) { for (int s = 0; s < numSamples; s += xSkip) { for (int b = 0; b < numBands; b++) { currTile[tcount++] = scale[b][samples[s + b]]; } } } else { for (int s = 0; s < numSamples; s += xSkip) { for (int b = 0; b < numBands; b++) { currTile[tcount++] = (byte)samples[s + b]; } } } } break; case 16: // XXX Need to verify this rescaling for signed vs. unsigned. if(isRescaling) { if(stream.getByteOrder() == ByteOrder.BIG_ENDIAN) { for (int s = 0; s < numSamples; s += xSkip) { for (int b = 0; b < numBands; b++) { int sample = samples[s + b]; currTile[tcount++] = scaleh[b][sample]; currTile[tcount++] = scalel[b][sample]; } } } else { // ByteOrder.LITLE_ENDIAN for (int s = 0; s < numSamples; s += xSkip) { for (int b = 0; b < numBands; b++) { int sample = samples[s + b]; currTile[tcount++] = scalel[b][sample]; currTile[tcount++] = scaleh[b][sample]; } } } } else { if(stream.getByteOrder() == ByteOrder.BIG_ENDIAN) { for (int s = 0; s < numSamples; s += xSkip) { for (int b = 0; b < numBands; b++) { int sample = samples[s + b]; currTile[tcount++] = (byte)((sample >>> 8) & 0xff); currTile[tcount++] = (byte)(sample & 0xff); } } } else { // ByteOrder.LITLE_ENDIAN for (int s = 0; s < numSamples; s += xSkip) { for (int b = 0; b < numBands; b++) { int sample = samples[s + b]; currTile[tcount++] = (byte)(sample & 0xff); currTile[tcount++] = (byte)((sample >>> 8) & 0xff); } } } } break; case 32: if(sampleFormat == BaselineTIFFTagSet.SAMPLE_FORMAT_FLOATING_POINT) { if(stream.getByteOrder() == ByteOrder.BIG_ENDIAN) { for (int s = 0; s < numSamples; s += xSkip) { for (int b = 0; b < numBands; b++) { float fsample = fsamples[s + b]; int isample = Float.floatToIntBits(fsample); currTile[tcount++] = (byte)((isample & 0xff000000) >> 24); currTile[tcount++] = (byte)((isample & 0x00ff0000) >> 16); currTile[tcount++] = (byte)((isample & 0x0000ff00) >> 8); currTile[tcount++] = (byte)(isample & 0x000000ff); } } } else { // ByteOrder.LITLE_ENDIAN for (int s = 0; s < numSamples; s += xSkip) { for (int b = 0; b < numBands; b++) { float fsample = fsamples[s + b]; int isample = Float.floatToIntBits(fsample); currTile[tcount++] = (byte)(isample & 0x000000ff); currTile[tcount++] = (byte)((isample & 0x0000ff00) >> 8); currTile[tcount++] = (byte)((isample & 0x00ff0000) >> 16); currTile[tcount++] = (byte)((isample & 0xff000000) >> 24); } } } } else { if(isRescaling) { // XXX Need to verify this for signed vs. unsigned. // XXX The following gives saturated results when the // original data are in the signed integer range. long[] maxIn = new long[numBands]; long[] halfIn = new long[numBands]; long maxOut = (1L << (long)bitDepth) - 1L; for (int b = 0; b < numBands; b++) { maxIn[b] = ((1L << (long)sampleSize[b]) - 1L); halfIn[b] = maxIn[b]/2; } if(stream.getByteOrder() == ByteOrder.BIG_ENDIAN) { for (int s = 0; s < numSamples; s += xSkip) { for (int b = 0; b < numBands; b++) { long sampleOut = (samples[s + b]*maxOut + halfIn[b])/ maxIn[b]; currTile[tcount++] = (byte)((sampleOut & 0xff000000) >> 24); currTile[tcount++] = (byte)((sampleOut & 0x00ff0000) >> 16); currTile[tcount++] = (byte)((sampleOut & 0x0000ff00) >> 8); currTile[tcount++] = (byte)(sampleOut & 0x000000ff); } } } else { // ByteOrder.LITLE_ENDIAN for (int s = 0; s < numSamples; s += xSkip) { for (int b = 0; b < numBands; b++) { long sampleOut = (samples[s + b]*maxOut + halfIn[b])/ maxIn[b]; currTile[tcount++] = (byte)(sampleOut & 0x000000ff); currTile[tcount++] = (byte)((sampleOut & 0x0000ff00) >> 8); currTile[tcount++] = (byte)((sampleOut & 0x00ff0000) >> 16); currTile[tcount++] = (byte)((sampleOut & 0xff000000) >> 24); } } } } else { if(stream.getByteOrder() == ByteOrder.BIG_ENDIAN) { for (int s = 0; s < numSamples; s += xSkip) { for (int b = 0; b < numBands; b++) { int isample = samples[s + b]; currTile[tcount++] = (byte)((isample & 0xff000000) >> 24); currTile[tcount++] = (byte)((isample & 0x00ff0000) >> 16); currTile[tcount++] = (byte)((isample & 0x0000ff00) >> 8); currTile[tcount++] = (byte)(isample & 0x000000ff); } } } else { // ByteOrder.LITLE_ENDIAN for (int s = 0; s < numSamples; s += xSkip) { for (int b = 0; b < numBands; b++) { int isample = samples[s + b]; currTile[tcount++] = (byte)(isample & 0x000000ff); currTile[tcount++] = (byte)((isample & 0x0000ff00) >> 8); currTile[tcount++] = (byte)((isample & 0x00ff0000) >> 16); currTile[tcount++] = (byte)((isample & 0xff000000) >> 24); } } } } } break; } } int[] bitsPerSample = new int[numBands]; for (int i = 0; i < bitsPerSample.length; i++) { bitsPerSample[i] = bitDepth; } int byteCount = compressor.encode(currTile, 0, hpixels, vpixels, bitsPerSample, bytesPerRow); return byteCount; } // Check two int arrays for value equality, always returns false // if either array is null private boolean equals(int[] s0, int[] s1) { if (s0 == null || s1 == null) { return false; } if (s0.length != s1.length) { return false; } for (int i = 0; i < s0.length; i++) { if (s0[i] != s1[i]) { return false; } } return true; } // Initialize the scale/scale0 or scaleh/scalel arrays to // hold the results of scaling an input value to the desired // output bit depth // XXX Need to verify this rescaling for signed vs. unsigned. private void initializeScaleTables(int[] sampleSize) { // Save the sample size in the instance variable. // If the existing tables are still valid, just return. if (bitDepth == scalingBitDepth && equals(sampleSize, this.sampleSize)) { if(DEBUG) { System.out.println("Returning from initializeScaleTables()"); } return; } // Reset scaling variables. isRescaling = false; scalingBitDepth = -1; scale = scalel = scaleh = null; scale0 = null; // Set global sample size to parameter. this.sampleSize = sampleSize; // Check whether rescaling is called for. if(bitDepth <= 16) { for(int b = 0; b < numBands; b++) { if(sampleSize[b] != bitDepth) { isRescaling = true; break; } } } if(DEBUG) { System.out.println("isRescaling = "+isRescaling); } // If not rescaling then return after saving the sample size. if(!isRescaling) { return; } // Compute new tables this.scalingBitDepth = bitDepth; int maxOutSample = (1 << bitDepth) - 1; if (bitDepth <= 8) { scale = new byte[numBands][]; for (int b = 0; b < numBands; b++) { int maxInSample = (1 << sampleSize[b]) - 1; int halfMaxInSample = maxInSample/2; scale[b] = new byte[maxInSample + 1]; for (int s = 0; s <= maxInSample; s++) { scale[b][s] = (byte)((s*maxOutSample + halfMaxInSample)/maxInSample); } } scale0 = scale[0]; scaleh = scalel = null; } else if(bitDepth <= 16) { // Divide scaling table into high and low bytes scaleh = new byte[numBands][]; scalel = new byte[numBands][]; for (int b = 0; b < numBands; b++) { int maxInSample = (1 << sampleSize[b]) - 1; int halfMaxInSample = maxInSample/2; scaleh[b] = new byte[maxInSample + 1]; scalel[b] = new byte[maxInSample + 1]; for (int s = 0; s <= maxInSample; s++) { int val = (s*maxOutSample + halfMaxInSample)/maxInSample; scaleh[b][s] = (byte)(val >> 8); scalel[b][s] = (byte)(val & 0xff); } } scale = null; scale0 = null; } } public void write(IIOMetadata sm, IIOImage iioimage, ImageWriteParam p) throws IOException { write(sm, iioimage, p, true, true); } private void writeHeader() throws IOException { if (streamMetadata != null) { this.byteOrder = streamMetadata.byteOrder; } else { this.byteOrder = ByteOrder.BIG_ENDIAN; } stream.setByteOrder(byteOrder); if (byteOrder == ByteOrder.BIG_ENDIAN) { stream.writeShort(0x4d4d); } else { stream.writeShort(0x4949); } stream.writeShort(42); // Magic number stream.writeInt(0); // Offset of first IFD (0 == none) nextSpace = stream.getStreamPosition(); headerPosition = nextSpace - 8; } private void write(IIOMetadata sm, IIOImage iioimage, ImageWriteParam p, boolean writeHeader, boolean writeData) throws IOException { if (stream == null) { throw new IllegalStateException("output == null!"); } if (iioimage == null) { throw new IllegalArgumentException("image == null!"); } if(iioimage.hasRaster() && !canWriteRasters()) { throw new UnsupportedOperationException ("TIFF ImageWriter cannot write Rasters!"); } this.image = iioimage.getRenderedImage(); SampleModel sampleModel = image.getSampleModel(); this.sourceXOffset = image.getMinX(); this.sourceYOffset = image.getMinY(); this.sourceWidth = image.getWidth(); this.sourceHeight = image.getHeight(); Rectangle imageBounds = new Rectangle(sourceXOffset, sourceYOffset, sourceWidth, sourceHeight); ColorModel colorModel = null; if (p == null) { this.param = getDefaultWriteParam(); this.sourceBands = null; this.periodX = 1; this.periodY = 1; this.numBands = sampleModel.getNumBands(); colorModel = image.getColorModel(); } else { this.param = p; // Get source region and subsampling factors Rectangle sourceRegion = param.getSourceRegion(); if (sourceRegion != null) { // Clip to actual image bounds sourceRegion = sourceRegion.intersection(imageBounds); sourceXOffset = sourceRegion.x; sourceYOffset = sourceRegion.y; sourceWidth = sourceRegion.width; sourceHeight = sourceRegion.height; } // Adjust for subsampling offsets int gridX = param.getSubsamplingXOffset(); int gridY = param.getSubsamplingYOffset(); this.sourceXOffset += gridX; this.sourceYOffset += gridY; this.sourceWidth -= gridX; this.sourceHeight -= gridY; // Get subsampling factors this.periodX = param.getSourceXSubsampling(); this.periodY = param.getSourceYSubsampling(); int[] sBands = param.getSourceBands(); if (sBands != null) { sourceBands = sBands; this.numBands = sourceBands.length; } else { this.numBands = sampleModel.getNumBands(); } ImageTypeSpecifier destType = p.getDestinationType(); if(destType != null) { ColorModel cm = destType.getColorModel(); if(cm.getNumComponents() == numBands) { colorModel = cm; } } if(colorModel == null) { colorModel = image.getColorModel(); } } this.imageType = new ImageTypeSpecifier(colorModel, sampleModel); ImageUtil.canEncodeImage(this, this.imageType); // Compute output dimensions int destWidth = (sourceWidth + periodX - 1)/periodX; int destHeight = (sourceHeight + periodY - 1)/periodY; if (destWidth <= 0 || destHeight <= 0) { throw new IllegalArgumentException("Empty source region!"); } // this.bitDepth = 8; // XXX fix? clearAbortRequest(); processImageStarted(0); // Optionally write the header. if (writeHeader) { // Clear previous stream metadata. this.streamMetadata = null; // Try to convert non-null input stream metadata. if (sm != null) { this.streamMetadata = (TIFFStreamMetadata)convertStreamMetadata(sm, param); } // Set to default if not converted. if(this.streamMetadata == null) { this.streamMetadata = (TIFFStreamMetadata)getDefaultStreamMetadata(param); } // Write the header. writeHeader(); // Seek to the position of the IFD pointer in the header. stream.seek(headerPosition + 4); // Ensure IFD is written on a word boundary nextSpace = (nextSpace + 3) & ~0x3; // Write the pointer to the first IFD after the header. stream.writeInt((int)nextSpace); } // Write out the IFD and any sub IFDs, followed by a zero // Clear previous image metadata. this.imageMetadata = null; // Initialize the metadata object. IIOMetadata im = iioimage.getMetadata(); if(im != null) { if (im instanceof TIFFImageMetadata) { // Clone the one passed in. this.imageMetadata = ((TIFFImageMetadata)im).getShallowClone(); } else if(Arrays.asList(im.getMetadataFormatNames()).contains( TIFFImageMetadata.nativeMetadataFormatName)) { this.imageMetadata = convertNativeImageMetadata(im); } else if(im.isStandardMetadataFormatSupported()) { try { // Convert standard metadata. this.imageMetadata = convertStandardImageMetadata(im); } catch(IIOInvalidTreeException e) { // XXX Warning } } } // Use default metadata if still null. if(this.imageMetadata == null) { this.imageMetadata = (TIFFImageMetadata)getDefaultImageMetadata(this.imageType, this.param); } // Set or overwrite mandatory fields in the root IFD setupMetadata(colorModel, sampleModel, destWidth, destHeight); // Set compressor fields. compressor.setWriter(this); // Metadata needs to be set on the compressor before the IFD is // written as the compressor could modify the metadata. compressor.setMetadata(imageMetadata); compressor.setStream(stream); // Initialize scaling tables for this image int[] sampleSize = sampleModel.getSampleSize(); initializeScaleTables(sampleModel.getSampleSize()); // Determine whether bilevel. this.isBilevel = ImageUtil.isBinary(this.image.getSampleModel()); // Check for photometric inversion. this.isInverted = (nativePhotometricInterpretation == BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_BLACK_IS_ZERO && photometricInterpretation == BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_WHITE_IS_ZERO) || (nativePhotometricInterpretation == BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_WHITE_IS_ZERO && photometricInterpretation == BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_BLACK_IS_ZERO); // Analyze image data suitability for direct copy. this.isImageSimple = (isBilevel || (!isInverted && ImageUtil.imageIsContiguous(this.image))) && !isRescaling && // no value rescaling sourceBands == null && // no subbanding periodX == 1 && periodY == 1 && // no subsampling colorConverter == null; TIFFIFD rootIFD = imageMetadata.getRootIFD(); rootIFD.writeToStream(stream); this.nextIFDPointerPos = stream.getStreamPosition(); stream.writeInt(0); // Seek to end of IFD data long lastIFDPosition = rootIFD.getLastPosition(); stream.seek(lastIFDPosition); if(lastIFDPosition > this.nextSpace) { this.nextSpace = lastIFDPosition; } // If not writing the image data, i.e., if writing or inserting an // empty image, return. if(!writeData) { return; } // Get positions of fields within the IFD to update as we write // each strip or tile long stripOrTileByteCountsPosition = rootIFD.getStripOrTileByteCountsPosition(); long stripOrTileOffsetsPosition = rootIFD.getStripOrTileOffsetsPosition(); // Compute total number of pixels for progress notification this.totalPixels = tileWidth*tileLength*tilesDown*tilesAcross; this.pixelsDone = 0; // Write the image, a strip or tile at a time for (int tj = 0; tj < tilesDown; tj++) { for (int ti = 0; ti < tilesAcross; ti++) { long pos = stream.getStreamPosition(); // Write the (possibly compressed) tile data Rectangle tileRect = new Rectangle(sourceXOffset + ti*tileWidth*periodX, sourceYOffset + tj*tileLength*periodY, tileWidth*periodX, tileLength*periodY); // tileRect = tileRect.intersection(imageBounds); // XXX try { int byteCount = writeTile(tileRect, compressor); if(pos + byteCount > nextSpace) { nextSpace = pos + byteCount; } pixelsDone += tileRect.width*tileRect.height; processImageProgress(100.0F*pixelsDone/totalPixels); // Fill in the offset and byte count for the file stream.mark(); stream.seek(stripOrTileOffsetsPosition); stream.writeInt((int)pos); stripOrTileOffsetsPosition += 4; stream.seek(stripOrTileByteCountsPosition); stream.writeInt(byteCount); stripOrTileByteCountsPosition += 4; stream.reset(); } catch (IOException e) { throw new IIOException("I/O error writing TIFF file!", e); } if (abortRequested()) { processWriteAborted(); return; } } } processImageComplete(); } public boolean canWriteSequence() { return true; } public void prepareWriteSequence(IIOMetadata streamMetadata) throws IOException { if (getOutput() == null) { throw new IllegalStateException("getOutput() == null!"); } // Set up stream metadata. if (streamMetadata != null) { streamMetadata = convertStreamMetadata(streamMetadata, null); } if(streamMetadata == null) { streamMetadata = getDefaultStreamMetadata(null); } this.streamMetadata = (TIFFStreamMetadata)streamMetadata; // Write the header. writeHeader(); // Set the sequence flag. this.isWritingSequence = true; } public void writeToSequence(IIOImage image, ImageWriteParam param) throws IOException { // Check sequence flag. if(!this.isWritingSequence) { throw new IllegalStateException ("prepareWriteSequence() has not been called!"); } // Append image. writeInsert(-1, image, param); } public void endWriteSequence() throws IOException { // Check output. if (getOutput() == null) { throw new IllegalStateException("getOutput() == null!"); } // Check sequence flag. if(!isWritingSequence) { throw new IllegalStateException ("prepareWriteSequence() has not been called!"); } // Unset sequence flag. this.isWritingSequence = false; } public boolean canInsertImage(int imageIndex) throws IOException { if (getOutput() == null) { throw new IllegalStateException("getOutput() == null!"); } // Mark position as locateIFD() will seek to IFD at imageIndex. stream.mark(); // locateIFD() will throw an IndexOutOfBoundsException if // imageIndex is < -1 or is too big thereby satisfying the spec. long[] ifdpos = new long[1]; long[] ifd = new long[1]; locateIFD(imageIndex, ifdpos, ifd); // Reset to position before locateIFD(). stream.reset(); return true; } // Locate start of IFD for image. // Throws IIOException if not at a TIFF header and // IndexOutOfBoundsException if imageIndex is < -1 or is too big. private void locateIFD(int imageIndex, long[] ifdpos, long[] ifd) throws IOException { if(imageIndex < -1) { throw new IndexOutOfBoundsException("imageIndex < -1!"); } long startPos = stream.getStreamPosition(); stream.seek(headerPosition); int byteOrder = stream.readUnsignedShort(); if (byteOrder == 0x4d4d) { stream.setByteOrder(ByteOrder.BIG_ENDIAN); } else if (byteOrder == 0x4949) { stream.setByteOrder(ByteOrder.LITTLE_ENDIAN); } else { stream.seek(startPos); throw new IIOException("Illegal byte order"); } if (stream.readUnsignedShort() != 42) { stream.seek(startPos); throw new IIOException("Illegal magic number"); } ifdpos[0] = stream.getStreamPosition(); ifd[0] = stream.readUnsignedInt(); if (ifd[0] == 0) { // imageIndex has to be >= -1 due to check above. if(imageIndex > 0) { stream.seek(startPos); throw new IndexOutOfBoundsException ("imageIndex is greater than the largest available index!"); } return; } stream.seek(ifd[0]); for (int i = 0; imageIndex == -1 || i < imageIndex; i++) { int numFields; try { numFields = stream.readShort(); } catch (EOFException eof) { stream.seek(startPos); ifd[0] = 0; return; } stream.skipBytes(12*numFields); ifdpos[0] = stream.getStreamPosition(); ifd[0] = stream.readUnsignedInt(); if (ifd[0] == 0) { if (imageIndex != -1 && i < imageIndex - 1) { stream.seek(startPos); throw new IndexOutOfBoundsException( "imageIndex is greater than the largest available index!"); } break; } stream.seek(ifd[0]); } } public void writeInsert(int imageIndex, IIOImage image, ImageWriteParam param) throws IOException { insert(imageIndex, image, param, true); } private void insert(int imageIndex, IIOImage image, ImageWriteParam param, boolean writeData) throws IOException { if (stream == null) { throw new IllegalStateException("Output not set!"); } if (image == null) { throw new IllegalArgumentException("image == null!"); } // Locate the position of the old IFD (ifd) and the location // of the pointer to that position (ifdpos). long[] ifdpos = new long[1]; long[] ifd = new long[1]; // locateIFD() will throw an IndexOutOfBoundsException if // imageIndex is < -1 or is too big thereby satisfying the spec. locateIFD(imageIndex, ifdpos, ifd); // Seek to the position containing the pointer to the old IFD. stream.seek(ifdpos[0]); // Update next space pointer in anticipation of next write. if(ifdpos[0] + 4 > nextSpace) { nextSpace = ifdpos[0] + 4; } // Ensure IFD is written on a word boundary nextSpace = (nextSpace + 3) & ~0x3; // Update the value to point to the next available space. stream.writeInt((int)nextSpace); // Seek to the next available space. stream.seek(nextSpace); // Write the image (IFD and data). write(null, image, param, false, writeData); // Seek to the position containing the pointer in the new IFD. stream.seek(nextIFDPointerPos); // Update the new IFD to point to the old IFD. stream.writeInt((int)ifd[0]); // Don't need to update nextSpace here as already done in write(). } // ----- BEGIN insert/writeEmpty methods ----- // XXX Move local variable(s) up. private boolean isInsertingEmpty = false; private boolean isWritingEmpty = false; private boolean isEncodingEmpty() { return isInsertingEmpty || isWritingEmpty; } public boolean canInsertEmpty(int imageIndex) throws IOException { return canInsertImage(imageIndex); } public boolean canWriteEmpty() throws IOException { if (getOutput() == null) { throw new IllegalStateException("getOutput() == null!"); } return true; } // Check state and parameters for writing or inserting empty images. private void checkParamsEmpty(ImageTypeSpecifier imageType, int width, int height, List thumbnails) { if (getOutput() == null) { throw new IllegalStateException("getOutput() == null!"); } if(imageType == null) { throw new IllegalArgumentException("imageType == null!"); } if(width < 1 || height < 1) { throw new IllegalArgumentException("width < 1 || height < 1!"); } if(thumbnails != null) { int numThumbs = thumbnails.size(); for(int i = 0; i < numThumbs; i++) { Object thumb = thumbnails.get(i); if(thumb == null || !(thumb instanceof BufferedImage)) { throw new IllegalArgumentException ("thumbnails contains null references or objects other than BufferedImages!"); } } } if(this.isInsertingEmpty) { throw new IllegalStateException ("Previous call to prepareInsertEmpty() without corresponding call to endInsertEmpty()!"); } if(this.isWritingEmpty) { throw new IllegalStateException ("Previous call to prepareWriteEmpty() without corresponding call to endWriteEmpty()!"); } } public void prepareInsertEmpty(int imageIndex, ImageTypeSpecifier imageType, int width, int height, IIOMetadata imageMetadata, List thumbnails, ImageWriteParam param) throws IOException { checkParamsEmpty(imageType, width, height, thumbnails); this.isInsertingEmpty = true; SampleModel emptySM = imageType.getSampleModel(); RenderedImage emptyImage = new EmptyImage(0, 0, width, height, 0, 0, emptySM.getWidth(), emptySM.getHeight(), emptySM, imageType.getColorModel()); insert(imageIndex, new IIOImage(emptyImage, null, imageMetadata), param, false); } public void prepareWriteEmpty(IIOMetadata streamMetadata, ImageTypeSpecifier imageType, int width, int height, IIOMetadata imageMetadata, List thumbnails, ImageWriteParam param) throws IOException { checkParamsEmpty(imageType, width, height, thumbnails); this.isWritingEmpty = true; SampleModel emptySM = imageType.getSampleModel(); RenderedImage emptyImage = new EmptyImage(0, 0, width, height, 0, 0, emptySM.getWidth(), emptySM.getHeight(), emptySM, imageType.getColorModel()); write(streamMetadata, new IIOImage(emptyImage, null, imageMetadata), param, true, false); } public void endInsertEmpty() throws IOException { if (getOutput() == null) { throw new IllegalStateException("getOutput() == null!"); } if(!this.isInsertingEmpty) { throw new IllegalStateException ("No previous call to prepareInsertEmpty()!"); } if(this.isWritingEmpty) { throw new IllegalStateException ("Previous call to prepareWriteEmpty() without corresponding call to endWriteEmpty()!"); } if (inReplacePixelsNest) { throw new IllegalStateException ("In nested call to prepareReplacePixels!"); } this.isInsertingEmpty = false; } public void endWriteEmpty() throws IOException { if (getOutput() == null) { throw new IllegalStateException("getOutput() == null!"); } if(!this.isWritingEmpty) { throw new IllegalStateException ("No previous call to prepareWriteEmpty()!"); } if(this.isInsertingEmpty) { throw new IllegalStateException ("Previous call to prepareInsertEmpty() without corresponding call to endInsertEmpty()!"); } if (inReplacePixelsNest) { throw new IllegalStateException ("In nested call to prepareReplacePixels!"); } this.isWritingEmpty = false; } // ----- END insert/writeEmpty methods ----- // ----- BEGIN replacePixels methods ----- private TIFFIFD readIFD(int imageIndex) throws IOException { if (stream == null) { throw new IllegalStateException("Output not set!"); } if (imageIndex < 0) { throw new IndexOutOfBoundsException("imageIndex < 0!"); } stream.mark(); long[] ifdpos = new long[1]; long[] ifd = new long[1]; locateIFD(imageIndex, ifdpos, ifd); if (ifd[0] == 0) { stream.reset(); throw new IndexOutOfBoundsException ("imageIndex out of bounds!"); } List tagSets = new ArrayList(1); tagSets.add(BaselineTIFFTagSet.getInstance()); TIFFIFD rootIFD = new TIFFIFD(tagSets); // XXX Ignore unknown fields in metadata presumably because // any fields needed to write pixels would be known? rootIFD.initialize(stream, true); stream.reset(); return rootIFD; } public boolean canReplacePixels(int imageIndex) throws IOException { if (getOutput() == null) { throw new IllegalStateException("getOutput() == null!"); } TIFFIFD rootIFD = readIFD(imageIndex); TIFFField f = rootIFD.getTIFFField(BaselineTIFFTagSet.TAG_COMPRESSION); int compression = f.getAsInt(0); return compression == BaselineTIFFTagSet.COMPRESSION_NONE; } private Object replacePixelsLock = new Object(); private int replacePixelsIndex = -1; private TIFFImageMetadata replacePixelsMetadata = null; private long[] replacePixelsTileOffsets = null; private long[] replacePixelsByteCounts = null; private long replacePixelsOffsetsPosition = 0L; private long replacePixelsByteCountsPosition = 0L; private Rectangle replacePixelsRegion = null; private boolean inReplacePixelsNest = false; private TIFFImageReader reader = null; public void prepareReplacePixels(int imageIndex, Rectangle region) throws IOException { synchronized(replacePixelsLock) { // Check state and parameters vis-a-vis ImageWriter specification. if (stream == null) { throw new IllegalStateException("Output not set!"); } if (region == null) { throw new IllegalArgumentException("region == null!"); } if (region.getWidth() < 1) { throw new IllegalArgumentException("region.getWidth() < 1!"); } if (region.getHeight() < 1) { throw new IllegalArgumentException("region.getHeight() < 1!"); } if (inReplacePixelsNest) { throw new IllegalStateException ("In nested call to prepareReplacePixels!"); } // Read the IFD for the pixel replacement index. TIFFIFD replacePixelsIFD = readIFD(imageIndex); // Ensure that compression is "none". TIFFField f = replacePixelsIFD.getTIFFField(BaselineTIFFTagSet.TAG_COMPRESSION); int compression = f.getAsInt(0); if (compression != BaselineTIFFTagSet.COMPRESSION_NONE) { throw new UnsupportedOperationException ("canReplacePixels(imageIndex) == false!"); } // Get the image dimensions. f = replacePixelsIFD.getTIFFField(BaselineTIFFTagSet.TAG_IMAGE_WIDTH); if(f == null) { throw new IIOException("Cannot read ImageWidth field."); } int w = f.getAsInt(0); f = replacePixelsIFD.getTIFFField(BaselineTIFFTagSet.TAG_IMAGE_LENGTH); if(f == null) { throw new IIOException("Cannot read ImageHeight field."); } int h = f.getAsInt(0); // Create image bounds. Rectangle bounds = new Rectangle(0, 0, w, h); // Intersect region with bounds. region = region.intersection(bounds); // Check for empty intersection. if(region.isEmpty()) { throw new IIOException("Region does not intersect image bounds"); } // Save the region. replacePixelsRegion = region; // Get the tile offsets. f = replacePixelsIFD.getTIFFField(BaselineTIFFTagSet.TAG_TILE_OFFSETS); if(f == null) { f = replacePixelsIFD.getTIFFField(BaselineTIFFTagSet.TAG_STRIP_OFFSETS); } replacePixelsTileOffsets = f.getAsLongs(); // Get the byte counts. f = replacePixelsIFD.getTIFFField(BaselineTIFFTagSet.TAG_TILE_BYTE_COUNTS); if(f == null) { f = replacePixelsIFD.getTIFFField(BaselineTIFFTagSet.TAG_STRIP_BYTE_COUNTS); } replacePixelsByteCounts = f.getAsLongs(); replacePixelsOffsetsPosition = replacePixelsIFD.getStripOrTileOffsetsPosition(); replacePixelsByteCountsPosition = replacePixelsIFD.getStripOrTileByteCountsPosition(); // Get the image metadata. replacePixelsMetadata = new TIFFImageMetadata(replacePixelsIFD); // Save the image index. replacePixelsIndex = imageIndex; // Set the pixel replacement flag. inReplacePixelsNest = true; } } private Raster subsample(Raster raster, int[] sourceBands, int subOriginX, int subOriginY, int subPeriodX, int subPeriodY, int dstOffsetX, int dstOffsetY, Rectangle target) { int x = raster.getMinX(); int y = raster.getMinY(); int w = raster.getWidth(); int h = raster.getHeight(); int b = raster.getSampleModel().getNumBands(); int t = raster.getSampleModel().getDataType(); int outMinX = XToTileX(x, subOriginX, subPeriodX) + dstOffsetX; int outMinY = YToTileY(y, subOriginY, subPeriodY) + dstOffsetY; int outMaxX = XToTileX(x + w - 1, subOriginX, subPeriodX) + dstOffsetX; int outMaxY = YToTileY(y + h - 1, subOriginY, subPeriodY) + dstOffsetY; int outWidth = outMaxX - outMinX + 1; int outHeight = outMaxY - outMinY + 1; if(outWidth <= 0 || outHeight <= 0) return null; int inMinX = (outMinX - dstOffsetX)*subPeriodX + subOriginX; int inMaxX = (outMaxX - dstOffsetX)*subPeriodX + subOriginX; int inWidth = inMaxX - inMinX + 1; int inMinY = (outMinY - dstOffsetY)*subPeriodY + subOriginY; int inMaxY = (outMaxY - dstOffsetY)*subPeriodY + subOriginY; int inHeight = inMaxY - inMinY + 1; WritableRaster wr = raster.createCompatibleWritableRaster(outMinX, outMinY, outWidth, outHeight); int jMax = inMinY + inHeight; if(t == DataBuffer.TYPE_FLOAT || t == DataBuffer.TYPE_DOUBLE) { float[] fsamples = new float[inWidth]; float[] fsubsamples = new float[outWidth]; for(int k = 0; k < b; k++) { int outY = outMinY; for(int j = inMinY; j < jMax; j += subPeriodY) { raster.getSamples(inMinX, j, inWidth, 1, k, fsamples); int s = 0; for(int i = 0; i < inWidth; i += subPeriodX) { fsubsamples[s++] = fsamples[i]; } wr.setSamples(outMinX, outY++, outWidth, 1, k, fsubsamples); } } } else { int[] samples = new int[inWidth]; int[] subsamples = new int[outWidth]; for(int k = 0; k < b; k++) { int outY = outMinY; for(int j = inMinY; j < jMax; j += subPeriodY) { raster.getSamples(inMinX, j, inWidth, 1, k, samples); int s = 0; for(int i = 0; i < inWidth; i += subPeriodX) { subsamples[s++] = samples[i]; } wr.setSamples(outMinX, outY++, outWidth, 1, k, subsamples); } } } return wr.createChild(outMinX, outMinY, target.width, target.height, target.x, target.y, sourceBands); } public void replacePixels(RenderedImage image, ImageWriteParam param) throws IOException { synchronized(replacePixelsLock) { // Check state and parameters vis-a-vis ImageWriter specification. if (stream == null) { throw new IllegalStateException("stream == null!"); } if (image == null) { throw new IllegalArgumentException("image == null!"); } if (!inReplacePixelsNest) { throw new IllegalStateException ("No previous call to prepareReplacePixels!"); } // Subsampling values. int stepX = 1, stepY = 1, gridX = 0, gridY = 0; // Initialize the ImageWriteParam. if (param == null) { // Use the default. param = getDefaultWriteParam(); } else { // Make a copy of the ImageWriteParam. ImageWriteParam paramCopy = getDefaultWriteParam(); // Force uncompressed. paramCopy.setCompressionMode(ImageWriteParam.MODE_DISABLED); // Force tiling to remain as in the already written image. paramCopy.setTilingMode(ImageWriteParam.MODE_COPY_FROM_METADATA); // Retain source and destination region and band settings. paramCopy.setDestinationOffset(param.getDestinationOffset()); paramCopy.setSourceBands(param.getSourceBands()); paramCopy.setSourceRegion(param.getSourceRegion()); // Save original subsampling values for subsampling the // replacement data - not the data re-read from the image. stepX = param.getSourceXSubsampling(); stepY = param.getSourceYSubsampling(); gridX = param.getSubsamplingXOffset(); gridY = param.getSubsamplingYOffset(); // Replace the param. param = paramCopy; } // Check band count and bit depth compatibility. TIFFField f = replacePixelsMetadata.getTIFFField(BaselineTIFFTagSet.TAG_BITS_PER_SAMPLE); if(f == null) { throw new IIOException ("Cannot read destination BitsPerSample"); } int[] dstBitsPerSample = f.getAsInts(); int[] srcBitsPerSample = image.getSampleModel().getSampleSize(); int[] sourceBands = param.getSourceBands(); if(sourceBands != null) { if(sourceBands.length != dstBitsPerSample.length) { throw new IIOException ("Source and destination have different SamplesPerPixel"); } for(int i = 0; i < sourceBands.length; i++) { if(dstBitsPerSample[i] != srcBitsPerSample[sourceBands[i]]) { throw new IIOException ("Source and destination have different BitsPerSample"); } } } else { int srcNumBands = image.getSampleModel().getNumBands(); if(srcNumBands != dstBitsPerSample.length) { throw new IIOException ("Source and destination have different SamplesPerPixel"); } for(int i = 0; i < srcNumBands; i++) { if(dstBitsPerSample[i] != srcBitsPerSample[i]) { throw new IIOException ("Source and destination have different BitsPerSample"); } } } // Get the source image bounds. Rectangle srcImageBounds = new Rectangle(image.getMinX(), image.getMinY(), image.getWidth(), image.getHeight()); // Initialize the source rect. Rectangle srcRect = param.getSourceRegion(); if(srcRect == null) { srcRect = srcImageBounds; } // Set subsampling grid parameters. int subPeriodX = stepX; int subPeriodY = stepY; int subOriginX = gridX + srcRect.x; int subOriginY = gridY + srcRect.y; // Intersect with the source bounds. if(!srcRect.equals(srcImageBounds)) { srcRect = srcRect.intersection(srcImageBounds); if(srcRect.isEmpty()) { throw new IllegalArgumentException ("Source region does not intersect source image!"); } } // Get the destination offset. Point dstOffset = param.getDestinationOffset(); // Forward map source rectangle to determine destination width. int dMinX = XToTileX(srcRect.x, subOriginX, subPeriodX) + dstOffset.x; int dMinY = YToTileY(srcRect.y, subOriginY, subPeriodY) + dstOffset.y; int dMaxX = XToTileX(srcRect.x + srcRect.width, subOriginX, subPeriodX) + dstOffset.x; int dMaxY = YToTileY(srcRect.y + srcRect.height, subOriginY, subPeriodY) + dstOffset.y; // Initialize the destination rectangle. Rectangle dstRect = new Rectangle(dstOffset.x, dstOffset.y, dMaxX - dMinX, dMaxY - dMinY); // Intersect with the replacement region. dstRect = dstRect.intersection(replacePixelsRegion); if(dstRect.isEmpty()) { throw new IllegalArgumentException ("Forward mapped source region does not intersect destination region!"); } // Backward map to the active source region. int activeSrcMinX = (dstRect.x - dstOffset.x)*subPeriodX + subOriginX; int sxmax = (dstRect.x + dstRect.width - 1 - dstOffset.x)*subPeriodX + subOriginX; int activeSrcWidth = sxmax - activeSrcMinX + 1; int activeSrcMinY = (dstRect.y - dstOffset.y)*subPeriodY + subOriginY; int symax = (dstRect.y + dstRect.height - 1 - dstOffset.y)*subPeriodY + subOriginY; int activeSrcHeight = symax - activeSrcMinY + 1; Rectangle activeSrcRect = new Rectangle(activeSrcMinX, activeSrcMinY, activeSrcWidth, activeSrcHeight); if(activeSrcRect.intersection(srcImageBounds).isEmpty()) { throw new IllegalArgumentException ("Backward mapped destination region does not intersect source image!"); } if(reader == null) { reader = new TIFFImageReader(new TIFFImageReaderSpi()); } else { reader.reset(); } stream.mark(); try { stream.seek(headerPosition); reader.setInput(stream); this.imageMetadata = replacePixelsMetadata; this.param = param; SampleModel sm = image.getSampleModel(); ColorModel cm = image.getColorModel(); this.numBands = sm.getNumBands(); this.imageType = new ImageTypeSpecifier(image); this.periodX = param.getSourceXSubsampling(); this.periodY = param.getSourceYSubsampling(); this.sourceBands = null; int[] sBands = param.getSourceBands(); if (sBands != null) { this.sourceBands = sBands; this.numBands = sourceBands.length; } setupMetadata(cm, sm, reader.getWidth(replacePixelsIndex), reader.getHeight(replacePixelsIndex)); int[] scaleSampleSize = sm.getSampleSize(); initializeScaleTables(scaleSampleSize); // Determine whether bilevel. this.isBilevel = ImageUtil.isBinary(image.getSampleModel()); // Check for photometric inversion. this.isInverted = (nativePhotometricInterpretation == BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_BLACK_IS_ZERO && photometricInterpretation == BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_WHITE_IS_ZERO) || (nativePhotometricInterpretation == BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_WHITE_IS_ZERO && photometricInterpretation == BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_BLACK_IS_ZERO); // Analyze image data suitability for direct copy. this.isImageSimple = (isBilevel || (!isInverted && ImageUtil.imageIsContiguous(image))) && !isRescaling && // no value rescaling sourceBands == null && // no subbanding periodX == 1 && periodY == 1 && // no subsampling colorConverter == null; int minTileX = XToTileX(dstRect.x, 0, tileWidth); int minTileY = YToTileY(dstRect.y, 0, tileLength); int maxTileX = XToTileX(dstRect.x + dstRect.width - 1, 0, tileWidth); int maxTileY = YToTileY(dstRect.y + dstRect.height - 1, 0, tileLength); TIFFCompressor encoder = new TIFFNullCompressor(); encoder.setWriter(this); encoder.setStream(stream); encoder.setMetadata(this.imageMetadata); Rectangle tileRect = new Rectangle(); for(int ty = minTileY; ty <= maxTileY; ty++) { for(int tx = minTileX; tx <= maxTileX; tx++) { int tileIndex = ty*tilesAcross + tx; boolean isEmpty = replacePixelsByteCounts[tileIndex] == 0L; WritableRaster raster; if(isEmpty) { SampleModel tileSM = sm.createCompatibleSampleModel(tileWidth, tileLength); raster = Raster.createWritableRaster(tileSM, null); } else { BufferedImage tileImage = reader.readTile(replacePixelsIndex, tx, ty); raster = tileImage.getRaster(); } tileRect.setLocation(tx*tileWidth, ty*tileLength); tileRect.setSize(raster.getWidth(), raster.getHeight()); raster = raster.createWritableTranslatedChild(tileRect.x, tileRect.y); Rectangle replacementRect = tileRect.intersection(dstRect); int srcMinX = (replacementRect.x - dstOffset.x)*subPeriodX + subOriginX; int srcXmax = (replacementRect.x + replacementRect.width - 1 - dstOffset.x)*subPeriodX + subOriginX; int srcWidth = srcXmax - srcMinX + 1; int srcMinY = (replacementRect.y - dstOffset.y)*subPeriodY + subOriginY; int srcYMax = (replacementRect.y + replacementRect.height - 1 - dstOffset.y)*subPeriodY + subOriginY; int srcHeight = srcYMax - srcMinY + 1; Rectangle srcTileRect = new Rectangle(srcMinX, srcMinY, srcWidth, srcHeight); Raster replacementData = image.getData(srcTileRect); if(subPeriodX == 1 && subPeriodY == 1 && subOriginX == 0 && subOriginY == 0) { replacementData = replacementData.createChild(srcTileRect.x, srcTileRect.y, srcTileRect.width, srcTileRect.height, replacementRect.x, replacementRect.y, sourceBands); } else { replacementData = subsample(replacementData, sourceBands, subOriginX, subOriginY, subPeriodX, subPeriodY, dstOffset.x, dstOffset.y, replacementRect); if(replacementData == null) { continue; } } raster.setRect(replacementData); if(isEmpty) { stream.seek(nextSpace); } else { stream.seek(replacePixelsTileOffsets[tileIndex]); } this.image = new SingleTileRenderedImage(raster, cm); int numBytes = writeTile(tileRect, encoder); if(isEmpty) { // Update Strip/TileOffsets and // Strip/TileByteCounts fields. stream.mark(); stream.seek(replacePixelsOffsetsPosition + 4*tileIndex); stream.writeInt((int)nextSpace); stream.seek(replacePixelsByteCountsPosition + 4*tileIndex); stream.writeInt(numBytes); stream.reset(); // Increment location of next available space. nextSpace += numBytes; } } } } catch(IOException e) { throw e; } finally { stream.reset(); } } } public void replacePixels(Raster raster, ImageWriteParam param) throws IOException { if (raster == null) { throw new IllegalArgumentException("raster == null!"); } replacePixels(new SingleTileRenderedImage(raster, image.getColorModel()), param); } public void endReplacePixels() throws IOException { synchronized(replacePixelsLock) { if(!this.inReplacePixelsNest) { throw new IllegalStateException ("No previous call to prepareReplacePixels()!"); } replacePixelsIndex = -1; replacePixelsMetadata = null; replacePixelsTileOffsets = null; replacePixelsByteCounts = null; replacePixelsOffsetsPosition = 0L; replacePixelsByteCountsPosition = 0L; replacePixelsRegion = null; inReplacePixelsNest = false; } } // ----- END replacePixels methods ----- public void reset() { super.reset(); stream = null; image = null; imageType = null; byteOrder = null; param = null; compressor = null; colorConverter = null; streamMetadata = null; imageMetadata = null; isWritingSequence = false; isWritingEmpty = false; isInsertingEmpty = false; replacePixelsIndex = -1; replacePixelsMetadata = null; replacePixelsTileOffsets = null; replacePixelsByteCounts = null; replacePixelsOffsetsPosition = 0L; replacePixelsByteCountsPosition = 0L; replacePixelsRegion = null; inReplacePixelsNest = false; } public void dispose() { reset(); super.dispose(); } } class EmptyImage extends SimpleRenderedImage { EmptyImage(int minX, int minY, int width, int height, int tileGridXOffset, int tileGridYOffset, int tileWidth, int tileHeight, SampleModel sampleModel, ColorModel colorModel) { this.minX = minX; this.minY = minY; this.width = width; this.height = height; this.tileGridXOffset = tileGridXOffset; this.tileGridYOffset = tileGridYOffset; this.tileWidth = tileWidth; this.tileHeight = tileHeight; this.sampleModel = sampleModel; this.colorModel = colorModel; } public Raster getTile(int tileX, int tileY) { return null; } } ././@LongLink0000000000000000000000000000014600000000000011566 Lustar rootrootjai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/tiff/TIFFZLibCompressor.javajai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/tiff/TIFFZLibCompressor.jav0000664000175100017510000000462710203036165032457 0ustar tilletille/* * $RCSfile: TIFFZLibCompressor.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.1 $ * $Date: 2005-02-11 05:01:51 $ * $State: Exp $ */ package com.sun.media.imageioimpl.plugins.tiff; import com.sun.media.imageio.plugins.tiff.BaselineTIFFTagSet; import com.sun.media.imageio.plugins.tiff.TIFFCompressor; import java.io.IOException; import java.util.zip.Deflater; import javax.imageio.ImageWriteParam; /** * Compressor for ZLib compression. */ public class TIFFZLibCompressor extends TIFFDeflater { public TIFFZLibCompressor(ImageWriteParam param, int predictor) { super("ZLib", BaselineTIFFTagSet.COMPRESSION_ZLIB, param, predictor); } } ././@LongLink0000000000000000000000000000014500000000000011565 Lustar rootrootjai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/tiff/TIFFRLECompressor.javajai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/tiff/TIFFRLECompressor.java0000664000175100017510000001130510203036165032371 0ustar tilletille/* * $RCSfile: TIFFRLECompressor.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.1 $ * $Date: 2005-02-11 05:01:49 $ * $State: Exp $ */ package com.sun.media.imageioimpl.plugins.tiff; import com.sun.media.imageio.plugins.tiff.BaselineTIFFTagSet; import com.sun.media.imageio.plugins.tiff.TIFFCompressor; import java.io.IOException; import javax.imageio.IIOException; /** * */ public class TIFFRLECompressor extends TIFFFaxCompressor { public TIFFRLECompressor() { super("CCITT RLE", BaselineTIFFTagSet.COMPRESSION_CCITT_RLE, true); } /** * Encode a row of data using Modified Huffman Compression also known as * CCITT RLE (Run Lenth Encoding). * * @param data The row of data to compress. * @param rowOffset Starting index in data. * @param colOffset Bit offset within first data[rowOffset]. * @param rowLength Number of bits in the row. * @param compData The compressed data. * * @return The number of bytes saved in the compressed data array. */ public int encodeRLE(byte[] data, int rowOffset, int colOffset, int rowLength, byte[] compData) { // // Initialize bit buffer machinery. // initBitBuf(); // // Run-length encode line. // int outIndex = encode1D(data, rowOffset, colOffset, rowLength, compData, 0); // // Flush pending bits // while (ndex > 0) { compData[outIndex++] = (byte)(bits >>> 24); bits <<= 8; ndex -= 8; } // // Flip the bytes if inverse fill was requested. // if (inverseFill) { byte[] flipTable = TIFFFaxDecompressor.flipTable; for(int i = 0; i < outIndex; i++) { compData[i] = flipTable[compData[i] & 0xff]; } } return outIndex; } public int encode(byte[] b, int off, int width, int height, int[] bitsPerSample, int scanlineStride) throws IOException { if (bitsPerSample.length != 1 || bitsPerSample[0] != 1) { throw new IIOException( "Bits per sample must be 1 for RLE compression!"); } // In the worst case, 2 bits of input will result in 9 bits of output, // plus 2 extra bits if the row starts with black. int maxBits = 9*((width + 1)/2) + 2; byte[] compData = new byte[(maxBits + 7)/8]; int bytes = 0; int rowOffset = off; for (int i = 0; i < height; i++) { int rowBytes = encodeRLE(b, rowOffset, 0, width, compData); stream.write(compData, 0, rowBytes); rowOffset += scanlineStride; bytes += rowBytes; } return bytes; } } jai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/tiff/TIFFAttrInfo.java0000664000175100017510000000452410203036165031425 0ustar tilletille/* * $RCSfile: TIFFAttrInfo.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.1 $ * $Date: 2005-02-11 05:01:44 $ * $State: Exp $ */ package com.sun.media.imageioimpl.plugins.tiff; import javax.imageio.metadata.IIOMetadataFormat; public class TIFFAttrInfo { int valueType = IIOMetadataFormat.VALUE_ARBITRARY; int dataType; boolean isRequired = false; String defaultValue = null; String[] enumerations = null; String minValue = null; String maxValue = null; int listMinLength = 0; int listMaxLength = Integer.MAX_VALUE; public TIFFAttrInfo() { } } jai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/tiff/I18N.java0000664000175100017510000000420710203036165027703 0ustar tilletille/* * $RCSfile: I18N.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.1 $ * $Date: 2005-02-11 05:01:43 $ * $State: Exp $ */ package com.sun.media.imageioimpl.plugins.tiff; import com.sun.media.imageioimpl.common.I18NImpl; final class I18N extends I18NImpl { static String getString(String key) { return getString("com.sun.media.imageioimpl.plugins.tiff.I18N", key); } } ././@LongLink0000000000000000000000000000014600000000000011566 Lustar rootrootjai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/tiff/TIFFMetadataFormat.javajai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/tiff/TIFFMetadataFormat.jav0000664000175100017510000002352510203036165032431 0ustar tilletille/* * $RCSfile: TIFFMetadataFormat.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.1 $ * $Date: 2005-02-11 05:01:48 $ * $State: Exp $ */ package com.sun.media.imageioimpl.plugins.tiff; import java.util.Collection; import java.util.HashMap; import java.util.Iterator; import java.util.Locale; import java.util.Map; import java.util.MissingResourceException; import java.util.ResourceBundle; import javax.imageio.ImageTypeSpecifier; import javax.imageio.metadata.IIOMetadataFormat; import com.sun.media.imageio.plugins.tiff.BaselineTIFFTagSet; import com.sun.media.imageio.plugins.tiff.TIFFTag; import com.sun.media.imageio.plugins.tiff.TIFFTagSet; public abstract class TIFFMetadataFormat implements IIOMetadataFormat { protected Map elementInfoMap = new HashMap(); protected Map attrInfoMap = new HashMap(); protected String resourceBaseName; protected String rootName; public String getRootName() { return rootName; } private String getResource(String key, Locale locale) { if (locale == null) { locale = Locale.getDefault(); } try { ResourceBundle bundle = ResourceBundle.getBundle(resourceBaseName, locale); return bundle.getString(key); } catch (MissingResourceException e) { return null; } } private TIFFElementInfo getElementInfo(String elementName) { if (elementName == null) { throw new IllegalArgumentException("elementName == null!"); } TIFFElementInfo info = (TIFFElementInfo)elementInfoMap.get(elementName); if (info == null) { throw new IllegalArgumentException("No such element: " + elementName); } return info; } private TIFFAttrInfo getAttrInfo(String elementName, String attrName) { if (elementName == null) { throw new IllegalArgumentException("elementName == null!"); } if (attrName == null) { throw new IllegalArgumentException("attrName == null!"); } String key = elementName + "/" + attrName; TIFFAttrInfo info = (TIFFAttrInfo)attrInfoMap.get(key); if (info == null) { throw new IllegalArgumentException("No such attribute: " + key); } return info; } public int getElementMinChildren(String elementName) { TIFFElementInfo info = getElementInfo(elementName); return info.minChildren; } public int getElementMaxChildren(String elementName) { TIFFElementInfo info = getElementInfo(elementName); return info.maxChildren; } public String getElementDescription(String elementName, Locale locale) { if (!elementInfoMap.containsKey(elementName)) { throw new IllegalArgumentException("No such element: " + elementName); } return getResource(elementName, locale); } public int getChildPolicy(String elementName) { TIFFElementInfo info = getElementInfo(elementName); return info.childPolicy; } public String[] getChildNames(String elementName) { TIFFElementInfo info = getElementInfo(elementName); return info.childNames; } public String[] getAttributeNames(String elementName) { TIFFElementInfo info = getElementInfo(elementName); return info.attributeNames; } public int getAttributeValueType(String elementName, String attrName) { TIFFAttrInfo info = getAttrInfo(elementName, attrName); return info.valueType; } public int getAttributeDataType(String elementName, String attrName) { TIFFAttrInfo info = getAttrInfo(elementName, attrName); return info.dataType; } public boolean isAttributeRequired(String elementName, String attrName) { TIFFAttrInfo info = getAttrInfo(elementName, attrName); return info.isRequired; } public String getAttributeDefaultValue(String elementName, String attrName) { TIFFAttrInfo info = getAttrInfo(elementName, attrName); return info.defaultValue; } public String[] getAttributeEnumerations(String elementName, String attrName) { TIFFAttrInfo info = getAttrInfo(elementName, attrName); return info.enumerations; } public String getAttributeMinValue(String elementName, String attrName) { TIFFAttrInfo info = getAttrInfo(elementName, attrName); return info.minValue; } public String getAttributeMaxValue(String elementName, String attrName) { TIFFAttrInfo info = getAttrInfo(elementName, attrName); return info.maxValue; } public int getAttributeListMinLength(String elementName, String attrName) { TIFFAttrInfo info = getAttrInfo(elementName, attrName); return info.listMinLength; } public int getAttributeListMaxLength(String elementName, String attrName) { TIFFAttrInfo info = getAttrInfo(elementName, attrName); return info.listMaxLength; } public String getAttributeDescription(String elementName, String attrName, Locale locale) { String key = elementName + "/" + attrName; if (!attrInfoMap.containsKey(key)) { throw new IllegalArgumentException("No such attribute: " + key); } return getResource(key, locale); } public int getObjectValueType(String elementName) { TIFFElementInfo info = getElementInfo(elementName); return info.objectValueType; } public Class getObjectClass(String elementName) { TIFFElementInfo info = getElementInfo(elementName); if (info.objectValueType == VALUE_NONE) { throw new IllegalArgumentException( "Element cannot contain an object value: " + elementName); } return info.objectClass; } public Object getObjectDefaultValue(String elementName) { TIFFElementInfo info = getElementInfo(elementName); if (info.objectValueType == VALUE_NONE) { throw new IllegalArgumentException( "Element cannot contain an object value: " + elementName); } return info.objectDefaultValue; } public Object[] getObjectEnumerations(String elementName) { TIFFElementInfo info = getElementInfo(elementName); if (info.objectValueType == VALUE_NONE) { throw new IllegalArgumentException( "Element cannot contain an object value: " + elementName); } return info.objectEnumerations; } public Comparable getObjectMinValue(String elementName) { TIFFElementInfo info = getElementInfo(elementName); if (info.objectValueType == VALUE_NONE) { throw new IllegalArgumentException( "Element cannot contain an object value: " + elementName); } return info.objectMinValue; } public Comparable getObjectMaxValue(String elementName) { TIFFElementInfo info = getElementInfo(elementName); if (info.objectValueType == VALUE_NONE) { throw new IllegalArgumentException( "Element cannot contain an object value: " + elementName); } return info.objectMaxValue; } public int getObjectArrayMinLength(String elementName) { TIFFElementInfo info = getElementInfo(elementName); if (info.objectValueType == VALUE_NONE) { throw new IllegalArgumentException( "Element cannot contain an object value: " + elementName); } return info.objectArrayMinLength; } public int getObjectArrayMaxLength(String elementName) { TIFFElementInfo info = getElementInfo(elementName); if (info.objectValueType == VALUE_NONE) { throw new IllegalArgumentException( "Element cannot contain an object value: " + elementName); } return info.objectArrayMaxLength; } public TIFFMetadataFormat() {} } ././@LongLink0000000000000000000000000000015500000000000011566 Lustar rootrootjai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/tiff/TIFFCodecLibRLECompressor.javajai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/tiff/TIFFCodecLibRLECompres0000664000175100017510000001257310422271407032325 0ustar tilletille/* * $RCSfile: TIFFCodecLibRLECompressor.java,v $ * * * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.1 $ * $Date: 2006-04-22 00:04:23 $ * $State: Exp $ */ package com.sun.media.imageioimpl.plugins.tiff; import java.io.IOException; import javax.imageio.IIOException; public class TIFFCodecLibRLECompressor extends TIFFRLECompressor { private static final boolean DEBUG = false; // XXX 'false' for release!!! Object encoder; public TIFFCodecLibRLECompressor() { super(); try { com.sun.medialib.codec.g3fax.Encoder encoder = new com.sun.medialib.codec.g3fax.Encoder(); this.encoder = encoder; } catch(Throwable t) { throw new RuntimeException("CodecLib not available"); } } public int encode(byte[] b, int off, int width, int height, int[] bitsPerSample, int scanlineStride) throws IOException { if (bitsPerSample.length != 1 || bitsPerSample[0] != 1) { throw new IIOException ("Bits per sample must be 1 for RLE compression!"); } // Set image to data if possible; otherwise copy. int bytesPerRow = (width + 7)/8; byte[] image = null; if(off == 0 && bytesPerRow == scanlineStride) { image = b; } else { image = new byte[bytesPerRow*height]; int dataOffset = off; int imageOffset = 0; for(int row = 0; row < height; row++) { System.arraycopy(b, dataOffset, image, imageOffset, bytesPerRow); dataOffset += scanlineStride; imageOffset += bytesPerRow; } } // In the worst case, 2 bits of input will result in 9 bits of output, // plus 2 extra bits if the row starts with black. int maxBits = 9*((width + 1)/2) + 2; byte[] compData = new byte[((maxBits + 7)/8)*height]; // Attempt the codecLib encoder. com.sun.medialib.codec.g3fax.Encoder clibEncoder = (com.sun.medialib.codec.g3fax.Encoder)encoder; // Set RLE encoding flag. int encodingFlags = com.sun.medialib.codec.g3fax.Constants.G3FAX_RLE_CODING; if(inverseFill) { encodingFlags |= com.sun.medialib.codec.g3fax.Constants.G3FAX_LSB2MSB; if(DEBUG) { System.out.println("Setting LSB flag"); } } // Set result flag. int result = com.sun.medialib.codec.g3fax.Constants.G3FAX_FAILURE; try { if(DEBUG) { System.out.println("Using MediaLib RLE encoder"); } result = clibEncoder.encode(compData, image, width, height, 2, // k parameter encodingFlags); stream.write(compData, 0, result); } catch(Throwable t) { if(DEBUG) { System.out.println("MediaLib RLE encoder failed: "+t); } // XXX Should write a warning to listeners here. result = com.sun.medialib.codec.g3fax.Constants.G3FAX_FAILURE; } // If the codecLib encoder failed, try the superclass. if(result == com.sun.medialib.codec.g3fax.Constants.G3FAX_FAILURE) { if(DEBUG) { System.out.println("Falling back to Java RLE encoder"); } result = super.encode(b, off, width, height, bitsPerSample, scanlineStride); } return result; } } ././@LongLink0000000000000000000000000000015200000000000011563 Lustar rootrootjai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/tiff/TIFFBaseJPEGCompressor.javajai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/tiff/TIFFBaseJPEGCompressor0000664000175100017510000004543010666130750032365 0ustar tilletille/* * $RCSfile: TIFFBaseJPEGCompressor.java,v $ * * * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.5 $ * $Date: 2007-09-01 00:27:20 $ * $State: Exp $ */ package com.sun.media.imageioimpl.plugins.tiff; import com.sun.media.imageio.plugins.tiff.TIFFCompressor; import java.awt.Point; import java.awt.Transparency; import java.awt.color.ColorSpace; import java.awt.image.BufferedImage; import java.awt.image.ColorModel; import java.awt.image.ComponentColorModel; import java.awt.image.DataBuffer; import java.awt.image.DataBufferByte; import java.awt.image.PixelInterleavedSampleModel; import java.awt.image.Raster; import java.awt.image.SampleModel; import java.awt.image.WritableRaster; import java.io.IOException; import java.io.ByteArrayOutputStream; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Iterator; import javax.imageio.IIOException; import javax.imageio.IIOImage; import javax.imageio.ImageIO; import javax.imageio.ImageReader; import javax.imageio.ImageWriteParam; import javax.imageio.ImageWriter; import javax.imageio.metadata.IIOInvalidTreeException; import javax.imageio.metadata.IIOMetadata; import javax.imageio.metadata.IIOMetadataNode; import javax.imageio.spi.ImageWriterSpi; import javax.imageio.plugins.jpeg.JPEGImageWriteParam; import javax.imageio.stream.ImageOutputStream; import javax.imageio.stream.MemoryCacheImageOutputStream; import org.w3c.dom.Node; /** * Base class for all possible forms of JPEG compression in TIFF. */ public abstract class TIFFBaseJPEGCompressor extends TIFFCompressor { private static final boolean DEBUG = false; // XXX false for release. // Stream metadata format. protected static final String STREAM_METADATA_NAME = "javax_imageio_jpeg_stream_1.0"; // Image metadata format. protected static final String IMAGE_METADATA_NAME = "javax_imageio_jpeg_image_1.0"; // ImageWriteParam passed in. private ImageWriteParam param = null; /** * ImageWriteParam for JPEG writer. * May be initialized by {@link #initJPEGWriter()}. */ protected JPEGImageWriteParam JPEGParam = null; /** * The JPEG writer. * May be initialized by {@link #initJPEGWriter()}. */ protected ImageWriter JPEGWriter = null; /** * Whether to write abbreviated JPEG streams (default == false). * A subclass which sets this to true should also * initialized {@link #JPEGStreamMetadata}. */ protected boolean writeAbbreviatedStream = false; /** * Stream metadata equivalent to a tables-only stream such as in * the JPEGTables. Default value is null. * This should be set by any subclass which sets * {@link writeAbbreviatedStream} to true. */ protected IIOMetadata JPEGStreamMetadata = null; // A pruned image metadata object containing only essential nodes. private IIOMetadata JPEGImageMetadata = null; // Whether the codecLib native JPEG writer is being used. private boolean usingCodecLib; // Array-based output stream. private IIOByteArrayOutputStream baos; /** * Removes nonessential nodes from a JPEG native image metadata tree. * All nodes derived from JPEG marker segments other than DHT, DQT, * SOF, SOS segments are removed unless pruneTables is * true in which case the nodes derived from the DHT and * DQT marker segments are also removed. * * @param tree A javax_imageio_jpeg_image_1.0 tree. * @param pruneTables Whether to prune Huffman and quantization tables. * @throws IllegalArgumentException if tree is * null or is not the root of a JPEG native image * metadata tree. */ private static void pruneNodes(Node tree, boolean pruneTables) { if(tree == null) { throw new IllegalArgumentException("tree == null!"); } if(!tree.getNodeName().equals(IMAGE_METADATA_NAME)) { throw new IllegalArgumentException ("root node name is not "+IMAGE_METADATA_NAME+"!"); } if(DEBUG) { System.out.println("pruneNodes("+tree+","+pruneTables+")"); } // Create list of required nodes. List wantedNodes = new ArrayList(); wantedNodes.addAll(Arrays.asList(new String[] { "JPEGvariety", "markerSequence", "sof", "componentSpec", "sos", "scanComponentSpec" })); // Add Huffman and quantization table nodes if not pruning tables. if(!pruneTables) { wantedNodes.add("dht"); wantedNodes.add("dhtable"); wantedNodes.add("dqt"); wantedNodes.add("dqtable"); } IIOMetadataNode iioTree = (IIOMetadataNode)tree; List nodes = getAllNodes(iioTree, null); int numNodes = nodes.size(); for(int i = 0; i < numNodes; i++) { Node node = (Node)nodes.get(i); if(!wantedNodes.contains(node.getNodeName())) { if(DEBUG) { System.out.println("Removing "+node.getNodeName()); } node.getParentNode().removeChild(node); } } } private static List getAllNodes(IIOMetadataNode root, List nodes) { if(nodes == null) nodes = new ArrayList(); if(root.hasChildNodes()) { Node sibling = root.getFirstChild(); while(sibling != null) { nodes.add(sibling); nodes = getAllNodes((IIOMetadataNode)sibling, nodes); sibling = sibling.getNextSibling(); } } return nodes; } public TIFFBaseJPEGCompressor(String compressionType, int compressionTagValue, boolean isCompressionLossless, ImageWriteParam param) { super(compressionType, compressionTagValue, isCompressionLossless); this.param = param; } /** * A ByteArrayOutputStream which allows writing to an * ImageOutputStream. */ private static class IIOByteArrayOutputStream extends ByteArrayOutputStream { IIOByteArrayOutputStream() { super(); } IIOByteArrayOutputStream(int size) { super(size); } public synchronized void writeTo(ImageOutputStream ios) throws IOException { ios.write(buf, 0, count); } } /** * Initializes the JPEGWriter and JPEGParam instance variables. * This method must be called before encode() is invoked. * * @param supportsStreamMetadata Whether the JPEG writer must * support JPEG native stream metadata, i.e., be capable of writing * abbreviated streams. * @param supportsImageMetadata Whether the JPEG writer must * support JPEG native image metadata. */ protected void initJPEGWriter(boolean supportsStreamMetadata, boolean supportsImageMetadata) { // Reset the writer to null if it does not match preferences. if(this.JPEGWriter != null && (supportsStreamMetadata || supportsImageMetadata)) { ImageWriterSpi spi = this.JPEGWriter.getOriginatingProvider(); if(supportsStreamMetadata) { String smName = spi.getNativeStreamMetadataFormatName(); if(smName == null || !smName.equals(STREAM_METADATA_NAME)) { this.JPEGWriter = null; } } if(this.JPEGWriter != null && supportsImageMetadata) { String imName = spi.getNativeImageMetadataFormatName(); if(imName == null || !imName.equals(IMAGE_METADATA_NAME)) { this.JPEGWriter = null; } } } // Set the writer. if(this.JPEGWriter == null) { Iterator iter = ImageIO.getImageWritersByFormatName("jpeg"); while(iter.hasNext()) { // Get a writer. ImageWriter writer = (ImageWriter)iter.next(); // Verify its metadata support level. if(supportsStreamMetadata || supportsImageMetadata) { ImageWriterSpi spi = writer.getOriginatingProvider(); if(supportsStreamMetadata) { String smName = spi.getNativeStreamMetadataFormatName(); if(smName == null || !smName.equals(STREAM_METADATA_NAME)) { // Try the next one. continue; } } if(supportsImageMetadata) { String imName = spi.getNativeImageMetadataFormatName(); if(imName == null || !imName.equals(IMAGE_METADATA_NAME)) { // Try the next one. continue; } } } // Set the writer. this.JPEGWriter = writer; break; } if(this.JPEGWriter == null) { // XXX The exception thrown should really be an IIOException. throw new IllegalStateException ("No appropriate JPEG writers found!"); } } this.usingCodecLib = JPEGWriter.getClass().getName().startsWith("com.sun.media"); if(DEBUG) System.out.println("usingCodecLib = "+usingCodecLib); // Initialize the ImageWriteParam. if(this.JPEGParam == null) { if(param != null && param instanceof JPEGImageWriteParam) { JPEGParam = (JPEGImageWriteParam)param; } else { JPEGParam = new JPEGImageWriteParam(writer != null ? writer.getLocale() : null); if(param.getCompressionMode() == ImageWriteParam.MODE_EXPLICIT) { JPEGParam.setCompressionMode(ImageWriteParam.MODE_EXPLICIT); JPEGParam.setCompressionQuality(param.getCompressionQuality()); } } } } /** * Retrieves image metadata with non-core nodes removed. */ private IIOMetadata getImageMetadata(boolean pruneTables) throws IIOException { if(DEBUG) { System.out.println("getImageMetadata("+pruneTables+")"); } if(JPEGImageMetadata == null && IMAGE_METADATA_NAME.equals(JPEGWriter.getOriginatingProvider().getNativeImageMetadataFormatName())) { TIFFImageWriter tiffWriter = (TIFFImageWriter)this.writer; // Get default image metadata. JPEGImageMetadata = JPEGWriter.getDefaultImageMetadata(tiffWriter.imageType, JPEGParam); // Get the DOM tree. Node tree = JPEGImageMetadata.getAsTree(IMAGE_METADATA_NAME); // Remove unwanted marker segments. try { pruneNodes(tree, pruneTables); } catch(IllegalArgumentException e) { throw new IIOException("Error pruning unwanted nodes", e); } // Set the DOM back into the metadata. try { JPEGImageMetadata.setFromTree(IMAGE_METADATA_NAME, tree); } catch(IIOInvalidTreeException e) { // XXX This should really be a warning that image data // segments will be written with tables despite the // present of JPEGTables field. throw new IIOException ("Cannot set pruned image metadata!", e); } } return JPEGImageMetadata; } public final int encode(byte[] b, int off, int width, int height, int[] bitsPerSample, int scanlineStride) throws IOException { if (this.JPEGWriter == null) { throw new IIOException ("JPEG writer has not been initialized!"); } if (!((bitsPerSample.length == 3 && bitsPerSample[0] == 8 && bitsPerSample[1] == 8 && bitsPerSample[2] == 8) || (bitsPerSample.length == 1 && bitsPerSample[0] == 8))) { throw new IIOException ("Can only JPEG compress 8- and 24-bit images!"); } // Set the stream. ImageOutputStream ios; long initialStreamPosition; // usingCodecLib && !writeAbbreviatedStream if(usingCodecLib && !writeAbbreviatedStream) { ios = stream; initialStreamPosition = stream.getStreamPosition(); } else { // If not using codecLib then the stream has to be wrapped as // 1) the core Java Image I/O JPEG ImageWriter flushes the // stream at the end of each write() and this causes problems // for the TIFF writer, or 2) the codecLib JPEG ImageWriter // is using a stream on the native side which cannot be reset. if(baos == null) { baos = new IIOByteArrayOutputStream(); } else { baos.reset(); } ios = new MemoryCacheImageOutputStream(baos); initialStreamPosition = 0L; } JPEGWriter.setOutput(ios); // Create a DataBuffer. DataBufferByte dbb; if(off == 0 || usingCodecLib) { dbb = new DataBufferByte(b, b.length); } else { // // Workaround for bug in core Java Image I/O JPEG // ImageWriter which cannot handle non-zero offsets. // int bytesPerSegment = scanlineStride*height; byte[] btmp = new byte[bytesPerSegment]; System.arraycopy(b, off, btmp, 0, bytesPerSegment); dbb = new DataBufferByte(btmp, bytesPerSegment); off = 0; } // Set up the ColorSpace. int[] offsets; ColorSpace cs; if(bitsPerSample.length == 3) { offsets = new int[] { off, off + 1, off + 2 }; cs = ColorSpace.getInstance(ColorSpace.CS_sRGB); } else { offsets = new int[] { off }; cs = ColorSpace.getInstance(ColorSpace.CS_GRAY); } // Create the ColorModel. ColorModel cm = new ComponentColorModel(cs, false, false, Transparency.OPAQUE, DataBuffer.TYPE_BYTE); // Create the SampleModel. SampleModel sm = new PixelInterleavedSampleModel(DataBuffer.TYPE_BYTE, width, height, bitsPerSample.length, scanlineStride, offsets); // Create the WritableRaster. WritableRaster wras = Raster.createWritableRaster(sm, dbb, new Point(0, 0)); // Create the BufferedImage. BufferedImage bi = new BufferedImage(cm, wras, false, null); // Get the pruned JPEG image metadata (may be null). IIOMetadata imageMetadata = getImageMetadata(writeAbbreviatedStream); // Compress the image into the output stream. int compDataLength; if(usingCodecLib && !writeAbbreviatedStream) { // Write complete JPEG stream JPEGWriter.write(null, new IIOImage(bi, null, imageMetadata), JPEGParam); compDataLength = (int)(stream.getStreamPosition() - initialStreamPosition); } else { if(writeAbbreviatedStream) { // Write abbreviated JPEG stream // First write the tables-only data. JPEGWriter.prepareWriteSequence(JPEGStreamMetadata); ios.flush(); // Rewind to the beginning of the byte array. baos.reset(); // Write the abbreviated image data. IIOImage image = new IIOImage(bi, null, imageMetadata); JPEGWriter.writeToSequence(image, JPEGParam); JPEGWriter.endWriteSequence(); } else { // Write complete JPEG stream JPEGWriter.write(null, new IIOImage(bi, null, imageMetadata), JPEGParam); } compDataLength = baos.size(); baos.writeTo(stream); baos.reset(); } return compDataLength; } protected void finalize() throws Throwable { super.finalize(); if(JPEGWriter != null) { JPEGWriter.dispose(); } } } ././@LongLink0000000000000000000000000000015300000000000011564 Lustar rootrootjai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/tiff/TIFFOldJPEGDecompressor.javajai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/tiff/TIFFOldJPEGDecompresso0000664000175100017510000006377710672360220032370 0ustar tilletille/* * $RCSfile: TIFFOldJPEGDecompressor.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.4 $ * $Date: 2007-09-14 01:14:56 $ * $State: Exp $ */ package com.sun.media.imageioimpl.plugins.tiff; import java.awt.Point; import java.awt.image.BufferedImage; import java.io.IOException; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.util.Iterator; import javax.imageio.IIOException; import javax.imageio.ImageIO; import javax.imageio.ImageReader; import javax.imageio.ImageReadParam; import javax.imageio.plugins.jpeg.JPEGHuffmanTable; import javax.imageio.plugins.jpeg.JPEGImageReadParam; import javax.imageio.plugins.jpeg.JPEGQTable; import javax.imageio.stream.MemoryCacheImageInputStream; import javax.imageio.stream.ImageInputStream; import com.sun.media.imageio.plugins.tiff.BaselineTIFFTagSet; import com.sun.media.imageio.plugins.tiff.TIFFDecompressor; import com.sun.media.imageio.plugins.tiff.TIFFField; /** * TIFFDecompressor for "Old JPEG" compression. */ public class TIFFOldJPEGDecompressor extends TIFFJPEGDecompressor { private static final boolean DEBUG = false; // XXX 'false' for release // Start of Image // private static final int SOI = 0xD8; // now defined in superclass // Define Huffman Tables private static final int DHT = 0xC4; // Define Quantisation Tables private static final int DQT = 0xDB; // Define Restart Interval private static final int DRI = 0xDD; // Baseline DCT private static final int SOF0 = 0xC0; // Start of Scan private static final int SOS = 0xDA; // End of Image // private static final int EOI = 0xD9; // now defined in superclass // Whether the decompressor has been initialized. private boolean isInitialized = false; // // Instance variables set by the initialize() method. // // Offset to a complete, contiguous JPEG stream. private Long JPEGStreamOffset = null; // Offset to the SOF marker. private int SOFPosition = -1; // Value of the SOS marker. private byte[] SOSMarker = null; // Horizontal chroma subsampling factor. private int subsamplingX = 2; // Vertical chroma subsampling factor. private int subsamplingY = 2; public TIFFOldJPEGDecompressor() {} // // Intialize instance variables according to an analysis of the // TIFF field content. See bug 4929147 for test image information. // // Case 1: Image contains a single strip or tile and the offset to // that strip or tile points to an SOI marker. // // Example: // "Visionshape Inc. Compression Software, version 2.5" // ColorTiffWithBarcode.tif // Color2.tif (pages 2-5 (indexes 1-4) // color3.tif (pages 2-5 (indexes 1-4) // // "Kofax standard Multi-Page TIFF Storage Filter v2.01.000" // 01.tif (pages 1 and 3(indexes 0 and 2)) // // Instance variables set: JPEGStreamOffset // // Case 2: Image contains a single strip or tile and a // JPEGInterchangeFormat field is present but the // JPEGInterchangeFormatLength is erroneously missing. // // Example: // "Kofax standard Multi-Page TIFF Storage Filter v2.01.000" // 01.tif (pages 1 and 3(indexes 0 and 2)) // (but this example also satisfies case 1) // // Instance variables set: JPEGStreamOffset // // Case 3: Image contains a single strip or tile, the // JPEGInterchangeFormat and JPEGInterchangeFormatLength // fields are both present, the value of JPEGInterchangeFormat // is less than the offset to the strip or tile, and the sum // of the values of JPEGInterchangeFormat and // JPEGInterchangeFormatLength is greater than the offset to // the strip or tile. // // Instance variables set: JPEGStreamOffset // // Example: // "HP IL v1.1" // smallliz.tif from libtiff test data. // // Instance variables set: JPEGStreamOffset // // Cases 4-5 apply if none of cases 1-3 applies or the image has multiple // strips or tiles. // // Case 4: JPEGInterchangeFormat and JPEGInterchangeFormatLength are // present, the value of JPEGInterchangeFormatLength is at least 2, // and the sum of the values of these two fields is at most the // value of the offset to the first strip or tile. // // Instance variables set: tables, SOFPosition, SOSMarker // // Example: // "Oi/GFS, writer v00.06.00P, (c) Wang Labs, Inc. 1990, 1991" // 03.tif (pages 1 and 3(indexes 0 and 2)) // // "Oi/GFS, writer v00.06.02" // Color2.tif (page 1 (index 0)) // color3.tif (page 1 (index 0)) // // Case 5: If none of the foregoing cases apply. For this case the // JPEGQTables, JPEGACTables, and JPEGDCTables must be valid. // // Instance variables set: tables, SOFPosition, SOSMarker // // Example: // "NeXT" // zackthecat.tif from libtiff test data. // private synchronized void initialize() throws IOException { if(isInitialized) { return; } // Get the TIFF metadata object. TIFFImageMetadata tim = (TIFFImageMetadata)metadata; // Get the JPEGInterchangeFormat field. TIFFField JPEGInterchangeFormatField = tim.getTIFFField(BaselineTIFFTagSet.TAG_JPEG_INTERCHANGE_FORMAT); // Get the tile or strip offsets. TIFFField segmentOffsetField = tim.getTIFFField(BaselineTIFFTagSet.TAG_TILE_OFFSETS); if(segmentOffsetField == null) { segmentOffsetField = tim.getTIFFField(BaselineTIFFTagSet.TAG_STRIP_OFFSETS); if(segmentOffsetField == null) { segmentOffsetField = JPEGInterchangeFormatField; } } long[] segmentOffsets = segmentOffsetField.getAsLongs(); // Determine whether the image has more than one strip or tile. boolean isTiled = segmentOffsets.length > 1; if(!isTiled) { // // If the image has only a single strip or tile and it looks // as if a complete JPEG stream is present then set the value // of JPEGStreamOffset to the offset of the JPEG stream; // otherwise leave JPEGStreamOffset set to null. // stream.seek(offset); stream.mark(); if(stream.read() == 0xff && stream.read() == SOI) { // Tile or strip offset points to SOI. JPEGStreamOffset = new Long(offset); // Set initialization flag and return. if(DEBUG) System.out.println("OLD JPEG CASE 1"); ((TIFFImageReader)reader).forwardWarningMessage("SOI marker detected at start of strip or tile."); isInitialized = true; stream.reset(); return; } stream.reset(); if(JPEGInterchangeFormatField != null) { // Get the value of JPEGInterchangeFormat. long jpegInterchangeOffset = JPEGInterchangeFormatField.getAsLong(0); // Check that the value of JPEGInterchangeFormat points to SOI. stream.mark(); stream.seek(jpegInterchangeOffset); if(stream.read() == 0xff && stream.read() == SOI) // JPEGInterchangeFormat offset points to SOI. JPEGStreamOffset = new Long(jpegInterchangeOffset); else ((TIFFImageReader)reader).forwardWarningMessage("JPEGInterchangeFormat does not point to SOI"); stream.reset(); // Get the JPEGInterchangeFormatLength field. TIFFField JPEGInterchangeFormatLengthField = tim.getTIFFField(BaselineTIFFTagSet.TAG_JPEG_INTERCHANGE_FORMAT_LENGTH); if(JPEGInterchangeFormatLengthField == null) { if(DEBUG) System.out.println("OLD JPEG CASE 2"); ((TIFFImageReader)reader).forwardWarningMessage("JPEGInterchangeFormatLength field is missing"); } else { // Get the JPEGInterchangeFormatLength field's value. long jpegInterchangeLength = JPEGInterchangeFormatLengthField.getAsLong(0); if(jpegInterchangeOffset < segmentOffsets[0] && (jpegInterchangeOffset + jpegInterchangeLength) > segmentOffsets[0]) { if(DEBUG) System.out.println("OLD JPEG CASE 3"); } else { if(DEBUG) System.out.println("OLD JPEG CASE 3A"); ((TIFFImageReader)reader).forwardWarningMessage("JPEGInterchangeFormatLength field value is invalid"); } } // Return if JPEGInterchangeFormat pointed to SOI. if(JPEGStreamOffset != null) { isInitialized = true; return; } } } // Get the subsampling factors. TIFFField YCbCrSubsamplingField = tim.getTIFFField(BaselineTIFFTagSet.TAG_Y_CB_CR_SUBSAMPLING); if(YCbCrSubsamplingField != null) { subsamplingX = YCbCrSubsamplingField.getAsChars()[0]; subsamplingY = YCbCrSubsamplingField.getAsChars()[1]; } // // Initialize the 'tables' instance variable either for later // use in prepending to individual abbreviated strips or tiles. // if(JPEGInterchangeFormatField != null) { // Get the value of JPEGInterchangeFormat. long jpegInterchangeOffset = JPEGInterchangeFormatField.getAsLong(0); // Get the JPEGInterchangeFormatLength field. TIFFField JPEGInterchangeFormatLengthField = tim.getTIFFField(BaselineTIFFTagSet.TAG_JPEG_INTERCHANGE_FORMAT_LENGTH); if(JPEGInterchangeFormatLengthField != null) { // Get the JPEGInterchangeFormatLength field's value. long jpegInterchangeLength = JPEGInterchangeFormatLengthField.getAsLong(0); if(jpegInterchangeLength >= 2 && jpegInterchangeOffset + jpegInterchangeLength <= segmentOffsets[0]) { // Determine the length excluding any terminal EOI marker // and allocate table memory. stream.mark(); stream.seek(jpegInterchangeOffset+jpegInterchangeLength-2); if(stream.read() == 0xff && stream.read() == EOI) { this.tables = new byte[(int)(jpegInterchangeLength-2)]; } else { this.tables = new byte[(int)jpegInterchangeLength]; } stream.reset(); // Read the tables. stream.mark(); stream.seek(jpegInterchangeOffset); stream.readFully(tables); stream.reset(); if(DEBUG) System.out.println("OLD JPEG CASE 4"); ((TIFFImageReader)reader).forwardWarningMessage("Incorrect JPEG interchange format: using JPEGInterchangeFormat offset to derive tables."); } else { ((TIFFImageReader)reader).forwardWarningMessage("JPEGInterchangeFormat+JPEGInterchangeFormatLength > offset to first strip or tile."); } } } if(this.tables == null) { // // Create tables-only stream in tables[] consisting of // SOI+DQTs+DHTs // ByteArrayOutputStream baos = new ByteArrayOutputStream();//XXX length // Save stream length; long streamLength = stream.length(); // SOI baos.write(0xff); baos.write(SOI); // Quantization Tables TIFFField f = tim.getTIFFField(BaselineTIFFTagSet.TAG_JPEG_Q_TABLES); if(f == null) { throw new IIOException("JPEGQTables field missing!"); } long[] off = f.getAsLongs(); for(int i = 0; i < off.length; i++) { baos.write(0xff); // Marker ID baos.write(DQT); char markerLength = (char)67; baos.write((markerLength >>> 8) & 0xff); // Length baos.write(markerLength & 0xff); baos.write(i); // Table ID and precision byte[] qtable = new byte[64]; if(streamLength != -1 && off[i] > streamLength) { throw new IIOException("JPEGQTables offset for index "+ i+" is not in the stream!"); } stream.seek(off[i]); stream.readFully(qtable); baos.write(qtable); // Table data } // Huffman Tables (k == 0 ? DC : AC). for(int k = 0; k < 2; k++) { int tableTagNumber = k == 0 ? BaselineTIFFTagSet.TAG_JPEG_DC_TABLES : BaselineTIFFTagSet.TAG_JPEG_AC_TABLES; f = tim.getTIFFField(tableTagNumber); String fieldName = tableTagNumber == BaselineTIFFTagSet.TAG_JPEG_DC_TABLES ? "JPEGDCTables" : "JPEGACTables"; if(f == null) { throw new IIOException(fieldName+" field missing!"); } off = f.getAsLongs(); for(int i = 0; i < off.length; i++) { baos.write(0xff); // Marker ID baos.write(DHT); byte[] blengths = new byte[16]; if(streamLength != -1 && off[i] > streamLength) { throw new IIOException(fieldName+" offset for index "+ i+" is not in the stream!"); } stream.seek(off[i]); stream.readFully(blengths); int numCodes = 0; for(int j = 0; j < 16; j++) { numCodes += blengths[j]&0xff; } char markerLength = (char)(19 + numCodes); baos.write((markerLength >>> 8) & 0xff); // Length baos.write(markerLength & 0xff); baos.write(i | (k << 4)); // Table ID and type baos.write(blengths); // Number of codes byte[] bcodes = new byte[numCodes]; stream.readFully(bcodes); baos.write(bcodes); // Codes } } // SOF0 baos.write((byte)0xff); // Marker identifier baos.write((byte)SOF0); short sval = (short)(8 + 3*samplesPerPixel); // Length baos.write((byte)((sval >>> 8) & 0xff)); baos.write((byte)(sval & 0xff)); baos.write((byte)8); // Data precision sval = (short)srcHeight; // Tile/strip height baos.write((byte)((sval >>> 8) & 0xff)); baos.write((byte)(sval & 0xff)); sval = (short)srcWidth; // Tile/strip width baos.write((byte)((sval >>> 8) & 0xff)); baos.write((byte)(sval & 0xff)); baos.write((byte)samplesPerPixel); // Number of components if(samplesPerPixel == 1) { baos.write((byte)1); // Component ID baos.write((byte)0x11); // Subsampling factor baos.write((byte)0); // Quantization table ID } else { // 3 for(int i = 0; i < 3; i++) { baos.write((byte)(i + 1)); // Component ID baos.write((i != 0) ? (byte)0x11 : (byte)(((subsamplingX & 0x0f) << 4) | (subsamplingY & 0x0f))); baos.write((byte)i); // Quantization table ID } }; // DRI (optional). f = tim.getTIFFField(BaselineTIFFTagSet.TAG_JPEG_RESTART_INTERVAL); if(f != null) { char restartInterval = f.getAsChars()[0]; if(restartInterval != 0) { baos.write((byte)0xff); // Marker identifier baos.write((byte)DRI); sval = 4; baos.write((byte)((sval >>> 8) & 0xff)); // Length baos.write((byte)(sval & 0xff)); // RestartInterval baos.write((byte)((restartInterval >>> 8) & 0xff)); baos.write((byte)(restartInterval & 0xff)); } } tables = baos.toByteArray(); if(DEBUG) System.out.println("OLD JPEG CASE 5"); } // // Check for presence of SOF marker and save its position. // int idx = 0; int idxMax = tables.length - 1; while(idx < idxMax) { if((tables[idx]&0xff) == 0xff && (tables[idx+1]&0xff) == SOF0) { SOFPosition = idx; break; } idx++; } // // If no SOF marker, add one. // if(SOFPosition == -1) { byte[] tmpTables = new byte[tables.length + 10 + 3*samplesPerPixel]; System.arraycopy(tables, 0, tmpTables, 0, tables.length); int tmpOffset = tables.length; SOFPosition = tables.length; tables = tmpTables; tables[tmpOffset++] = (byte)0xff; // Marker identifier tables[tmpOffset++] = (byte)SOF0; short sval = (short)(8 + 3*samplesPerPixel); // Length tables[tmpOffset++] = (byte)((sval >>> 8) & 0xff); tables[tmpOffset++] = (byte)(sval & 0xff); tables[tmpOffset++] = (byte)8; // Data precision sval = (short)srcHeight; // Tile/strip height tables[tmpOffset++] = (byte)((sval >>> 8) & 0xff); tables[tmpOffset++] = (byte)(sval & 0xff); sval = (short)srcWidth; // Tile/strip width tables[tmpOffset++] = (byte)((sval >>> 8) & 0xff); tables[tmpOffset++] = (byte)(sval & 0xff); tables[tmpOffset++] = (byte)samplesPerPixel; // Number of components if(samplesPerPixel == 1) { tables[tmpOffset++] = (byte)1; // Component ID tables[tmpOffset++] = (byte)0x11; // Subsampling factor tables[tmpOffset++] = (byte)0; // Quantization table ID } else { // 3 for(int i = 0; i < 3; i++) { tables[tmpOffset++] = (byte)(i + 1); // Component ID tables[tmpOffset++] = (i != 0) ? (byte)0x11 : (byte)(((subsamplingX & 0x0f) << 4) | (subsamplingY & 0x0f)); tables[tmpOffset++] = (byte)i; // Quantization table ID } }; } // // Initialize SOSMarker. // stream.mark(); stream.seek(segmentOffsets[0]); if(stream.read() == 0xff && stream.read() == SOS) { // // If the first segment starts with an SOS marker save it. // int SOSLength = (stream.read()<<8)|stream.read(); SOSMarker = new byte[SOSLength+2]; SOSMarker[0] = (byte)0xff; SOSMarker[1] = (byte)SOS; SOSMarker[2] = (byte)((SOSLength & 0xff00) >> 8); SOSMarker[3] = (byte)(SOSLength & 0xff); stream.readFully(SOSMarker, 4, SOSLength - 2); } else { // // Manufacture an SOS marker. // SOSMarker = new byte[2 + 6 + 2*samplesPerPixel]; int SOSMarkerIndex = 0; SOSMarker[SOSMarkerIndex++] = (byte)0xff; // Marker identifier SOSMarker[SOSMarkerIndex++] = (byte)SOS; short sval = (short)(6 + 2*samplesPerPixel); // Length SOSMarker[SOSMarkerIndex++] = (byte)((sval >>> 8) & 0xff); SOSMarker[SOSMarkerIndex++] = (byte)(sval & 0xff); // Number of components in scan SOSMarker[SOSMarkerIndex++] = (byte)samplesPerPixel; if(samplesPerPixel == 1) { SOSMarker[SOSMarkerIndex++] = (byte)1; // Component ID SOSMarker[SOSMarkerIndex++] = (byte)0; // Huffman table ID } else { // 3 for(int i = 0; i < 3; i++) { SOSMarker[SOSMarkerIndex++] = (byte)(i + 1); // Component ID SOSMarker[SOSMarkerIndex++] = (byte)((i << 4) | i); // Huffman table IDs } }; SOSMarker[SOSMarkerIndex++] = (byte)0; SOSMarker[SOSMarkerIndex++] = (byte)0x3f; SOSMarker[SOSMarkerIndex++] = (byte)0; } stream.reset(); // Set initialization flag. isInitialized = true; } // // The strategy for reading cases 1-3 is to treat the data as a complete // JPEG interchange stream located at JPEGStreamOffset. // // The strategy for cases 4-5 is to concatenate a tables stream created // in initialize() with the entropy coded data in each strip or tile. // public void decodeRaw(byte[] b, int dstOffset, int bitsPerPixel, int scanlineStride) throws IOException { initialize(); TIFFImageMetadata tim = (TIFFImageMetadata)metadata; if(JPEGStreamOffset != null) { stream.seek(JPEGStreamOffset.longValue()); JPEGReader.setInput(stream, false, true); } else { // Determine buffer length and allocate. int tableLength = tables.length; int bufLength = tableLength + SOSMarker.length + byteCount + 2; // 2 for EOI. byte[] buf = new byte[bufLength]; if(tables != null) { System.arraycopy(tables, 0, buf, 0, tableLength); } int bufOffset = tableLength; // Update the SOF dimensions. short sval = (short)srcHeight; // Tile/strip height buf[SOFPosition + 5] = (byte)((sval >>> 8) & 0xff); buf[SOFPosition + 6] = (byte)(sval & 0xff); sval = (short)srcWidth; // Tile/strip width buf[SOFPosition + 7] = (byte)((sval >>> 8) & 0xff); buf[SOFPosition + 8] = (byte)(sval & 0xff); // Seek to data. stream.seek(offset); // Add SOS marker if data segment does not start with one. byte[] twoBytes = new byte[2]; stream.readFully(twoBytes); if(!((twoBytes[0]&0xff) == 0xff && (twoBytes[1]&0xff) == SOS)) { // Segment does not start with SOS marker; // use the pre-calculated SOS marker. System.arraycopy(SOSMarker, 0, buf, bufOffset, SOSMarker.length); bufOffset += SOSMarker.length; } // Copy the segment data into the buffer. buf[bufOffset++] = twoBytes[0]; buf[bufOffset++] = twoBytes[1]; stream.readFully(buf, bufOffset, byteCount - 2); bufOffset += byteCount - 2; // EOI. buf[bufOffset++] = (byte)0xff; // Marker identifier buf[bufOffset++] = (byte)EOI; ByteArrayInputStream bais = new ByteArrayInputStream(buf, 0, bufOffset); ImageInputStream is = new MemoryCacheImageInputStream(bais); JPEGReader.setInput(is, true, true); } // Read real image JPEGParam.setDestination(rawImage); JPEGReader.read(0, JPEGParam); } protected void finalize() throws Throwable { super.finalize(); JPEGReader.dispose(); } } ././@LongLink0000000000000000000000000000014600000000000011566 Lustar rootrootjai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/tiff/TIFFJPEGCompressor.javajai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/tiff/TIFFJPEGCompressor.jav0000664000175100017510000002763610417024535032356 0ustar tilletille/* * $RCSfile: TIFFJPEGCompressor.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.3 $ * $Date: 2006-04-11 22:10:36 $ * $State: Exp $ */ package com.sun.media.imageioimpl.plugins.tiff; import com.sun.media.imageio.plugins.tiff.BaselineTIFFTagSet; import com.sun.media.imageio.plugins.tiff.TIFFField; import com.sun.media.imageio.plugins.tiff.TIFFTag; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.util.Iterator; import javax.imageio.ImageReader; import javax.imageio.ImageWriteParam; import javax.imageio.metadata.IIOMetadata; import javax.imageio.spi.IIORegistry; import javax.imageio.spi.ImageReaderSpi; import javax.imageio.spi.ServiceRegistry; import javax.imageio.stream.MemoryCacheImageInputStream; import javax.imageio.stream.MemoryCacheImageOutputStream; /** * Compressor for encoding compression type 7, TTN2/Adobe JPEG-in-TIFF. */ public class TIFFJPEGCompressor extends TIFFBaseJPEGCompressor { private static final boolean DEBUG = false; // XXX false for release. // Subsampling factor for chroma bands (Cb Cr). static final int CHROMA_SUBSAMPLING = 2; /** * A filter which identifies the ImageReaderSpi of a JPEG reader * which supports JPEG native stream metadata. */ private static class JPEGSPIFilter implements ServiceRegistry.Filter { JPEGSPIFilter() {} public boolean filter(Object provider) { ImageReaderSpi readerSPI = (ImageReaderSpi)provider; if(readerSPI != null) { String streamMetadataName = readerSPI.getNativeStreamMetadataFormatName(); if(streamMetadataName != null) { return streamMetadataName.equals(STREAM_METADATA_NAME); } else { return false; } } return false; } } /** * Retrieves a JPEG reader which supports native JPEG stream metadata. */ private static ImageReader getJPEGTablesReader() { ImageReader jpegReader = null; try { IIORegistry registry = IIORegistry.getDefaultInstance(); Class imageReaderClass = Class.forName("javax.imageio.spi.ImageReaderSpi"); Iterator readerSPIs = registry.getServiceProviders(imageReaderClass, new JPEGSPIFilter(), true); if(readerSPIs.hasNext()) { ImageReaderSpi jpegReaderSPI = (ImageReaderSpi)readerSPIs.next(); jpegReader = jpegReaderSPI.createReaderInstance(); } } catch(Exception e) { // Ignore it ... } return jpegReader; } public TIFFJPEGCompressor(ImageWriteParam param) { super("JPEG", BaselineTIFFTagSet.COMPRESSION_JPEG, false, param); } /** * Sets the value of the metadata field. * *

The implementation in this class also adds the TIFF fields * JPEGTables, YCbCrSubSampling, YCbCrPositioning, and * ReferenceBlackWhite superseding any prior settings of those * fields.

* * @param metadata the IIOMetadata object for the * image being written. * * @see #getMetadata() */ public void setMetadata(IIOMetadata metadata) { super.setMetadata(metadata); if (metadata instanceof TIFFImageMetadata) { TIFFImageMetadata tim = (TIFFImageMetadata)metadata; TIFFIFD rootIFD = tim.getRootIFD(); BaselineTIFFTagSet base = BaselineTIFFTagSet.getInstance(); TIFFField f = tim.getTIFFField(BaselineTIFFTagSet.TAG_SAMPLES_PER_PIXEL); int numBands = f.getAsInt(0); if(numBands == 1) { // Remove YCbCr fields not relevant for grayscale. rootIFD.removeTIFFField(BaselineTIFFTagSet.TAG_Y_CB_CR_SUBSAMPLING); rootIFD.removeTIFFField(BaselineTIFFTagSet.TAG_Y_CB_CR_POSITIONING); rootIFD.removeTIFFField(BaselineTIFFTagSet.TAG_REFERENCE_BLACK_WHITE); } else { // numBands == 3 // Replace YCbCr fields. // YCbCrSubSampling TIFFField YCbCrSubSamplingField = new TIFFField (base.getTag(BaselineTIFFTagSet.TAG_Y_CB_CR_SUBSAMPLING), TIFFTag.TIFF_SHORT, 2, new char[] {CHROMA_SUBSAMPLING, CHROMA_SUBSAMPLING}); rootIFD.addTIFFField(YCbCrSubSamplingField); // YCbCrPositioning TIFFField YCbCrPositioningField = new TIFFField (base.getTag(BaselineTIFFTagSet.TAG_Y_CB_CR_POSITIONING), TIFFTag.TIFF_SHORT, 1, new char[] {BaselineTIFFTagSet.Y_CB_CR_POSITIONING_CENTERED}); rootIFD.addTIFFField(YCbCrPositioningField); // ReferenceBlackWhite TIFFField referenceBlackWhiteField = new TIFFField (base.getTag(BaselineTIFFTagSet.TAG_REFERENCE_BLACK_WHITE), TIFFTag.TIFF_RATIONAL, 6, new long[][] { // no headroon/footroom {0, 1}, {255, 1}, {128, 1}, {255, 1}, {128, 1}, {255, 1} }); rootIFD.addTIFFField(referenceBlackWhiteField); } // JPEGTables field is written if and only if one is // already present in the metadata. If one is present // and has either zero length or does not represent a // valid tables-only stream, then a JPEGTables field // will be written initialized to the standard tables- // only stream written by the JPEG writer. // Retrieve the JPEGTables field. TIFFField JPEGTablesField = tim.getTIFFField(BaselineTIFFTagSet.TAG_JPEG_TABLES); // Initialize JPEG writer to one supporting abbreviated streams. if(JPEGTablesField != null) { // Intialize the JPEG writer to one that supports stream // metadata, i.e., abbreviated streams, and may or may not // support image metadata. initJPEGWriter(true, false); } // Write JPEGTables field if a writer supporting abbreviated // streams was available. if(JPEGTablesField != null && JPEGWriter != null) { if(DEBUG) System.out.println("Has JPEGTables ..."); // Set the abbreviated stream flag. this.writeAbbreviatedStream = true; //Branch based on field value count. if(JPEGTablesField.getCount() > 0) { if(DEBUG) System.out.println("JPEGTables > 0"); // Derive the stream metadata from the field. // Get the field values. byte[] tables = JPEGTablesField.getAsBytes(); // Create an input stream for the tables. ByteArrayInputStream bais = new ByteArrayInputStream(tables); MemoryCacheImageInputStream iis = new MemoryCacheImageInputStream(bais); // Read the tables stream using the JPEG reader. ImageReader jpegReader = getJPEGTablesReader(); jpegReader.setInput(iis); // Initialize the stream metadata object. try { JPEGStreamMetadata = jpegReader.getStreamMetadata(); } catch(Exception e) { // Fall back to default tables. JPEGStreamMetadata = null; } finally { jpegReader.reset(); } if(DEBUG) System.out.println(JPEGStreamMetadata); } if(JPEGStreamMetadata == null) { if(DEBUG) System.out.println("JPEGTables == 0"); // Derive the field from default stream metadata. // Get default stream metadata. JPEGStreamMetadata = JPEGWriter.getDefaultStreamMetadata(JPEGParam); // Create an output stream for the tables. ByteArrayOutputStream tableByteStream = new ByteArrayOutputStream(); MemoryCacheImageOutputStream tableStream = new MemoryCacheImageOutputStream(tableByteStream); // Write a tables-only stream. JPEGWriter.setOutput(tableStream); try { JPEGWriter.prepareWriteSequence(JPEGStreamMetadata); tableStream.flush(); JPEGWriter.endWriteSequence(); // Get the tables-only stream content. byte[] tables = tableByteStream.toByteArray(); if(DEBUG) System.out.println("tables.length = "+ tables.length); // Add the JPEGTables field. JPEGTablesField = new TIFFField (base.getTag(BaselineTIFFTagSet.TAG_JPEG_TABLES), TIFFTag.TIFF_UNDEFINED, tables.length, tables); rootIFD.addTIFFField(JPEGTablesField); } catch(Exception e) { // Do not write JPEGTables field. rootIFD.removeTIFFField(BaselineTIFFTagSet.TAG_JPEG_TABLES); this.writeAbbreviatedStream = false; } } } else { // Do not write JPEGTables field. // Remove any field present. rootIFD.removeTIFFField(BaselineTIFFTagSet.TAG_JPEG_TABLES); // Initialize the writer preferring codecLib. initJPEGWriter(false, false); } } } } jai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/raw/0000775000175100017510000000000011650556211026225 5ustar tilletillejai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/raw/RawImageReaderSpi.java0000664000175100017510000000744110413303155032362 0ustar tilletille/* * $RCSfile: RawImageReaderSpi.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.2 $ * $Date: 2006-03-31 19:43:40 $ * $State: Exp $ */ package com.sun.media.imageioimpl.plugins.raw; import java.util.Locale; import javax.imageio.spi.ImageReaderSpi; import javax.imageio.stream.ImageInputStream; import javax.imageio.spi.IIORegistry; import javax.imageio.spi.ServiceRegistry; import java.io.IOException; import javax.imageio.ImageReader; import javax.imageio.IIOException; import com.sun.media.imageio.stream.RawImageInputStream; import com.sun.media.imageioimpl.common.PackageUtil; public class RawImageReaderSpi extends ImageReaderSpi { private static String [] writerSpiNames = {"com.sun.media.imageioimpl.plugins.raw.RawImageWriterSpi"}; private static String[] formatNames = {"raw", "RAW"}; private static String[] entensions = {""}; private static String[] mimeType = {""}; private boolean registered = false; public RawImageReaderSpi() { super(PackageUtil.getVendor(), PackageUtil.getVersion(), formatNames, entensions, mimeType, "com.sun.media.imageioimpl.plugins.raw.RawImageReader", STANDARD_INPUT_TYPE, writerSpiNames, true, null, null, null, null, true, null, null, null, null); } public void onRegistration(ServiceRegistry registry, Class category) { if (registered) { return; } registered = true; } public String getDescription(Locale locale) { String desc = PackageUtil.getSpecificationTitle() + " Raw Image Reader"; return desc; } public boolean canDecodeInput(Object source) throws IOException { if (!(source instanceof RawImageInputStream)) { return false; } return true; } public ImageReader createReaderInstance(Object extension) throws IIOException { return new RawImageReader(this); } } ././@LongLink0000000000000000000000000000014500000000000011565 Lustar rootrootjai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/raw/RawImageWriteParam.javajai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/raw/RawImageWriteParam.java0000664000175100017510000000513410203036165032555 0ustar tilletille/* * $RCSfile: RawImageWriteParam.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.1 $ * $Date: 2005-02-11 05:01:42 $ * $State: Exp $ */ package com.sun.media.imageioimpl.plugins.raw; import java.awt.Rectangle; import java.awt.image.Raster; import java.awt.image.RenderedImage; import java.util.Collections; import java.util.Locale; import java.util.Iterator; import javax.imageio.ImageWriteParam; /** * A subclass of ImageWriteParam for writing images in * the RAW format. */ public class RawImageWriteParam extends ImageWriteParam { /** Constructor to set locales. */ public RawImageWriteParam(Locale locale) { super(locale); canWriteTiles = true; } /* public void setTilingMode(int mode) { if (mode == MODE_EXPLICIT) throw new IllegalArgumentException(I18N.getString("RawImageWriteParam0")); } */ } jai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/raw/RawImageReader.java0000664000175100017510000002465510203036165031715 0ustar tilletille/* * $RCSfile: RawImageReader.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.1 $ * $Date: 2005-02-11 05:01:42 $ * $State: Exp $ */ package com.sun.media.imageioimpl.plugins.raw; import java.awt.Point; import java.awt.Rectangle; import java.awt.Transparency; import java.awt.color.ColorSpace; import java.awt.image.BufferedImage; import java.awt.image.ColorModel; import java.awt.image.ComponentColorModel; import java.awt.image.ComponentSampleModel; import java.awt.image.DataBuffer; import java.awt.image.DataBufferByte; import java.awt.image.DataBufferInt; import java.awt.image.DataBufferUShort; import java.awt.image.IndexColorModel; import java.awt.image.MultiPixelPackedSampleModel; import java.awt.image.PixelInterleavedSampleModel; import java.awt.image.Raster; import java.awt.image.RenderedImage; import java.awt.image.SampleModel; import java.awt.image.WritableRaster; import javax.imageio.IIOException; import javax.imageio.ImageReader; import javax.imageio.ImageReadParam; import javax.imageio.ImageTypeSpecifier; import javax.imageio.metadata.IIOMetadata; import javax.imageio.spi.ImageReaderSpi; import javax.imageio.stream.ImageInputStream; import java.io.*; import java.util.ArrayList; import java.util.Hashtable; import java.util.Iterator; import java.util.StringTokenizer; import com.sun.media.imageio.stream.RawImageInputStream; /** This class is the Java Image IO plugin reader for Raw images. * It may subsample the image, clip the image, select sub-bands, * and shift the decoded image origin if the proper decoding parameter * are set in the provided PNMImageReadParam. */ public class RawImageReader extends ImageReader { /** The input stream where reads from */ private RawImageInputStream iis = null; /** Wrapper for the protected method computeRegions. So it * can be access from the classes which are not in ImageReader * hierachy. */ public static void computeRegionsWrapper(ImageReadParam param, int srcWidth, int srcHeight, BufferedImage image, Rectangle srcRegion, Rectangle destRegion) { computeRegions(param, srcWidth, srcHeight, image, srcRegion, destRegion) ; } /** Constructs RawImageReader from the provided * ImageReaderSpi. */ public RawImageReader(ImageReaderSpi originator) { super(originator); } /** Overrides the method defined in the superclass. * @throw ClassCastException If the provided input is not * an instance of RawImageInputImage */ public void setInput(Object input, boolean seekForwardOnly, boolean ignoreMetadata) { super.setInput(input, seekForwardOnly, ignoreMetadata); iis = (RawImageInputStream) input; // Always works } /** Overrides the method defined in the superclass. */ public int getNumImages(boolean allowSearch) throws IOException { return iis.getNumImages(); } public int getWidth(int imageIndex) throws IOException { checkIndex(imageIndex); return iis.getImageDimension(imageIndex).width; } public int getHeight(int imageIndex) throws IOException { checkIndex(imageIndex); return iis.getImageDimension(imageIndex).height; } public int getTileWidth(int imageIndex) throws IOException { checkIndex(imageIndex); return iis.getImageType().getSampleModel().getWidth(); } public int getTileHeight(int imageIndex) throws IOException { checkIndex(imageIndex); return iis.getImageType().getSampleModel().getHeight(); } private void checkIndex(int imageIndex) throws IOException { if (imageIndex <0 || imageIndex >= getNumImages(true)) { throw new IndexOutOfBoundsException(I18N.getString("RawImageReader0")); } } public Iterator getImageTypes(int imageIndex) throws IOException { checkIndex(imageIndex); ArrayList list = new ArrayList(1); list.add(iis.getImageType()); return list.iterator(); } public ImageReadParam getDefaultReadParam() { return new ImageReadParam(); } public IIOMetadata getImageMetadata(int imageIndex) throws IOException { return null; } public IIOMetadata getStreamMetadata() throws IOException { return null; } public boolean isRandomAccessEasy(int imageIndex) throws IOException { checkIndex(imageIndex); return true; } public BufferedImage read(int imageIndex, ImageReadParam param) throws IOException { if (param == null) param = getDefaultReadParam(); checkIndex(imageIndex); clearAbortRequest(); processImageStarted(imageIndex); BufferedImage bi = param.getDestination(); RawRenderedImage image = new RawRenderedImage(iis, this, param, imageIndex); Point offset = param.getDestinationOffset(); WritableRaster raster; if (bi == null) { ColorModel colorModel = image.getColorModel(); SampleModel sampleModel = image.getSampleModel(); // If the destination type is specified, use the color model of it. ImageTypeSpecifier type = param.getDestinationType(); if (type != null) colorModel = type.getColorModel(); raster = Raster.createWritableRaster( sampleModel.createCompatibleSampleModel(image.getMinX()+ image.getWidth(), image.getMinY() + image.getHeight()), new Point(0, 0)); bi = new BufferedImage(colorModel, raster, colorModel != null ? colorModel.isAlphaPremultiplied() : false, new Hashtable()); } else { raster = bi.getWritableTile(0, 0); } image.setDestImage(bi); image.readAsRaster(raster); image.clearDestImage(); if (abortRequested()) processReadAborted(); else processImageComplete(); return bi; } public RenderedImage readAsRenderedImage(int imageIndex, ImageReadParam param) throws java.io.IOException { if (param == null) param = getDefaultReadParam(); checkIndex(imageIndex); clearAbortRequest(); processImageStarted(0); RenderedImage image = new RawRenderedImage(iis, this, param, imageIndex); if (abortRequested()) processReadAborted(); else processImageComplete(); return image; } public Raster readRaster(int imageIndex, ImageReadParam param) throws IOException { BufferedImage bi = read(imageIndex, param); return bi.getData(); } public boolean canReadRaster() { return true; } public void reset() { super.reset(); iis = null; } /** Wrapper for the protected method processImageUpdate * So it can be access from the classes which are not in * ImageReader hierachy. */ public void processImageUpdateWrapper(BufferedImage theImage, int minX, int minY, int width, int height, int periodX, int periodY, int[] bands) { processImageUpdate(theImage, minX, minY, width, height, periodX, periodY, bands); } /** Wrapper for the protected method processImageProgress * So it can be access from the classes which are not in * ImageReader hierachy. */ public void processImageProgressWrapper(float percentageDone) { processImageProgress(percentageDone); } /** This method wraps the protected method abortRequested * to allow the abortions be monitored by J2KReadState. */ public boolean getAbortRequest() { return abortRequested(); } } jai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/raw/RawRenderedImage.java0000664000175100017510000014551310422264161032242 0ustar tilletille/* * $RCSfile: RawRenderedImage.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.2 $ * $Date: 2006-04-21 23:19:13 $ * $State: Exp $ */ package com.sun.media.imageioimpl.plugins.raw; import javax.imageio.stream.ImageInputStream; import java.awt.Dimension; import java.awt.Point; import java.awt.Rectangle; import java.awt.Transparency; import java.awt.color.ColorSpace; import java.awt.image.BufferedImage; import java.awt.image.BandedSampleModel; import java.awt.image.ColorModel; import java.awt.image.ComponentColorModel; import java.awt.image.ComponentSampleModel; import java.awt.image.DataBuffer; import java.awt.image.DataBufferByte; import java.awt.image.DataBufferDouble; import java.awt.image.DataBufferFloat; import java.awt.image.DataBufferInt; import java.awt.image.DataBufferShort; import java.awt.image.DataBufferUShort; import java.awt.image.DirectColorModel; import java.awt.image.IndexColorModel; import java.awt.image.MultiPixelPackedSampleModel; import java.awt.image.PixelInterleavedSampleModel; import java.awt.image.SinglePixelPackedSampleModel; import java.awt.image.Raster; import java.awt.image.RenderedImage; import java.awt.image.SampleModel; import java.awt.image.WritableRaster; import java.lang.reflect.Constructor; import java.lang.reflect.Method; import java.lang.reflect.InvocationTargetException; import java.io.*; import javax.imageio.ImageReadParam; import javax.imageio.ImageTypeSpecifier; import com.sun.media.imageio.stream.RawImageInputStream; import com.sun.media.imageioimpl.common.ImageUtil; import com.sun.media.imageioimpl.common.SimpleRenderedImage; public class RawRenderedImage extends SimpleRenderedImage { /** The sample model for the original image. */ private SampleModel originalSampleModel; private Raster currentTile; private Point currentTileGrid; /** The input stream we read from */ private RawImageInputStream iis = null; /** Caches the RawImageReader which creates this object. This * variable is used to monitor the abortion. */ private RawImageReader reader; /** The ImageReadParam to create this * renderedImage. */ private ImageReadParam param = null; // The image index in the stream private int imageIndex; /** The destination bounds. */ private Rectangle destinationRegion; private Rectangle originalRegion; private Point sourceOrigin; private Dimension originalDimension; private int maxXTile, maxYTile; /** The subsampling parameters. */ private int scaleX, scaleY, xOffset, yOffset; private int[] destinationBands = null; private int[] sourceBands = null; private int nComp; /** Coordinate transform is not needed from the source (image stream) * to the destination. */ private boolean noTransform = true; /** The raster for medialib tiles to share. */ private WritableRaster rasForATile; private BufferedImage destImage; /** The position of the first sample of this image in the stream. */ private long position; /** cache the size of the data for each tile in the stream. */ private long tileDataSize; /** The orginal number tiles in X direction. */ private int originalNumXTiles; public RawRenderedImage(RawImageInputStream iis, RawImageReader reader, ImageReadParam param, int imageIndex) throws IOException { this.iis = iis; this.reader = reader; this.param = param; this.imageIndex = imageIndex; this.position = iis.getImageOffset(imageIndex); this.originalDimension = iis.getImageDimension(imageIndex); ImageTypeSpecifier type = iis.getImageType(); sampleModel = originalSampleModel = type.getSampleModel(); colorModel = type.getColorModel(); // If the destination band is set used it sourceBands = (param == null) ? null : param.getSourceBands(); if (sourceBands == null) { nComp = originalSampleModel.getNumBands(); sourceBands = new int[nComp]; for (int i = 0; i < nComp; i++) sourceBands[i] = i; } else { sampleModel = originalSampleModel.createSubsetSampleModel(sourceBands); colorModel = ImageUtil.createColorModel(null, sampleModel); } nComp = sourceBands.length; destinationBands = (param == null) ? null : param.getDestinationBands(); if (destinationBands == null) { destinationBands = new int[nComp]; for (int i = 0; i < nComp; i++) destinationBands[i] = i; } Dimension dim = iis.getImageDimension(imageIndex); this.width = dim.width; this.height = dim.height; Rectangle sourceRegion = new Rectangle(0, 0, this.width, this.height); originalRegion = (Rectangle)sourceRegion.clone(); destinationRegion = (Rectangle)sourceRegion.clone(); if (param != null) { RawImageReader.computeRegionsWrapper(param, this.width, this.height, param.getDestination(), sourceRegion, destinationRegion); scaleX = param.getSourceXSubsampling(); scaleY = param.getSourceYSubsampling(); xOffset = param.getSubsamplingXOffset(); yOffset = param.getSubsamplingYOffset(); } sourceOrigin = new Point(sourceRegion.x, sourceRegion.y); if (!destinationRegion.equals(sourceRegion)) noTransform = false; this.tileDataSize = ImageUtil.getTileSize(originalSampleModel); this.tileWidth = originalSampleModel.getWidth(); this.tileHeight = originalSampleModel.getHeight(); this.tileGridXOffset = destinationRegion.x; this.tileGridYOffset = destinationRegion.y; this.originalNumXTiles = getNumXTiles(); this.width = destinationRegion.width; this.height = destinationRegion.height; this.minX = destinationRegion.x; this.minY = destinationRegion.y; sampleModel = sampleModel.createCompatibleSampleModel(tileWidth, tileHeight); maxXTile = originalDimension.width / tileWidth; maxYTile = originalDimension.height / tileHeight; } public synchronized Raster getTile(int tileX, int tileY) { if (currentTile != null && currentTileGrid.x == tileX && currentTileGrid.y == tileY) return currentTile; if (tileX >= getNumXTiles() || tileY >= getNumYTiles()) throw new IllegalArgumentException(I18N.getString("RawRenderedImage0")); try { iis.seek(position + (tileY * originalNumXTiles + tileX) * tileDataSize); int x = tileXToX(tileX); int y = tileYToY(tileY); currentTile = Raster.createWritableRaster(sampleModel, new Point(x, y)); if (noTransform) { switch (sampleModel.getDataType()) { case DataBuffer.TYPE_BYTE: byte[][] buf = ((DataBufferByte)currentTile.getDataBuffer()).getBankData(); for (int i = 0; i < buf.length; i++) iis.readFully(buf[i], 0, buf[i].length); break; case DataBuffer.TYPE_SHORT: short[][] sbuf = ((DataBufferShort)currentTile.getDataBuffer()).getBankData(); for (int i = 0; i < sbuf.length; i++) iis.readFully(sbuf[i], 0, sbuf[i].length); break; case DataBuffer.TYPE_USHORT: short[][] usbuf = ((DataBufferUShort)currentTile.getDataBuffer()).getBankData(); for (int i = 0; i < usbuf.length; i++) iis.readFully(usbuf[i], 0, usbuf[i].length); break; case DataBuffer.TYPE_INT: int[][] ibuf = ((DataBufferInt)currentTile.getDataBuffer()).getBankData(); for (int i = 0; i < ibuf.length; i++) iis.readFully(ibuf[i], 0, ibuf[i].length); break; case DataBuffer.TYPE_FLOAT: float[][] fbuf = ((DataBufferFloat)currentTile.getDataBuffer()).getBankData(); for (int i = 0; i < fbuf.length; i++) iis.readFully(fbuf[i], 0, fbuf[i].length); break; case DataBuffer.TYPE_DOUBLE: double[][] dbuf = ((DataBufferDouble)currentTile.getDataBuffer()).getBankData(); for (int i = 0; i < dbuf.length; i++) iis.readFully(dbuf[i], 0, dbuf[i].length); break; } } else { currentTile = readSubsampledRaster((WritableRaster)currentTile); } } catch (IOException e) { throw new RuntimeException(e); } if (currentTileGrid == null) currentTileGrid = new Point(tileX, tileY); else { currentTileGrid.x = tileX; currentTileGrid.y = tileY; } return currentTile; } public void readAsRaster(WritableRaster raster) throws java.io.IOException { readSubsampledRaster(raster); } private Raster readSubsampledRaster(WritableRaster raster) throws IOException { if (raster == null) raster = Raster.createWritableRaster( sampleModel.createCompatibleSampleModel(destinationRegion.x + destinationRegion.width, destinationRegion.y + destinationRegion.height), new Point(destinationRegion.x, destinationRegion.y)); int numBands = sourceBands.length; int dataType = sampleModel.getDataType(); int sampleSizeBit = DataBuffer.getDataTypeSize(dataType); int sampleSizeByte = (sampleSizeBit + 7) / 8; Rectangle destRect = raster.getBounds().intersection(destinationRegion); int offx = destinationRegion.x; int offy = destinationRegion.y; int sourceSX = (destRect.x - offx) * scaleX + sourceOrigin.x; int sourceSY = (destRect.y - offy) * scaleY + sourceOrigin.y; int sourceEX = (destRect.width - 1) * scaleX + sourceSX; int sourceEY = (destRect.height - 1) * scaleY + sourceSY; int startXTile = sourceSX / tileWidth; int startYTile = sourceSY / tileHeight; int endXTile = sourceEX / tileWidth; int endYTile = sourceEY / tileHeight; startXTile = clip(startXTile, 0, maxXTile); startYTile = clip(startYTile, 0, maxYTile); endXTile = clip(endXTile, 0, maxXTile); endYTile = clip(endYTile, 0, maxYTile); int totalXTiles = getNumXTiles(); int totalYTiles = getNumYTiles(); int totalTiles = totalXTiles * totalYTiles; //The line buffer for the source byte[] pixbuf = null; // byte buffer for the decoded pixels. short[] spixbuf = null; // byte buffer for the decoded pixels. int[] ipixbuf = null; // byte buffer for the decoded pixels. float[] fpixbuf = null; // byte buffer for the decoded pixels. double[] dpixbuf = null; // byte buffer for the decoded pixels. // A flag to show the ComponentSampleModel has a single data bank boolean singleBank = true; int pixelStride = 0; int scanlineStride = 0; int bandStride = 0; int[] bandOffsets = null; int[] bankIndices = null; if (originalSampleModel instanceof ComponentSampleModel) { ComponentSampleModel csm = (ComponentSampleModel)originalSampleModel; bankIndices = csm.getBankIndices(); int maxBank = 0; for (int i = 0; i < bankIndices.length; i++) if (maxBank > bankIndices[i]) maxBank = bankIndices[i]; if (maxBank > 0) singleBank = false; pixelStride = csm.getPixelStride(); scanlineStride = csm.getScanlineStride(); bandOffsets = csm.getBandOffsets(); for (int i = 0; i < bandOffsets.length; i++) if (bandStride < bandOffsets[i]) bandStride = bandOffsets[i]; } else if (originalSampleModel instanceof MultiPixelPackedSampleModel) { scanlineStride = ((MultiPixelPackedSampleModel)originalSampleModel).getScanlineStride(); } else if(originalSampleModel instanceof SinglePixelPackedSampleModel) { pixelStride = 1; scanlineStride = ((SinglePixelPackedSampleModel)originalSampleModel).getScanlineStride(); } // The dstination buffer for the raster byte[] destPixbuf = null; // byte buffer for the decoded pixels. short[] destSPixbuf = null; // byte buffer for the decoded pixels. int[] destIPixbuf = null; // byte buffer for the decoded pixels. float[] destFPixbuf = null; // byte buffer for the decoded pixels. double[] destDPixbuf = null; // byte buffer for the decoded pixels. int[] destBandOffsets = null; int destPixelStride = 0; int destScanlineStride = 0; int destSX = 0; // The first pixel for the destionation if (raster.getSampleModel() instanceof ComponentSampleModel) { ComponentSampleModel csm = (ComponentSampleModel)raster.getSampleModel(); bankIndices = csm.getBankIndices(); destBandOffsets = csm.getBandOffsets(); destPixelStride = csm.getPixelStride(); destScanlineStride = csm.getScanlineStride(); destSX = csm.getOffset(raster.getMinX() - raster.getSampleModelTranslateX(), raster.getMinY() - raster.getSampleModelTranslateY()) - destBandOffsets[0]; switch(dataType) { case DataBuffer.TYPE_BYTE: destPixbuf = ((DataBufferByte)raster.getDataBuffer()).getData(); break; case DataBuffer.TYPE_SHORT: destSPixbuf = ((DataBufferShort)raster.getDataBuffer()).getData(); break; case DataBuffer.TYPE_USHORT: destSPixbuf = ((DataBufferUShort)raster.getDataBuffer()).getData(); break; case DataBuffer.TYPE_INT: destIPixbuf = ((DataBufferInt)raster.getDataBuffer()).getData(); break; case DataBuffer.TYPE_FLOAT: destFPixbuf = ((DataBufferFloat)raster.getDataBuffer()).getData(); break; case DataBuffer.TYPE_DOUBLE: destDPixbuf = ((DataBufferDouble)raster.getDataBuffer()).getData(); break; } } else if (raster.getSampleModel() instanceof SinglePixelPackedSampleModel) { numBands = 1; bankIndices = new int[]{0}; destBandOffsets = new int[numBands]; for (int i = 0; i < numBands; i++) destBandOffsets[i] = 0; destPixelStride = 1; destScanlineStride = ((SinglePixelPackedSampleModel)raster.getSampleModel()).getScanlineStride(); } // Start the data delivery to the cached consumers tile by tile for(int y = startYTile; y <= endYTile; y++){ if (reader.getAbortRequest()) break; // Loop on horizontal tiles for(int x=startXTile; x <= endXTile; x++){ if (reader.getAbortRequest()) break; long tilePosition = position + (y * originalNumXTiles + x) * tileDataSize; iis.seek(tilePosition); float percentage = (x - startXTile + y * totalXTiles) / totalXTiles; int startX = x * tileWidth; int startY = y * tileHeight; int cTileHeight = tileHeight; int cTileWidth = tileWidth; if (startY + cTileHeight >= originalDimension.height) cTileHeight = originalDimension.height - startY; if (startX + cTileWidth >= originalDimension.width) cTileWidth = originalDimension.width - startX; int tx = startX; int ty = startY; // If source start position calculated by taking subsampling // into account is after the tile's start X position, adjust // the start position accordingly if (sourceSX > startX) { cTileWidth += startX - sourceSX; tx = sourceSX; startX = sourceSX; } if (sourceSY > startY) { cTileHeight += startY - sourceSY; ty = sourceSY; startY = sourceSY; } // If source end position calculated by taking subsampling // into account is prior to the tile's end X position, adjust // the tile width to read accordingly if (sourceEX < startX + cTileWidth -1) { cTileWidth += sourceEX - startX - cTileWidth + 1; } if (sourceEY < startY + cTileHeight - 1) { cTileHeight += sourceEY - startY - cTileHeight + 1; } // The start X in the destination int x1 = (startX + scaleX - 1 - sourceOrigin.x) / scaleX; int x2 = (startX + scaleX - 1 + cTileWidth - sourceOrigin.x) / scaleX; int lineLength = x2 - x1; x2 = (x2 - 1) * scaleX + sourceOrigin.x; int y1 = (startY + scaleY -1 - sourceOrigin.y) /scaleY; startX = x1 * scaleX + sourceOrigin.x; startY = y1 * scaleY + sourceOrigin.y; // offx is destination.x x1 += offx; y1 += offy; tx -= x * tileWidth; ty -= y * tileHeight; if (sampleModel instanceof MultiPixelPackedSampleModel) { MultiPixelPackedSampleModel mppsm = (MultiPixelPackedSampleModel)originalSampleModel; iis.skipBytes(mppsm.getOffset(tx, ty) * sampleSizeByte); int readBytes = (mppsm.getOffset(x2, 0) - mppsm.getOffset(startX, 0) + 1) * sampleSizeByte; int skipLength = (scanlineStride * scaleY - readBytes) * sampleSizeByte; readBytes *= sampleSizeByte; if (pixbuf == null || pixbuf.length < readBytes) pixbuf = new byte[readBytes]; int bitoff = mppsm.getBitOffset(tx); for (int l = 0, m = y1; l < cTileHeight; l += scaleY, m++) { if (reader.getAbortRequest()) break; iis.readFully(pixbuf, 0, readBytes); if (scaleX == 1) { if (bitoff != 0) { int mask1 = (255 << bitoff) & 255; int mask2 = ~mask1 & 255; int shift = 8 - bitoff; int n = 0; for (; n < readBytes -1; n++) pixbuf[n] = (byte)(((pixbuf[n] & mask2) << shift) | (pixbuf[n + 1] & mask1) >>bitoff); pixbuf[n] = (byte)((pixbuf[n] & mask2) << shift); } } else { int bit = 7 ; int pos = 0 ; int mask = 128; for (int n = 0, n1 = startX & 7; n < lineLength; n++, n1 += scaleX) { pixbuf[pos] = (byte)((pixbuf[pos] & ~(1 << bit)) | (((pixbuf[n1 >> 3] >> (7 - (n1 & 7))) & 1) << bit)); bit--; if (bit == -1) { bit = 7; pos++; } } } ImageUtil.setPackedBinaryData(pixbuf, raster, new Rectangle(x1, m, lineLength, 1)); iis.skipBytes(skipLength); if (destImage != null) reader.processImageUpdateWrapper(destImage, x1, m, cTileWidth, 1, 1, 1, destinationBands); reader.processImageProgressWrapper(percentage + (l - startY + 1.0F) / cTileHeight / totalTiles); } } else { int readLength, skipLength; if (pixelStride < scanlineStride) { readLength = cTileWidth * pixelStride; skipLength = (scanlineStride * scaleY - readLength) * sampleSizeByte; } else { readLength = cTileHeight * scanlineStride; skipLength = (pixelStride * scaleX - readLength) * sampleSizeByte; } //Allocate buffer for all the types switch (sampleModel.getDataType()) { case DataBuffer.TYPE_BYTE: if (pixbuf == null || pixbuf.length < readLength) pixbuf = new byte[readLength]; break; case DataBuffer.TYPE_SHORT: case DataBuffer.TYPE_USHORT: if (spixbuf == null || spixbuf.length < readLength) spixbuf = new short[readLength]; break; case DataBuffer.TYPE_INT: if (ipixbuf == null || ipixbuf.length < readLength) ipixbuf = new int[readLength]; break; case DataBuffer.TYPE_FLOAT: if (fpixbuf == null || fpixbuf.length < readLength) fpixbuf = new float[readLength]; break; case DataBuffer.TYPE_DOUBLE: if (dpixbuf == null || dpixbuf.length < readLength) dpixbuf = new double[readLength]; break; } if (sampleModel instanceof PixelInterleavedSampleModel) { iis.skipBytes((tx * pixelStride + ty * scanlineStride) * sampleSizeByte); // variables for ther loop int outerFirst, outerSecond, outerStep, outerBound; int innerStep, innerStep1, outerStep1; if (pixelStride < scanlineStride) { outerFirst = 0; outerSecond = y1; outerStep = scaleY; outerBound = cTileHeight; innerStep = scaleX * pixelStride; innerStep1 = destPixelStride; outerStep1 = destScanlineStride; } else { outerFirst = 0; outerSecond = x1; outerStep = scaleX; outerBound = cTileWidth; innerStep = scaleY * scanlineStride; innerStep1 = destScanlineStride; outerStep1 = destPixelStride; } int destPos = destSX + (y1 - raster.getSampleModelTranslateY()) * destScanlineStride + (x1 - raster.getSampleModelTranslateX()) * destPixelStride; for (int l = outerFirst, m = outerSecond; l < outerBound; l += outerStep, m++) { if (reader.getAbortRequest()) break; switch(dataType) { case DataBuffer.TYPE_BYTE: if (innerStep == numBands && innerStep1 == numBands) iis.readFully(destPixbuf, destPos, readLength); else iis.readFully(pixbuf, 0, readLength); break; case DataBuffer.TYPE_SHORT: case DataBuffer.TYPE_USHORT: if (innerStep == numBands && innerStep1 == numBands) { iis.readFully(destSPixbuf, destPos, readLength); } else iis.readFully(spixbuf, 0, readLength); break; case DataBuffer.TYPE_INT: if (innerStep == numBands && innerStep1 == numBands) iis.readFully(destIPixbuf, destPos, readLength); else iis.readFully(ipixbuf, 0, readLength); break; case DataBuffer.TYPE_FLOAT: if (innerStep == numBands && innerStep1 == numBands) iis.readFully(destFPixbuf, destPos, readLength); else iis.readFully(fpixbuf, 0, readLength); break; case DataBuffer.TYPE_DOUBLE: if (innerStep == numBands && innerStep1 == numBands) iis.readFully(destDPixbuf, destPos, readLength); else iis.readFully(dpixbuf, 0, readLength); break; } if (innerStep != numBands || innerStep1 != numBands) for (int b = 0; b < numBands; b++) { int destBandOffset = destBandOffsets[destinationBands[b]]; destPos += destBandOffset; int sourceBandOffset = bandOffsets[sourceBands[b]]; switch(dataType) { case DataBuffer.TYPE_BYTE: for (int m1 = 0, n = destPos; m1 < readLength; m1 += innerStep, n += innerStep1) { destPixbuf[n] = pixbuf[m1 + sourceBandOffset]; } break; case DataBuffer.TYPE_SHORT: case DataBuffer.TYPE_USHORT: for (int m1 = 0, n = destPos; m1 < readLength; m1 += innerStep, n += innerStep1) { destSPixbuf[n] = spixbuf[m1 + sourceBandOffset]; } break; case DataBuffer.TYPE_INT: for (int m1 = 0, n = destPos; m1 < readLength; m1 += innerStep, n += innerStep1) { destIPixbuf[n] = ipixbuf[m1 + sourceBandOffset]; } break; case DataBuffer.TYPE_FLOAT: for (int m1 = 0, n = destPos; m1 < readLength; m1 += innerStep, n += innerStep1) { destFPixbuf[n] = fpixbuf[m1 + sourceBandOffset]; } break; case DataBuffer.TYPE_DOUBLE: for (int m1 = 0, n = destPos; m1 < readLength; m1 += innerStep, n += innerStep1) { destDPixbuf[n] = dpixbuf[m1 + sourceBandOffset]; } break; } destPos -= destBandOffset; } iis.skipBytes(skipLength); destPos += outerStep1; if (destImage != null) if (pixelStride < scanlineStride) reader.processImageUpdateWrapper(destImage, x1, m, outerBound, 1, 1, 1, destinationBands); else reader.processImageUpdateWrapper(destImage, m, y1, 1, outerBound, 1, 1, destinationBands); reader.processImageProgressWrapper(percentage + (l + 1.0F) / outerBound / totalTiles); } } else if (sampleModel instanceof BandedSampleModel || sampleModel instanceof SinglePixelPackedSampleModel || bandStride == 0) { boolean isBanded = sampleModel instanceof BandedSampleModel; int bandSize = (int)ImageUtil.getBandSize(originalSampleModel); for (int b = 0; b < numBands; b++) { iis.seek(tilePosition + bandSize * sourceBands[b] * sampleSizeByte); int destBandOffset = destBandOffsets[destinationBands[b]]; iis.skipBytes((ty * scanlineStride + tx * pixelStride) * sampleSizeByte); // variables for ther loop int outerFirst, outerSecond, outerStep, outerBound; int innerStep, innerStep1, outerStep1; if (pixelStride < scanlineStride) { outerFirst = 0; outerSecond = y1; outerStep = scaleY; outerBound = cTileHeight; innerStep = scaleX * pixelStride; innerStep1 = destPixelStride; outerStep1 = destScanlineStride; } else { outerFirst = 0; outerSecond = x1; outerStep = scaleX; outerBound = cTileWidth; innerStep = scaleY * scanlineStride; innerStep1 = destScanlineStride; outerStep1 = destPixelStride; } int destPos = destSX + (y1 - raster.getSampleModelTranslateY())* destScanlineStride + (x1 - raster.getSampleModelTranslateX()) * destPixelStride + destBandOffset; int bank = bankIndices[destinationBands[b]]; switch(dataType) { case DataBuffer.TYPE_BYTE: destPixbuf = ((DataBufferByte)raster.getDataBuffer()).getData(bank); break; case DataBuffer.TYPE_SHORT: destSPixbuf = ((DataBufferShort)raster.getDataBuffer()).getData(bank); break; case DataBuffer.TYPE_USHORT: destSPixbuf = ((DataBufferUShort)raster.getDataBuffer()).getData(bank); break; case DataBuffer.TYPE_INT: destIPixbuf = ((DataBufferInt)raster.getDataBuffer()).getData(bank); break; case DataBuffer.TYPE_FLOAT: destFPixbuf = ((DataBufferFloat)raster.getDataBuffer()).getData(bank); break; case DataBuffer.TYPE_DOUBLE: destDPixbuf = ((DataBufferDouble)raster.getDataBuffer()).getData(bank); break; } for (int l = outerFirst, m = outerSecond; l < outerBound; l += outerStep, m++) { if (reader.getAbortRequest()) break; switch(dataType) { case DataBuffer.TYPE_BYTE: if (innerStep == 1 && innerStep1 == 1) { iis.readFully(destPixbuf, destPos, readLength); } else { iis.readFully(pixbuf, 0, readLength); for (int m1 = 0, n = destPos; m1 < readLength; m1 += innerStep, n += innerStep1) { destPixbuf[n] = pixbuf[m1]; } } break; case DataBuffer.TYPE_SHORT: case DataBuffer.TYPE_USHORT: if (innerStep == 1 && innerStep1 == 1) { iis.readFully(destSPixbuf, destPos, readLength); } else { iis.readFully(spixbuf, 0, readLength); for (int m1 = 0, n = destPos; m1 < readLength; m1 += innerStep, n += innerStep1) { destSPixbuf[n] = spixbuf[m1]; } } break; case DataBuffer.TYPE_INT: if (innerStep == 1 && innerStep1 == 1) { iis.readFully(destIPixbuf, destPos, readLength); } else { iis.readFully(ipixbuf, 0, readLength); for (int m1 = 0, n = destPos; m1 < readLength; m1 += innerStep, n += innerStep1) { destIPixbuf[n] = ipixbuf[m1]; } } break; case DataBuffer.TYPE_FLOAT: if (innerStep == 1 && innerStep1 == 1) { iis.readFully(destFPixbuf, destPos, readLength); } else { iis.readFully(fpixbuf, 0, readLength); for (int m1 = 0, n = destPos; m1 < readLength; m1 += innerStep, n += innerStep1) { destFPixbuf[n] = fpixbuf[m1]; } } break; case DataBuffer.TYPE_DOUBLE: if (innerStep == 1 && innerStep1 == 1) { iis.readFully(destDPixbuf, destPos, readLength); } else { iis.readFully(dpixbuf, 0, readLength); for (int m1 = 0, n = destPos; m1 < readLength; m1 += innerStep, n += innerStep1) { destDPixbuf[n] = dpixbuf[m1]; } } break; } iis.skipBytes(skipLength); destPos += outerStep1; if (destImage != null) { int[] destBands = new int[] {destinationBands[b]}; if (pixelStride < scanlineStride) reader.processImageUpdateWrapper(destImage, x1, m, outerBound, 1, 1, 1, destBands); else reader.processImageUpdateWrapper(destImage, m, y1, 1, outerBound, 1, 1, destBands); } reader.processImageProgressWrapper( (percentage + (l+1.0F)/outerBound/numBands/totalTiles) * 100.0F); } } } else if (sampleModel instanceof ComponentSampleModel) { //for the other case, may slow //Allocate buffer for all the types int bufferSize = (int)tileDataSize; switch (sampleModel.getDataType()) { case DataBuffer.TYPE_BYTE: if (pixbuf == null || pixbuf.length < tileDataSize) pixbuf = new byte[(int)tileDataSize]; iis.readFully(pixbuf, 0, (int)tileDataSize); break; case DataBuffer.TYPE_SHORT: case DataBuffer.TYPE_USHORT: bufferSize /= 2; if (spixbuf == null || spixbuf.length < bufferSize) spixbuf = new short[(int)bufferSize]; iis.readFully(spixbuf, 0, (int)bufferSize); break; case DataBuffer.TYPE_INT: bufferSize /= 4; if (ipixbuf == null || ipixbuf.length < bufferSize) ipixbuf = new int[(int)bufferSize]; iis.readFully(ipixbuf, 0, (int)bufferSize); break; case DataBuffer.TYPE_FLOAT: bufferSize /= 4; if (fpixbuf == null || fpixbuf.length < bufferSize) fpixbuf = new float[(int)bufferSize]; iis.readFully(fpixbuf, 0, (int)bufferSize); break; case DataBuffer.TYPE_DOUBLE: bufferSize /= 8; if (dpixbuf == null || dpixbuf.length < bufferSize) dpixbuf = new double[(int)bufferSize]; iis.readFully(dpixbuf, 0, (int)bufferSize); break; } for (int b = 0; b < numBands; b++) { int destBandOffset = destBandOffsets[destinationBands[b]]; int destPos = ((ComponentSampleModel)raster.getSampleModel()).getOffset( x1-raster.getSampleModelTranslateX(), y1-raster.getSampleModelTranslateY(), destinationBands[b]); int bank = bankIndices[destinationBands[b]]; switch(dataType) { case DataBuffer.TYPE_BYTE: destPixbuf = ((DataBufferByte)raster.getDataBuffer()).getData(bank); break; case DataBuffer.TYPE_SHORT: destSPixbuf = ((DataBufferShort)raster.getDataBuffer()).getData(bank); break; case DataBuffer.TYPE_USHORT: destSPixbuf = ((DataBufferUShort)raster.getDataBuffer()).getData(bank); break; case DataBuffer.TYPE_INT: destIPixbuf = ((DataBufferInt)raster.getDataBuffer()).getData(bank); break; case DataBuffer.TYPE_FLOAT: destFPixbuf = ((DataBufferFloat)raster.getDataBuffer()).getData(bank); break; case DataBuffer.TYPE_DOUBLE: destDPixbuf = ((DataBufferDouble)raster.getDataBuffer()).getData(bank); break; } int srcPos = ((ComponentSampleModel)originalSampleModel).getOffset(tx, ty, sourceBands[b]); int skipX = scaleX * pixelStride;; for (int l = 0, m = y1; l < cTileHeight; l += scaleY, m++) { if (reader.getAbortRequest()) break; switch(dataType) { case DataBuffer.TYPE_BYTE: for (int n = 0, m1 = srcPos, m2 = destPos; n < lineLength; n++, m1 += skipX, m2 += destPixelStride) destPixbuf[m2] = pixbuf[m1]; break; case DataBuffer.TYPE_SHORT: case DataBuffer.TYPE_USHORT: for (int n = 0, m1 = srcPos, m2 = destPos; n < lineLength; n++, m1 += skipX, m2 += destPixelStride) destSPixbuf[m2] = spixbuf[m1]; break; case DataBuffer.TYPE_INT: for (int n = 0, m1 = srcPos, m2 = destPos; n < lineLength; n++, m1 += skipX, m2 += destPixelStride) destIPixbuf[m2] = ipixbuf[m1]; break; case DataBuffer.TYPE_FLOAT: for (int n = 0, m1 = srcPos, m2 = destPos; n < lineLength; n++, m1 += skipX, m2 += destPixelStride) destFPixbuf[m2] = fpixbuf[m1]; break; case DataBuffer.TYPE_DOUBLE: for (int n = 0, m1 = srcPos, m2 = destPos; n < lineLength; n++, m1 += skipX, m2 += destPixelStride) destDPixbuf[m2] = dpixbuf[m1]; break; } destPos += destScanlineStride; srcPos += scanlineStride * scaleY; if (destImage != null) { int[] destBands = new int[] {destinationBands[b]}; reader.processImageUpdateWrapper(destImage, x1, m, cTileHeight, 1, 1, 1, destBands); } reader.processImageProgressWrapper(percentage + (l + 1.0F) / cTileHeight / numBands / totalTiles); } } } else { throw new IllegalArgumentException(I18N.getString("RawRenderedImage1")); } } } // End loop on horizontal tiles } // End loop on vertical tiles return raster; } public void setDestImage(BufferedImage image) { destImage = image; } public void clearDestImage() { destImage = null; } private int getTileNum(int x, int y) { int num = (y - getMinTileY()) * getNumXTiles() + x - getMinTileX(); if (num < 0 || num >= getNumXTiles() * getNumYTiles()) throw new IllegalArgumentException(I18N.getString("RawRenderedImage0")); return num; } private int clip(int value, int min, int max) { if (value < min) value = min; if (value > max) value = max; return value; } } jai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/raw/RawImageWriter.java0000664000175100017510000007666110203036165031773 0ustar tilletille/* * $RCSfile: RawImageWriter.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.1 $ * $Date: 2005-02-11 05:01:42 $ * $State: Exp $ */ package com.sun.media.imageioimpl.plugins.raw; import java.awt.Point; import java.awt.Rectangle; import java.awt.image.BandedSampleModel; import java.awt.image.ColorModel; import java.awt.image.ComponentSampleModel; import java.awt.image.DataBuffer; import java.awt.image.DataBufferByte; import java.awt.image.DataBufferShort; import java.awt.image.DataBufferUShort; import java.awt.image.DataBufferInt; import java.awt.image.DataBufferFloat; import java.awt.image.DataBufferDouble; import java.awt.image.IndexColorModel; import java.awt.image.MultiPixelPackedSampleModel; import java.awt.image.Raster; import java.awt.image.RenderedImage; import java.awt.image.SampleModel; import java.awt.image.SinglePixelPackedSampleModel; import java.awt.image.WritableRaster; import java.io.IOException; import javax.imageio.IIOImage; import javax.imageio.IIOException; import javax.imageio.ImageTypeSpecifier; import javax.imageio.ImageWriteParam; import javax.imageio.ImageWriter; import javax.imageio.metadata.IIOMetadata; import javax.imageio.metadata.IIOMetadataNode; import javax.imageio.metadata.IIOMetadataFormatImpl; import javax.imageio.metadata.IIOInvalidTreeException; import javax.imageio.spi.ImageWriterSpi; import javax.imageio.stream.ImageOutputStream; import com.sun.media.imageioimpl.common.ImageUtil; /** * The Java Image IO plugin writer for encoding a binary RenderedImage into * a Raw format. * *

The encoding process may clip, subsample or select bands using the * parameters specified in the ImageWriteParam. * * Thus, when read this raw image the proper image data type * should be provided. * * @see com.sun.media.imageio.plugins.RawImageWriteParam */ //

If the destination data is packed packed, the data is written in the // order defined by the sample model. That the data is packed is defined as // (1) if the sample model is SingleSamplePackedSampleModel or // BandedSampleModel; or (2) the pixel stride or sanline stride // equals to the band number; or (3) the pixel stride equals to the band // number multiply the tile height; or (4) the scanline stride equals to the // band number multiply the tile width; or (5) the data for a band is stored // in a separate data bank. // //

Otherwise, the data is reordered in a packed pixel interleaved format, // and then written into the stream. In this case the data order may be change. // For example, the original image data is in the order of //

 //        RRRRRRRRRRRRRRRRRRRR
 //        GGGGGGGGGGGGGGGGGGGG
 //        BBBBBBBBBBBBBBBBBBBB
 //        RRRRRRRRRRRRRRRRRRRR
 //        GGGGGGGGGGGGGGGGGGGG
 //        BBBBBBBBBBBBBBBBBBBB
 // 
// // , and only the G and B bands are written in the stream. So the data in the // stream will be in the order of //
 //       GBGBGBGBGBGBGB
 // 
. public class RawImageWriter extends ImageWriter { /** The output stream to write into */ private ImageOutputStream stream = null; /** The image index in this stream. */ private int imageIndex; /** The tile width for encoding */ private int tileWidth; /** The tile height for encoding */ private int tileHeight; /** The tile grid offset for encoding */ private int tileXOffset, tileYOffset; /** The source -> destination transformation */ private int scaleX, scaleY, xOffset, yOffset; /** The source bands to be encoded. */ private int[] sourceBands = null; /** The number of components in the image */ private int numBands; /** The source raster if write raster. */ private RenderedImage input; /** The input source raster. */ private Raster inputRaster; private Rectangle destinationRegion = null; private SampleModel sampleModel; /** Coordinate transform or sub selection is needed before encoding. */ private boolean noTransform = true; private boolean noSubband = true; /** Indicates a raster rather than a RenderedImage * to be encoded. */ private boolean writeRaster = false; /** Whether can write optimally. */ private boolean optimal = false; /** The strides for pixel, band, and scanline. */ private int pxlStride, lineStride, bandStride; /** Constructs RawImageWriter based on the provided * ImageWriterSpi. */ public RawImageWriter(ImageWriterSpi originator) { super(originator); } public void setOutput(Object output) { super.setOutput(output); // validates output if (output != null) { if (!(output instanceof ImageOutputStream)) throw new IllegalArgumentException(I18N.getString("RawImageWriter0")); this.stream = (ImageOutputStream)output; } else this.stream = null; } public IIOMetadata getDefaultStreamMetadata(ImageWriteParam param) { return null; } public IIOMetadata getDefaultImageMetadata(ImageTypeSpecifier imageType, ImageWriteParam param) { return null; } public IIOMetadata convertStreamMetadata(IIOMetadata inData, ImageWriteParam param) { return null; } public IIOMetadata convertImageMetadata(IIOMetadata metadata, ImageTypeSpecifier type, ImageWriteParam param) { return null; } public boolean canWriteRasters() { return true; } public ImageWriteParam getDefaultWriteParam() { return new RawImageWriteParam(getLocale()); } public void write(IIOMetadata streamMetadata, IIOImage image, ImageWriteParam param) throws IOException { clearAbortRequest(); processImageStarted(imageIndex++); if (param == null) param = getDefaultWriteParam(); writeRaster = image.hasRaster(); Rectangle sourceRegion = param.getSourceRegion(); ColorModel colorModel = null; Rectangle originalRegion = null; if (writeRaster) { inputRaster = image.getRaster(); sampleModel = inputRaster.getSampleModel(); originalRegion = inputRaster.getBounds(); } else { input = image.getRenderedImage(); sampleModel = input.getSampleModel(); originalRegion = new Rectangle(input.getMinX(), input.getMinY(), input.getWidth(), input.getHeight()); colorModel = input.getColorModel(); } if (sourceRegion == null) sourceRegion = (Rectangle)originalRegion.clone(); else sourceRegion = sourceRegion.intersection(originalRegion); if (sourceRegion.isEmpty()) throw new RuntimeException(I18N.getString("RawImageWriter1")); scaleX = param.getSourceXSubsampling(); scaleY = param.getSourceYSubsampling(); xOffset = param.getSubsamplingXOffset(); yOffset = param.getSubsamplingYOffset(); sourceRegion.translate(xOffset, yOffset); sourceRegion.width -= xOffset; sourceRegion.height -= yOffset; xOffset = sourceRegion.x % scaleX; yOffset = sourceRegion.y % scaleY; int minX = sourceRegion.x / scaleX; int minY = sourceRegion.y / scaleY; int w = (sourceRegion.width + scaleX - 1) / scaleX; int h = (sourceRegion.height + scaleY - 1) / scaleY; destinationRegion = new Rectangle(minX, minY, w, h); noTransform = destinationRegion.equals(originalRegion); tileHeight = sampleModel.getHeight(); tileWidth = sampleModel.getWidth(); if (noTransform) { if (writeRaster) { tileXOffset = inputRaster.getMinX(); tileYOffset = inputRaster.getMinY(); } else { tileXOffset = input.getTileGridXOffset(); tileYOffset = input.getTileGridYOffset(); } } else { tileXOffset = destinationRegion.x; tileYOffset = destinationRegion.y; } sourceBands = param.getSourceBands(); boolean noSubband = true; numBands = sampleModel.getNumBands(); if (sourceBands != null) { sampleModel = sampleModel.createSubsetSampleModel(sourceBands); colorModel = null; noSubband = false; numBands = sampleModel.getNumBands(); } else { sourceBands = new int[numBands]; for (int i = 0; i < numBands; i++) sourceBands[i] = i; } if (sampleModel instanceof ComponentSampleModel) { ComponentSampleModel csm = (ComponentSampleModel)sampleModel; int[] bandOffsets = csm.getBandOffsets(); bandStride = bandOffsets[0]; for (int i = 1; i < bandOffsets.length; i++) if (bandStride > bandOffsets[i]) bandStride = bandOffsets[i]; int[] bankIndices = csm.getBankIndices(); int numBank = bankIndices[0]; for (int i = 1; i < bankIndices.length; i++) if (numBank > bankIndices[i]) numBank = bankIndices[i]; pxlStride = csm.getPixelStride(); lineStride = csm.getScanlineStride(); optimal = bandStride == 0 || (pxlStride < lineStride && pxlStride == numBands) || (lineStride < pxlStride && lineStride == numBands) || (pxlStride < lineStride && lineStride == numBands * csm.getWidth()) || (lineStride < pxlStride && pxlStride == numBands * csm.getHeight()) || csm instanceof BandedSampleModel; } else if (sampleModel instanceof SinglePixelPackedSampleModel || sampleModel instanceof MultiPixelPackedSampleModel) { optimal = true; } int numXTiles = getMaxTileX() - getMinTileX() + 1; int totalTiles = numXTiles * (getMaxTileY() - getMinTileY() + 1); for (int y = getMinTileY(); y <= getMaxTileY(); y++) { for (int x = getMinTileX(); x <= getMaxTileX(); x++) { writeRaster(getTile(x, y)); float percentage = (x + y * numXTiles + 1.0F) / totalTiles; processImageProgress(percentage * 100.0F); } } stream.flush(); if (abortRequested()) processWriteAborted(); else processImageComplete(); } //XXX: just for test public int getWidth() { return destinationRegion.width; } public int getHeight() { return destinationRegion.height; } private void writeRaster(Raster raster) throws IOException { int numBank = 0; int bandStride = 0; int[] bankIndices = null; int[] bandOffsets = null; int bandSize = 0; int numBand = sampleModel.getNumBands(); int type = sampleModel.getDataType(); if (sampleModel instanceof ComponentSampleModel) { ComponentSampleModel csm = (ComponentSampleModel)sampleModel; bandOffsets = csm.getBandOffsets(); for (int i = 0; i < numBand; i++) if (bandStride < bandOffsets[i]) bandStride = bandOffsets[i]; bankIndices = csm.getBankIndices(); for (int i = 0; i < numBand; i++) if (numBank < bankIndices[i]) numBank = bankIndices[i]; bandSize = (int)ImageUtil.getBandSize(sampleModel) ; } byte[] bdata = null; short[] sdata = null; int[] idata = null; float[] fdata = null; double[] ddata = null; if (raster.getParent() != null && !sampleModel.equals(raster.getParent().getSampleModel())) { WritableRaster ras = Raster.createWritableRaster(sampleModel, new Point(raster.getMinX(), raster.getMinY())); ras.setRect(raster); raster = ras; } DataBuffer data = raster.getDataBuffer(); if (optimal) { if (numBank > 0) { //multiple data bank for (int i = 0; i < numBands; i++) { int bank = bankIndices[sourceBands[i]]; switch (type) { case DataBuffer.TYPE_BYTE: bdata = ((DataBufferByte)data).getData(bank); stream.write(bdata, 0, bdata.length); break; case DataBuffer.TYPE_SHORT: sdata = ((DataBufferShort)data).getData(bank); stream.writeShorts(sdata, 0, sdata.length); break; case DataBuffer.TYPE_USHORT: sdata = ((DataBufferUShort)data).getData(bank); stream.writeShorts(sdata, 0, sdata.length); break; case DataBuffer.TYPE_INT: idata = ((DataBufferInt)data).getData(bank); stream.writeInts(idata, 0, idata.length); break; case DataBuffer.TYPE_FLOAT: fdata = ((DataBufferFloat)data).getData(bank); stream.writeFloats(fdata, 0, fdata.length); break; case DataBuffer.TYPE_DOUBLE: ddata = ((DataBufferDouble)data).getData(bank); stream.writeDoubles(ddata, 0, ddata.length); break; } } } else { // Single data bank switch (type) { case DataBuffer.TYPE_BYTE: bdata = ((DataBufferByte)data).getData(); break; case DataBuffer.TYPE_SHORT: sdata = ((DataBufferShort)data).getData(); break; case DataBuffer.TYPE_USHORT: sdata = ((DataBufferUShort)data).getData(); break; case DataBuffer.TYPE_INT: idata = ((DataBufferInt)data).getData(); break; case DataBuffer.TYPE_FLOAT: fdata = ((DataBufferFloat)data).getData(); break; case DataBuffer.TYPE_DOUBLE: ddata = ((DataBufferDouble)data).getData(); break; } if (!noSubband && bandStride >= raster.getWidth() * raster.getHeight() * (numBands-1)) { for (int i = 0; i < numBands; i++) { int offset = bandOffsets[sourceBands[i]]; switch (type) { case DataBuffer.TYPE_BYTE: stream.write(bdata, offset, bandSize); break; case DataBuffer.TYPE_SHORT: case DataBuffer.TYPE_USHORT: stream.writeShorts(sdata, offset, bandSize); break; case DataBuffer.TYPE_INT: stream.writeInts(idata, offset, bandSize); break; case DataBuffer.TYPE_FLOAT: stream.writeFloats(fdata, offset, bandSize); break; case DataBuffer.TYPE_DOUBLE: stream.writeDoubles(ddata, offset, bandSize); break; } } } else { switch (type) { case DataBuffer.TYPE_BYTE: stream.write(bdata, 0, bdata.length); break; case DataBuffer.TYPE_SHORT: case DataBuffer.TYPE_USHORT: stream.writeShorts(sdata, 0, sdata.length); break; case DataBuffer.TYPE_INT: stream.writeInts(idata, 0, idata.length); break; case DataBuffer.TYPE_FLOAT: stream.writeFloats(fdata, 0, fdata.length); break; case DataBuffer.TYPE_DOUBLE: stream.writeDoubles(ddata, 0, ddata.length); break; } } } } else if (sampleModel instanceof ComponentSampleModel) { // The others, must be a ComponentSampleModel switch (type) { case DataBuffer.TYPE_BYTE: bdata = ((DataBufferByte)data).getData(); break; case DataBuffer.TYPE_SHORT: sdata = ((DataBufferShort)data).getData(); break; case DataBuffer.TYPE_USHORT: sdata = ((DataBufferUShort)data).getData(); break; case DataBuffer.TYPE_INT: idata = ((DataBufferInt)data).getData(); break; case DataBuffer.TYPE_FLOAT: fdata = ((DataBufferFloat)data).getData(); break; case DataBuffer.TYPE_DOUBLE: ddata = ((DataBufferDouble)data).getData(); break; } ComponentSampleModel csm = (ComponentSampleModel)sampleModel; int offset = csm.getOffset(raster.getMinX()-raster.getSampleModelTranslateX(), raster.getMinY()-raster.getSampleModelTranslateY()) - bandOffsets[0]; int srcSkip = pxlStride; int copyLength = 1; int innerStep = pxlStride; int width = raster.getWidth(); int height = raster.getHeight(); int innerBound = width; int outerBound = height; if (srcSkip < lineStride) { if (bandStride > pxlStride) copyLength = width; srcSkip = lineStride; } else { if (bandStride > lineStride) copyLength = height; innerStep = lineStride; innerBound = height; outerBound = width; } int writeLength = innerBound * numBands; byte[] destBBuf = null; short[] destSBuf = null; int[] destIBuf = null; float[] destFBuf = null; double[] destDBuf = null; Object srcBuf = null; Object dstBuf = null; switch (type) { case DataBuffer.TYPE_BYTE: srcBuf = bdata; dstBuf = destBBuf = new byte[writeLength]; break; case DataBuffer.TYPE_SHORT: case DataBuffer.TYPE_USHORT: srcBuf = sdata; dstBuf = destSBuf = new short[writeLength]; break; case DataBuffer.TYPE_INT: srcBuf = idata; dstBuf = destIBuf = new int[writeLength]; break; case DataBuffer.TYPE_FLOAT: srcBuf = fdata; dstBuf = destFBuf = new float[writeLength]; break; case DataBuffer.TYPE_DOUBLE: srcBuf = ddata; dstBuf = destDBuf = new double[writeLength]; break; } if (copyLength > 1) { for (int i = 0; i < outerBound; i++) { for (int b = 0; b < numBands; b++) { int bandOffset = bandOffsets[b]; System.arraycopy(srcBuf, offset + bandOffset, dstBuf, b * innerBound, innerBound); } switch (type) { case DataBuffer.TYPE_BYTE: stream.write((byte[])dstBuf, 0, writeLength); break; case DataBuffer.TYPE_SHORT: case DataBuffer.TYPE_USHORT: stream.writeShorts((short[])dstBuf, 0, writeLength); break; case DataBuffer.TYPE_INT: stream.writeInts((int[])dstBuf, 0, writeLength); break; case DataBuffer.TYPE_FLOAT: stream.writeFloats((float[])dstBuf, 0, writeLength); break; case DataBuffer.TYPE_DOUBLE: stream.writeDoubles((double[])dstBuf, 0, writeLength); break; } offset += srcSkip; } } else { switch (type) { case DataBuffer.TYPE_BYTE: { for (int i = 0; i < outerBound; i++) { for (int b = 0, k = 0; b < numBands; b++) { int bandOffset = bandOffsets[b]; for (int j = 0, m = offset; j < innerBound; j++, m += innerStep) // copy one sample to the destination buffer destBBuf[k++] = bdata[m + bandOffset]; } stream.write(destBBuf, 0, writeLength); offset += srcSkip; } } break; case DataBuffer.TYPE_SHORT: case DataBuffer.TYPE_USHORT: { for (int i = 0; i < outerBound; i++) { for (int b = 0, k = 0; b < numBands; b++) { int bandOffset = bandOffsets[b]; for (int j = 0, m = offset; j < innerBound; j++, m += innerStep) // copy one sample to the destination buffer destSBuf[k++] = sdata[m + bandOffset]; } stream.writeShorts(destSBuf, 0, writeLength); offset += srcSkip; } } break; case DataBuffer.TYPE_INT: { for (int i = 0; i < outerBound; i++) { for (int b = 0, k = 0; b < numBands; b++) { int bandOffset = bandOffsets[b]; for (int j = 0, m = offset; j < innerBound; j++, m += innerStep) // copy one sample to the destination buffer destIBuf[k++] = idata[m + bandOffset]; } stream.writeInts(destIBuf, 0, writeLength); offset += srcSkip; } } break; case DataBuffer.TYPE_FLOAT: { for (int i = 0; i < outerBound; i++) { for (int b = 0, k = 0; b < numBands; b++) { int bandOffset = bandOffsets[b]; for (int j = 0, m = offset; j < innerBound; j++, m += innerStep) // copy one sample to the destination buffer destFBuf[k++] = fdata[m + bandOffset]; } stream.writeFloats(destFBuf, 0, writeLength); offset += srcSkip; } } break; case DataBuffer.TYPE_DOUBLE: { for (int i = 0; i < outerBound; i++) { for (int b = 0, k = 0; b < numBands; b++) { int bandOffset = bandOffsets[b]; for (int j = 0, m = offset; j < innerBound; j++, m += innerStep) // copy one sample to the destination buffer destDBuf[k++] = ddata[m + bandOffset]; } stream.writeDoubles(destDBuf, 0, writeLength); offset += srcSkip; } } break; } } } } private Raster getTile(int tileX, int tileY) { int sx = tileXOffset + tileX * tileWidth; int sy = tileYOffset + tileY * tileHeight; Rectangle bounds = new Rectangle(sx, sy, tileWidth, tileHeight); if (writeRaster) { bounds = bounds.intersection(destinationRegion); if (noTransform) { return inputRaster.createChild(bounds.x, bounds.y, bounds.width, bounds.height, bounds.x, bounds.y, sourceBands); } sx = bounds.x; sy = bounds.y; WritableRaster ras = Raster.createWritableRaster(sampleModel, new Point(sx, sy)); int x = mapToSourceX(sx); int y = mapToSourceY(sy); int minY = inputRaster.getMinY(); int maxY = inputRaster.getMinY() + inputRaster.getHeight(); int cTileWidth = bounds.width; int length = (cTileWidth - 1) * scaleX + 1; for (int j = 0; j < bounds.height; j++, sy++, y += scaleY) { if (y < minY || y >= maxY) continue; Raster source = inputRaster.createChild(x, y, length, 1, x, y, null); int tempX = sx; for (int i = 0, offset = x; i < cTileWidth; i++, tempX++, offset += scaleX) { for (int k = 0; k < numBands; k++) { int p = source.getSample(offset, y, sourceBands[k]); ras.setSample(tempX, sy, k, p); } } } return ras; } else { if (noTransform) { Raster ras = input.getTile(tileX, tileY); if (destinationRegion.contains(bounds) && noSubband) return ras; else { bounds = bounds.intersection(destinationRegion); return ras.createChild(bounds.x, bounds.y, bounds.width, bounds.height, bounds.x, bounds.y, sourceBands); } } bounds = bounds.intersection(destinationRegion); sx = bounds.x; sy = bounds.y; WritableRaster ras = Raster.createWritableRaster(sampleModel, new Point(sx, sy)); int x = mapToSourceX(sx); int y = mapToSourceY(sy); int minY = input.getMinY(); int maxY = input.getMinY() + input.getHeight(); int cTileWidth = bounds.width; int length = (cTileWidth -1) * scaleX + 1; for (int j = 0; j < bounds.height; j++, sy++, y += scaleY) { if (y < minY || y >= maxY) continue; Raster source = input.getData(new Rectangle(x, y, length, 1)); int tempX = sx; for (int i = 0, offset = x; i < cTileWidth; i++, tempX++, offset += scaleX) { for (int k = 0; k < numBands; k++) { int p = source.getSample(offset, y, sourceBands[k]); ras.setSample(tempX, sy, k, p); } } } return ras; } } private int mapToSourceX(int x) { return x * scaleX + xOffset; } private int mapToSourceY(int y) { return y * scaleY + yOffset; } private int getMinTileX() { return ToTile(destinationRegion.x, tileXOffset, tileWidth); } private int getMaxTileX() { return ToTile(destinationRegion.x + destinationRegion.width - 1, tileXOffset, tileWidth); } private int getMinTileY() { return ToTile(destinationRegion.y, tileYOffset, tileHeight); } private int getMaxTileY() { return ToTile(destinationRegion.y + destinationRegion.height - 1, tileYOffset, tileHeight); } private static int ToTile(int pos, int tileOffset, int tileSize) { pos -= tileOffset; if (pos < 0) { pos += 1 - tileSize; // force round to -infinity (ceiling) } return pos/tileSize; } public void reset() { super.reset(); stream = null; optimal = false; sourceBands = null; destinationRegion = null; noTransform = true; noSubband = true; writeRaster = false; } } jai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/raw/properties0000664000175100017510000000124310203036165030336 0ustar tilletille# # $RCSfile: properties,v $ # # Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved. # # Use is subject to license terms. # # $Revision: 1.1 $ # $Date: 2005-02-11 05:01:43 $ # $State: Exp $ # # Internationalization file for com.sun.media.imageioimpl.plugins.raw RawImageReader0=Only one image exists in the stream. RawImageWriteParam0=MODE_EXPLICIT is not supported. RawImageWriter0=Output is not an ImageOutputStream. RawImageWriter1=The image region to be encoded is empty. RawImageWriter2=The provided ImageWriteParam should be a RawImageWriteParam RawRenderedImage0=The provided tile grid position is out of range. RawRenderedImage1=Unsupported sample model. jai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/raw/RawImageWriterSpi.java0000664000175100017510000000720310413303155032430 0ustar tilletille/* * $RCSfile: RawImageWriterSpi.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.2 $ * $Date: 2006-03-31 19:43:40 $ * $State: Exp $ */ package com.sun.media.imageioimpl.plugins.raw; import java.awt.image.DataBuffer; import javax.imageio.spi.ImageWriterSpi; import javax.imageio.spi.ServiceRegistry; import javax.imageio.spi.IIORegistry; import javax.imageio.ImageWriter; import javax.imageio.ImageTypeSpecifier; import javax.imageio.IIOException; import java.util.Locale; import com.sun.media.imageioimpl.common.PackageUtil; public class RawImageWriterSpi extends ImageWriterSpi { private static String [] readerSpiNames = {"com.sun.media.imageioimpl.plugins.raw.RawImageReaderSpi"}; private static String[] formatNames = {"raw", "RAW"}; private static String[] entensions = {""}; private static String[] mimeType = {""}; private boolean registered = false; public RawImageWriterSpi() { super(PackageUtil.getVendor(), PackageUtil.getVersion(), formatNames, entensions, mimeType, "com.sun.media.imageioimpl.plugins.raw.RawImageWriter", STANDARD_OUTPUT_TYPE, readerSpiNames, true, null, null, null, null, true, null, null, null, null); } public String getDescription(Locale locale) { String desc = PackageUtil.getSpecificationTitle() + " Raw Image Writer"; return desc; } public void onRegistration(ServiceRegistry registry, Class category) { if (registered) { return; } registered = true; } public boolean canEncodeImage(ImageTypeSpecifier type) { return true; } public ImageWriter createWriterInstance(Object extension) throws IIOException { return new RawImageWriter(this); } } jai-imageio-core-1.2/src/share/classes/com/sun/media/imageioimpl/plugins/raw/I18N.java0000664000175100017510000000420510203036165027542 0ustar tilletille/* * $RCSfile: I18N.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.1 $ * $Date: 2005-02-11 05:01:42 $ * $State: Exp $ */ package com.sun.media.imageioimpl.plugins.raw; import com.sun.media.imageioimpl.common.I18NImpl; final class I18N extends I18NImpl { static String getString(String key) { return getString("com.sun.media.imageioimpl.plugins.raw.I18N", key); } } jai-imageio-core-1.2/src/share/classes/com/sun/media/imageio/0000775000175100017510000000000011650556206023075 5ustar tilletillejai-imageio-core-1.2/src/share/classes/com/sun/media/imageio/stream/0000775000175100017510000000000011650556206024370 5ustar tilletillejai-imageio-core-1.2/src/share/classes/com/sun/media/imageio/stream/RawImageInputStream.java0000664000175100017510000010300610203036165031111 0ustar tilletille/* * $RCSfile: RawImageInputStream.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.1 $ * $Date: 2005-02-11 05:01:20 $ * $State: Exp $ */ package com.sun.media.imageio.stream; import java.awt.Dimension; import java.awt.Transparency; import java.awt.color.ColorSpace; import java.awt.color.ICC_ColorSpace; import java.awt.color.ICC_Profile; import java.awt.image.ColorModel; import java.awt.image.ComponentColorModel; import java.awt.image.ComponentSampleModel; import java.awt.image.DirectColorModel; import java.awt.image.IndexColorModel; import java.awt.image.MultiPixelPackedSampleModel; import java.awt.image.SampleModel; import java.awt.image.SinglePixelPackedSampleModel; import java.io.IOException; import java.io.InputStream; import java.net.URL; import java.nio.ByteOrder; import java.util.StringTokenizer; import javax.imageio.ImageTypeSpecifier; import javax.imageio.stream.*; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import org.w3c.dom.Document; import org.w3c.dom.NamedNodeMap; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.xml.sax.InputSource; import org.xml.sax.SAXException; import com.sun.media.imageioimpl.common.ImageUtil; /** * This class defines the content of the ImageInputStream * containing several raw images with the same image type: the number of * the images, the image type, the offset for the first sample of each image, * and the image size information. * *

ImageInputStream methods are not commented individually. * These methods merely forward the call to the ImageInputStream * specified when the RawImageInputStream is constructed.

*/ public class RawImageInputStream implements ImageInputStream { private static final String[] preDefinedColorSpaces = new String[]{"GRAY", "sRGB", "LINEAR_RGB", "PYCC", "CIEXYZ"}; private static final int[] preDefinedTypes = new int[]{ ColorSpace.CS_GRAY, ColorSpace.CS_sRGB, ColorSpace.CS_LINEAR_RGB, ColorSpace.CS_PYCC, ColorSpace.CS_CIEXYZ }; /** Gets the attribute from the node. */ private static String getAttribute(Node node, String name) { NamedNodeMap map = node.getAttributes(); node = map.getNamedItem(name); return (node != null) ? node.getNodeValue() : null; } /** Gets the boolean type attribute. */ private static boolean getBoolean(Node node, String name) { String s = getAttribute(node, name); return (s == null) ? false : (new Boolean(s)).booleanValue(); } /** Gets the integer type attribute. */ private static int getInt(Node node, String name) { String s = getAttribute(node, name); return (s == null) ? 0 : (new Integer(s)).intValue(); } /** Gets the integer type attribute. */ private static byte[] getByteArray(Node node, String name) { String s = getAttribute(node, name); if (s == null) return null; StringTokenizer token = new StringTokenizer(s); int count = token.countTokens(); if (count == 0) return null; byte[] buf = new byte[count]; int i = 0; while(token.hasMoreElements()) { buf[i++] = new Byte(token.nextToken()).byteValue(); } return buf; } /** Gets the integer type attribute. */ private static int[] getIntArray(Node node, String name) { String s = getAttribute(node, name); if (s == null) return null; StringTokenizer token = new StringTokenizer(s); int count = token.countTokens(); if (count == 0) return null; int[] buf = new int[count]; int i = 0; while(token.hasMoreElements()) { buf[i++] = new Integer(token.nextToken()).intValue(); } return buf; } private static int getTransparency(String s) { if ("BITMASK".equals(s)) return Transparency.BITMASK; else if ("OPAQUE".equals(s)) return Transparency.OPAQUE; else if ("TRANSLUCENT".equals(s)) return Transparency.TRANSLUCENT; else return 0; } private static ColorSpace getColorSpace(Node node) throws IOException { NodeList nodes = node.getChildNodes(); for (int i = 0; i < nodes.getLength(); i++) { Node child = nodes.item(i); if ("colorSpace".equals(child.getNodeName())) { String s = child.getNodeValue(); for (int j = 0; j < preDefinedColorSpaces.length; j++) { if (preDefinedColorSpaces[j].equals(s)) return ColorSpace.getInstance(preDefinedTypes[j]); } InputStream stm = new URL(s).openStream(); ColorSpace cp = new ICC_ColorSpace(ICC_Profile.getInstance(stm)); stm.close(); return cp; } } return null; } /** The wrapperred ImageInputStream. */ private ImageInputStream source; /** The image type for all the images in the stream. */ private ImageTypeSpecifier type; /** The position of the first sample for each image. */ private long[] imageOffsets; /** The image sizes. */ private Dimension[] imageDimensions; /** Constructor. * @param source The ImageInputStream containing all the raw * images. * @param type The ImageTypeSpecifier for all the images * in the stream. * @param imageOffsets The position of the first sample for each image * in the stream. * @param imageDimensions The image size for each image in the stream. * * @throws IllegalArgumentException If the sizes of * imageOffsets * and imageDimensions are different or if * either array is null. */ public RawImageInputStream(ImageInputStream source, ImageTypeSpecifier type, long[] imageOffsets, Dimension[] imageDimensions) { if (imageOffsets == null || imageDimensions == null || imageOffsets.length != imageDimensions.length) { throw new IllegalArgumentException (I18N.getString("RawImageInputStream0")); } this.source = source; this.type = type; this.imageOffsets = imageOffsets; this.imageDimensions = imageDimensions; } /** * Constructor. * *

This constructor is the same as * {@link #RawImageInputStream(ImageInputStream,ImageTypeSpecifier, * long[],Dimension[])} except that a SampleModel is * supplied instead of an ImageTypeSpecifier. This * constructor creates a ColorModel for the supplied * SampleModel and then creates an * ImageTypeSpecifier.

* *

Suitable ColorModels are guaranteed to exist * for all instances of ComponentSampleModel. * For 1- and 3- banded SampleModels, the * ColorModel will be opaque. For 2- and 4-banded * SampleModels, the output will use alpha transparency * which is not premultiplied. 1- and 2-banded data will use a * grayscale ColorSpace, and 3- and 4-banded data a sRGB * ColorSpace. Data with 5 or more bands will use a * ColorSpace which satisfies compatibility constraints * but is merely a placeholder and does not perform correct color * conversion to and from the C.I.E. XYZ and sRGB color spaces.

* *

An instance of DirectColorModel will be created for * instances of SinglePixelPackedSampleModel with no more * than 4 bands.

* *

An instance of IndexColorModel will be created for * instances of MultiPixelPackedSampleModel. The colormap * will be a grayscale ramp with 1 << numberOfBits * entries ranging from zero to at most 255.

* * @param source The ImageInputStream containing all the raw * images. * @param sampleModel The SampleModel for all the images * in the stream. * @param imageOffsets The position of the first sample for each image * in the stream. * @param imageDimensions The image size for each image in the stream. * * @throws IllegalArgumentException If sampleModel is null. * @throws IllegalArgumentException If the sizes of * imageOffsets * and imageDimensions are different or if * either array is null. * @throws IllegalArgumentException If it is not possible to create a * ColorModel from the supplied * SampleModel. */ public RawImageInputStream(ImageInputStream source, SampleModel sampleModel, long[] imageOffsets, Dimension[] imageDimensions) { if (imageOffsets == null || imageDimensions == null || imageOffsets.length != imageDimensions.length) { throw new IllegalArgumentException (I18N.getString("RawImageInputStream0")); } this.source = source; ColorModel colorModel = ImageUtil.createColorModel(sampleModel); if(colorModel == null) { throw new IllegalArgumentException (I18N.getString("RawImageInputStream4")); } this.type = new ImageTypeSpecifier(colorModel, sampleModel); this.imageOffsets = imageOffsets; this.imageDimensions = imageDimensions; } /** * Constructor. * * The xmlSource must adhere to the following DTD: * *
     *<!DOCTYPE "com_sun_media_imageio_stream_raw_1.0" [
     *
     *  <!ELEMENT com_sun_media_imageio_stream_raw_1.0
     *    (byteOrder?, offset?, width?, height?,
     *     (ComponentSampleModel |
     *      MultiPixelPackedSampleModel |
     *      SinglePixelPackedSampleModel),
     *     (ComponentColorModel |
     *      DirectColorModel |
     *      IndexColorModel)?)>
     *
     *    <!ATTLIST com_sun_media_imageio_stream_raw_1.0
     *      xmlns CDATA #FIXED "http://com/sun/media/imageio">
     *
     *  <!ELEMENT byteOrder (#PCDATA)>
     *    <!-- Byte order of data stream -->
     *    <!-- Either "NETWORK" or "REVERSE" -->
     *    <!-- Data type: String -->
     *
     *  <!ELEMENT offset (#PCDATA)>
     *    <!-- Byte offset to the image data in the stream -->
     *    <!-- Data type: long -->
     *
     *  <!ELEMENT width (#PCDATA)>
     *    <!-- Image width; default value is SampleModel width -->
     *    <!-- Data type: int -->
     *
     *  <!ELEMENT height (#PCDATA)>
     *    <!-- Image height; default value is SampleModel height -->
     *    <!-- Data type: int -->
     *
     *  <!ELEMENT ComponentSampleModel EMPTY>
     *    <!-- ComponentSampleModel -->
     *
     *    <!ATTLIST ComponentSampleModel
     *      dataType (BYTE | USHORT | SHORT | INT | FLOAT | DOUBLE) #REQUIRED
     *        <!-- Data type: String -->
     *      w              CDATA #REQUIRED
     *        <!-- SampleModel width -->
     *        <!-- Data type: int -->
     *      h              CDATA #REQUIRED
     *        <!-- SampleModel height -->
     *        <!-- Data type: int -->
     *      pixelStride    CDATA "1"
     *        <!-- SampleModel pixel stride -->
     *        <!-- Data type: int -->
     *      scanlineStride CDATA #REQUIRED
     *        <!-- SampleModel line stride -->
     *        <!-- Data type: int -->
     *      bankIndices    CDATA #IMPLIED
     *        <!-- SampleModel bank indices -->
     *        <!-- Data type: int array -->
     *      bandOffsets    CDATA #REQUIRED>
     *        <!-- SampleModel band offsets -->
     *        <!-- Data type: int array -->
     *
     *  <!ELEMENT MultiPixelPackedSampleModel EMPTY>
     *    <!-- MultiPixelPackedSampleModel -->
     *
     *    <!ATTLIST MultiPixelPackedSampleModel
     *      dataType       (BYTE | USHORT | INT) #REQUIRED
     *        <!-- Data type: String -->
     *      w              CDATA #REQUIRED
     *        <!-- SampleModel width -->
     *        <!-- Data type: int -->
     *      h              CDATA #REQUIRED
     *        <!-- SampleModel height -->
     *        <!-- Data type: int -->
     *      numberOfBits   CDATA #REQUIRED
     *        <!-- Number of bits per pixel -->
     *        <!-- Data type: int -->
     *      scanlineStride CDATA #REQUIRED
     *        <!-- SampleModel line stride -->
     *        <!-- Data type: int -->
     *      dataBitOffset  CDATA "0">
     *        <!-- Offset to first valid bit in a line -->
     *        <!-- Data type: int -->
     *
     *  <!ELEMENT SinglePixelPackedSampleModel EMPTY>
     *    <!-- SinglePixelPackedSampleModel -->
     *
     *    <!ATTLIST SinglePixelPackedSampleModel
     *      dataType       (BYTE | USHORT | INT) #REQUIRED
     *        <!-- Data type: String -->
     *      w              CDATA #REQUIRED
     *        <!-- SampleModel width -->
     *        <!-- Data type: int -->
     *      h              CDATA #REQUIRED
     *        <!-- SampleModel height -->
     *        <!-- Data type: int -->
     *      scanlineStride CDATA #REQUIRED
     *        <!-- SampleModel line stride -->
     *        <!-- Data type: int -->
     *      bitMasks       CDATA #REQUIRED>
     *        <!-- Masks indicating RGBA positions -->
     *        <!-- Data type: int -->
     *
     *  <!ELEMENT ComponentColorModel EMPTY>
     *    <!-- ComponentColorModel -->
     *
     *    <!ATTLIST ComponentColorModel
     *      colorSpace (CIEXYZ | GRAY | LINEAR_RGB | PYCC | sRGB | URL)
     *                     #REQUIRED
     *        <!-- A string representing a predefined ColorSpace or a URI
     *                representing the location of any ICC profile from which
     *                a ColorSpace may be created. -->
     *        <!-- Data type: String -->
     *      bits                 CDATA          #IMPLIED
     *        <!-- Number of bits per color component -->
     *        <!-- Data type: int -->
     *      hasAlpha             (true | false) #REQUIRED
     *        <!-- Whether an alpha channel is present -->
     *        <!-- Data type: boolean -->
     *      isAlphaPremultiplied (true | false) #REQUIRED
     *        <!-- Whether any alpha channel is premultiplied -->
     *        <!-- Data type: boolean -->
     *      transparency         (BITMASK | OPAQUE | TRANSLUCENT) #REQUIRED
     *        <!-- The type of transparency -->
     *      transferType (BYTE | USHORT | SHORT | INT | FLOAT | DOUBLE)
     *                     #REQUIRED>
     *        <!-- The data transfer type -->
     *
     *  <!ELEMENT DirectColorModel EMPTY>
     *    <!-- DirectColorModel -->
     *
     *    <!ATTLIST DirectColorModel
     *      colorSpace           (LINEAR_RGB | sRGB | URL) #IMPLIED
     *        <!-- A string representing a predefined RGB ColorSpace or a
     *                URL representing the location of any ICC profile from
     *                which an RGB ColorSpace may be created. -->
     *        <!-- Data type: String -->
     *      bits       CDATA #REQUIRED
     *        <!-- Number of bits per color component -->
     *        <!-- Data type: int -->
     *      rmask      CDATA #REQUIRED
     *        <!-- Bitmask of the red component -->
     *        <!-- Data type: int -->
     *      gmask      CDATA #REQUIRED
     *        <!-- Bitmask of the grenn component -->
     *        <!-- Data type: int -->
     *      bmask      CDATA #REQUIRED
     *        <!-- Bitmask of the blue component -->
     *        <!-- Data type: int -->
     *      amask      CDATA "0">
     *        <!-- Bitmask of the alpha component -->
     *        <!-- Data type: int -->
     *
     *  <!ELEMENT IndexColorModel EMPTY>
     *    <!-- IndexColorModel -->
     *
     *    <!ATTLIST IndexColorModel
     *      bits CDATA #REQUIRED
     *        <!-- Number of bits per color component -->
     *        <!-- Data type: int -->
     *      size CDATA #REQUIRED
     *        <!-- Number of elements in the colormap -->
     *        <!-- Data type: int -->
     *      r    CDATA #REQUIRED
     *        <!-- Red elements of the colormap -->
     *        <!-- Data type: byte array -->
     *      g    CDATA #REQUIRED
     *        <!-- Green elements of the colormap -->
     *        <!-- Data type: byte array -->
     *      b    CDATA #REQUIRED
     *        <!-- Blue elements of the colormap -->
     *        <!-- Data type: byte array -->
     *      a    CDATA #IMPLIED>
     *        <!-- Alpha elements of the colormap -->
     *        <!-- Data type: byte array -->
     *]>
     *
* * * @param source The ImageInputStream containing all the raw * images. * @param xmlSource The org.xml.sax.InputSource to provide * the xml document in which the stream structure is defined. * * @throws RuntimeException If the parse configuration isn't correct. * * @throws IllegalArgumentException If the number of "width" elements isn't * the same as the number of "height" elements. * * @throws SAXException If one is thrown in parsing. * * @throws IOException If one is thrown in parsing, or creating color space * from a URL. */ public RawImageInputStream(ImageInputStream source, org.xml.sax.InputSource xmlSource) throws SAXException, IOException { this.source = source; DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); dbf.setValidating(true); dbf.setNamespaceAware(true); dbf.setAttribute("http://java.sun.com/xml/jaxp/properties/schemaLanguage", "http://www.w3.org/2001/XMLSchema"); DocumentBuilder db = null; try { db = dbf.newDocumentBuilder(); } catch (ParserConfigurationException ex) { throw new RuntimeException(I18N.getString("RawImageInputStream1"), ex); } Document doc = db.parse(xmlSource); //gets the byte order NodeList nodes = doc.getElementsByTagName("byteOrder"); String byteOrder = nodes.item(0).getNodeValue(); if ("NETWORK".equals(byteOrder)) { this.setByteOrder(ByteOrder.BIG_ENDIAN); this.source.setByteOrder(ByteOrder.BIG_ENDIAN); } else if ("REVERSE".equals(byteOrder)) { this.setByteOrder(ByteOrder.LITTLE_ENDIAN); this.setByteOrder(ByteOrder.LITTLE_ENDIAN); } //gets image offsets nodes = doc.getElementsByTagName("offset"); int length = nodes.getLength(); this.imageOffsets = new long[length]; for (int i = 0; i < length; i++) { imageOffsets[i] = new Long(nodes.item(i).getNodeValue()).longValue(); } //gets image dimensions nodes = doc.getElementsByTagName("width"); NodeList nodes1 = doc.getElementsByTagName("height"); length = nodes.getLength(); if (length != nodes1.getLength()) throw new IllegalArgumentException (I18N.getString("RawImageInputStream2")); this.imageDimensions = new Dimension[length]; for (int i = 0; i < length; i++) { String w = nodes.item(i).getNodeValue(); String h = nodes1.item(i).getNodeValue(); imageDimensions[i] = new Dimension((new Integer(w)).intValue(), (new Integer(h)).intValue()); } //get sampleModel SampleModel sampleModel = null; // for ComponentSampleModel nodes = doc.getElementsByTagName("ComponentSampleModel"); if (nodes.getLength() > 0) { Node node = nodes.item(0); int[] bankIndices =getIntArray (node, "bankIndices"); if (bankIndices == null) sampleModel = new ComponentSampleModel(getInt(node, "dataType"), getInt(node, "w"), getInt(node, "h"), getInt(node, "pixelStride"), getInt(node, "scanlineStride"), getIntArray(node, "bandOffsets")); else sampleModel = new ComponentSampleModel(getInt(node, "dataType"), getInt(node, "w"), getInt(node, "h"), getInt(node, "pixelStride"), getInt(node, "scanlineStride"), bankIndices, getIntArray(node, "bandOffsets")); } // for MultiPixelPackedSampleModel nodes = doc.getElementsByTagName("MultiPixelPackedSampleModel"); if (nodes.getLength() > 0) { Node node = nodes.item(0); sampleModel = new MultiPixelPackedSampleModel(getInt(node, "dataType"), getInt(node, "w"), getInt(node, "h"), getInt(node, "numberOfBits"), getInt(node, "scanlineStride"), getInt(node, "dataBitOffset")); } // for SinglePixelPackedSampleModel nodes = doc.getElementsByTagName("SinglePixelPackedSampleModel"); if (nodes.getLength() > 0) { Node node = nodes.item(0); sampleModel = new SinglePixelPackedSampleModel(getInt(node, "dataType"), getInt(node, "w"), getInt(node, "h"), getInt(node, "scanlineStride"), getIntArray(node, "bitMasks")); } //get colorModel ColorModel colorModel = null; // for ComponentColorModel nodes = doc.getElementsByTagName("ComponentColorModel"); if (nodes.getLength() > 0) { Node node = nodes.item(0); colorModel = new ComponentColorModel(getColorSpace(node), getIntArray(node, "bits"), getBoolean(node, "hasAlpha"), getBoolean(node, "isAlphaPremultiplied"), getTransparency(getAttribute(node, "transparency")), getInt(node, "transferType")); } // for DirectColorModel nodes = doc.getElementsByTagName("DirectColorModel"); if (nodes.getLength() > 0) { Node node = nodes.item(0); colorModel = new DirectColorModel(getColorSpace(node), getInt(node, "bits"), getInt(node, "rmask"), getInt(node, "gmask"), getInt(node, "bmask"), getInt(node, "amask"), false, Transparency.OPAQUE); } // for IndexColorModel nodes = doc.getElementsByTagName("IndexColorModel"); if (nodes.getLength() > 0) { Node node = nodes.item(0); byte[] alpha = getByteArray(node, "a"); if (alpha == null) colorModel = new IndexColorModel(getInt(node, "bits"), getInt(node, "size"), getByteArray(node, "r"), getByteArray(node, "g"), getByteArray(node, "b")); else colorModel = new IndexColorModel(getInt(node, "bits"), getInt(node, "size"), getByteArray(node, "r"), getByteArray(node, "g"), getByteArray(node, "b"), alpha); } //create image type this.type = new ImageTypeSpecifier(colorModel, sampleModel); //assign imagedimension based on the sample model if (this.imageDimensions.length == 0) { this.imageDimensions = new Dimension[this.imageOffsets.length]; imageDimensions[0] = new Dimension(sampleModel.getWidth(), sampleModel.getHeight()); for (int i = 1; i < imageDimensions.length; i++) imageDimensions[i] = imageDimensions[0]; } } /** * Retrieves the image type. * * @return the image type */ public ImageTypeSpecifier getImageType() { return type; } /** * Retrieves the image offset of the imageIndexth image. * * @param imageIndex the index of the image of interest. * @throws IllegalArgumentException If the provided parameter is out of * range. * @return the offset in the stream to the specified image. */ public long getImageOffset(int imageIndex) { if (imageIndex < 0 || imageIndex >= imageOffsets.length) throw new IllegalArgumentException (I18N.getString("RawImageInputStream3")); return imageOffsets[imageIndex]; } /** Retrieves the dimnsion of the imageIndexth image. * @param imageIndex the index of the image of interest. * @throws IllegalArgumentException If the provided parameter is out of * rangle. * @return the size of the specified image. */ public Dimension getImageDimension(int imageIndex) { if (imageIndex < 0 || imageIndex >= imageOffsets.length) throw new IllegalArgumentException (I18N.getString("RawImageInputStream3")); return imageDimensions[imageIndex]; } /** * Retrieves the number of images in the ImageInputStream. * @return the number of image in the stream. */ public int getNumImages() { return imageOffsets.length; } public void setByteOrder(ByteOrder byteOrder) { source.setByteOrder(byteOrder); } public ByteOrder getByteOrder() { return source.getByteOrder(); } public int read() throws IOException { return source.read(); } public int read(byte[] b) throws IOException { return source.read(b); } public int read(byte[] b, int off, int len) throws IOException { return source.read(b, off, len); } public void readBytes(IIOByteBuffer buf, int len) throws IOException { source.readBytes(buf, len); } public boolean readBoolean() throws IOException { return source.readBoolean(); } public byte readByte() throws IOException { return source.readByte(); } public int readUnsignedByte() throws IOException { return source.readUnsignedByte(); } public short readShort() throws IOException { return source.readShort(); } public int readUnsignedShort() throws IOException { return source.readUnsignedShort(); } public char readChar() throws IOException { return source.readChar(); } public int readInt() throws IOException { return source.readInt(); } public long readUnsignedInt() throws IOException { return source.readUnsignedInt(); } public long readLong() throws IOException { return source.readLong(); } public float readFloat() throws IOException { return source.readFloat(); } public double readDouble() throws IOException { return source.readDouble(); } public String readLine() throws IOException { return source.readLine(); } public String readUTF() throws IOException { return source.readUTF(); } public void readFully(byte[] b, int off, int len) throws IOException { source.readFully(b, off, len); } public void readFully(byte[] b) throws IOException { source.readFully(b); } public void readFully(short[] s, int off, int len) throws IOException { source.readFully(s, off, len); } public void readFully(char[] c, int off, int len) throws IOException { source.readFully(c, off, len); } public void readFully(int[] i, int off, int len) throws IOException { source.readFully(i, off, len); } public void readFully(long[] l, int off, int len) throws IOException { source.readFully(l, off, len); } public void readFully(float[] f, int off, int len) throws IOException { source.readFully(f, off, len); } public void readFully(double[] d, int off, int len) throws IOException { source.readFully(d, off, len); } public long getStreamPosition() throws IOException { return source.getStreamPosition(); } public int getBitOffset() throws IOException { return source.getBitOffset(); } public void setBitOffset(int bitOffset) throws IOException { source.setBitOffset(bitOffset); } public int readBit() throws IOException { return source.readBit(); } public long readBits(int numBits) throws IOException { return source.readBits(numBits); } public long length() throws IOException { return source.length(); } public int skipBytes(int n) throws IOException { return source.skipBytes(n); } public long skipBytes(long n) throws IOException { return source.skipBytes(n); } public void seek(long pos) throws IOException { source.seek(pos); } public void mark() { source.mark(); } public void reset() throws IOException { source.reset(); } public void flushBefore(long pos) throws IOException { source.flushBefore(pos); } public void flush() throws IOException { source.flush(); } public long getFlushedPosition() { return source.getFlushedPosition(); } public boolean isCached() { return source.isCached(); } public boolean isCachedMemory() { return source.isCachedMemory(); } public boolean isCachedFile() { return source.isCachedFile(); } public void close() throws IOException { source.close(); } } ././@LongLink0000000000000000000000000000014500000000000011565 Lustar rootrootjai-imageio-core-1.2/src/share/classes/com/sun/media/imageio/stream/FileChannelImageInputStream.javajai-imageio-core-1.2/src/share/classes/com/sun/media/imageio/stream/FileChannelImageInputStream.java0000664000175100017510000003722310672610763032553 0ustar tilletille/* * $RCSfile: FileChannelImageInputStream.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.2 $ * $Date: 2007-09-14 22:57:55 $ * $State: Exp $ */ package com.sun.media.imageio.stream; import java.io.File; import java.io.EOFException; import java.io.IOException; import java.nio.Buffer; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.CharBuffer; import java.nio.DoubleBuffer; import java.nio.FloatBuffer; import java.nio.IntBuffer; import java.nio.LongBuffer; import java.nio.MappedByteBuffer; import java.nio.ShortBuffer; import java.nio.channels.FileChannel; import javax.imageio.stream.ImageInputStreamImpl; /** * A class which implements ImageInputStream using a * FileChannel as the eventual data source. The channel * contents are assumed to be stable during the lifetime of the object. * *

Memory mapping and new I/O view Buffers are used to * read the data. Only methods which provide significant performance * improvement with respect to the superclass implementation are overridden. * Overridden methods are not commented individually unless some noteworthy * aspect of the implementation must be described.

* *

The methods of this class are not synchronized.

* * @see javax.imageio.stream.ImageInputStream * @see java.nio * @see java.nio.channels.FileChannel */ public class FileChannelImageInputStream extends ImageInputStreamImpl { /** The FileChannel data source. */ private FileChannel channel; /** A memory mapping of all or part of the channel. */ private MappedByteBuffer mappedBuffer; /** The stream position of the mapping. */ private long mappedPos; /** The stream position least upper bound of the mapping. */ private long mappedUpperBound; /** * Constructs a FileChannelImageInputStream from a * FileChannel. The initial position of the stream * stream is taken to be the position of the FileChannel * parameter when this constructor is invoked. The stream and flushed * positions are therefore both initialized to * channel.position(). * * @param channel the source FileChannel. * * @throws IllegalArgumentException if channel is * null or is not open. * @throws IOException if a method invoked on channel * throws an IOException. */ public FileChannelImageInputStream(FileChannel channel) throws IOException { // Check the parameter. if(channel == null) { throw new IllegalArgumentException("channel == null"); } else if(!channel.isOpen()) { throw new IllegalArgumentException("channel.isOpen() == false"); } // Save the channel reference. this.channel = channel; // Get the channel position. long channelPosition = channel.position(); // Set stream and flushed positions to initial channel position. this.streamPos = this.flushedPos = channelPosition; // Determine the size of the mapping. long fullSize = channel.size() - channelPosition; long mappedSize = Math.min(fullSize, Integer.MAX_VALUE); // Set the mapped position and upper bound. this.mappedPos = 0; this.mappedUpperBound = mappedPos + mappedSize; // Map the file. this.mappedBuffer = channel.map(FileChannel.MapMode.READ_ONLY, channelPosition, mappedSize); } /** * Returns a MappedByteBuffer which memory maps * at least from the channel position corresponding to the * current stream position to len bytes beyond. * A new buffer is created only if necessary. * * @param len The number of bytes required beyond the current stream * position. */ private MappedByteBuffer getMappedBuffer(int len) throws IOException { // If request is outside mapped region, map a new region. if(streamPos < mappedPos || streamPos + len >= mappedUpperBound) { // Set the map position. mappedPos = streamPos; // Determine the map size. long mappedSize = Math.min(channel.size() - mappedPos, Integer.MAX_VALUE); // Set the mapped upper bound. mappedUpperBound = mappedPos + mappedSize; // Map the file. mappedBuffer = channel.map(FileChannel.MapMode.READ_ONLY, mappedPos, mappedSize); mappedBuffer.order(super.getByteOrder()); } return mappedBuffer; } // --- Implementation of superclass abstract methods. --- public int read() throws IOException { checkClosed(); bitOffset = 0; // Get the mapped buffer. ByteBuffer byteBuffer = getMappedBuffer(1); // Check number of bytes left. if(byteBuffer.remaining() < 1) { // Return EOF. return -1; } // Get the byte from the buffer. int value = byteBuffer.get()&0xff; // Increment the stream position. streamPos++; //System.out.println("value = "+value); return value; } public int read(byte[] b, int off, int len) throws IOException { if(off < 0 || len < 0 || off + len > b.length) { // NullPointerException will be thrown before this if b is null. throw new IndexOutOfBoundsException ("off < 0 || len < 0 || off + len > b.length"); } else if(len == 0) { return 0; } checkClosed(); bitOffset = 0; // Get the mapped buffer. ByteBuffer byteBuffer = getMappedBuffer(len); // Get the number of bytes remaining. int numBytesRemaining = byteBuffer.remaining(); // Check number of bytes left. if(numBytesRemaining < 1) { // Return EOF. return -1; } else if(len > numBytesRemaining) { // Clamp 'len' to number of bytes in Buffer. Apparently some // readers (JPEG) request data beyond the end of the file. len = numBytesRemaining; } // Read the data from the buffer. byteBuffer.get(b, off, len); // Increment the stream position. streamPos += len; return len; } // --- Overriding of superclass methods. --- /** * Invokes the superclass method and sets the internal reference * to the source FileChannel to null. * The source FileChannel is not closed. * * @exception IOException if an error occurs. */ public void close() throws IOException { super.close(); channel = null; } public void readFully(char[] c, int off, int len) throws IOException { if(off < 0 || len < 0 || off + len > c.length) { // NullPointerException will be thrown before this if c is null. throw new IndexOutOfBoundsException ("off < 0 || len < 0 || off + len > c.length"); } else if(len == 0) { return; } // Determine the requested length in bytes. int byteLen = 2*len; // Get the mapped buffer. ByteBuffer byteBuffer = getMappedBuffer(byteLen); // Ensure enough bytes remain. if(byteBuffer.remaining() < byteLen) { throw new EOFException(); } // Get the view Buffer. CharBuffer viewBuffer = byteBuffer.asCharBuffer(); // Get the chars. viewBuffer.get(c, off, len); // Update the position. seek(streamPos + byteLen); } public void readFully(short[] s, int off, int len) throws IOException { if(off < 0 || len < 0 || off + len > s.length) { // NullPointerException will be thrown before this if s is null. throw new IndexOutOfBoundsException ("off < 0 || len < 0 || off + len > s.length"); } else if(len == 0) { return; } // Determine the requested length in bytes. int byteLen = 2*len; // Get the mapped buffer. ByteBuffer byteBuffer = getMappedBuffer(byteLen); // Ensure enough bytes remain. if(byteBuffer.remaining() < byteLen) { throw new EOFException(); } // Get the view Buffer. ShortBuffer viewBuffer = byteBuffer.asShortBuffer(); // Get the shorts. viewBuffer.get(s, off, len); // Update the position. seek(streamPos + byteLen); } public void readFully(int[] i, int off, int len) throws IOException { if(off < 0 || len < 0 || off + len > i.length) { // NullPointerException will be thrown before this if i is null. throw new IndexOutOfBoundsException ("off < 0 || len < 0 || off + len > i.length"); } else if(len == 0) { return; } // Determine the requested length in bytes. int byteLen = 4*len; // Get the mapped buffer. ByteBuffer byteBuffer = getMappedBuffer(byteLen); // Ensure enough bytes remain. if(byteBuffer.remaining() < byteLen) { throw new EOFException(); } // Get the view Buffer. IntBuffer viewBuffer = byteBuffer.asIntBuffer(); // Get the ints. viewBuffer.get(i, off, len); // Update the position. seek(streamPos + byteLen); } public void readFully(long[] l, int off, int len) throws IOException { if(off < 0 || len < 0 || off + len > l.length) { // NullPointerException will be thrown before this if l is null. throw new IndexOutOfBoundsException ("off < 0 || len < 0 || off + len > l.length"); } else if(len == 0) { return; } // Determine the requested length in bytes. int byteLen = 8*len; // Get the mapped buffer. ByteBuffer byteBuffer = getMappedBuffer(byteLen); // Ensure enough bytes remain. if(byteBuffer.remaining() < byteLen) { throw new EOFException(); } // Get the view Buffer. LongBuffer viewBuffer = byteBuffer.asLongBuffer(); // Get the longs. viewBuffer.get(l, off, len); // Update the position. seek(streamPos + byteLen); } public void readFully(float[] f, int off, int len) throws IOException { if(off < 0 || len < 0 || off + len > f.length) { // NullPointerException will be thrown before this if f is null. throw new IndexOutOfBoundsException ("off < 0 || len < 0 || off + len > f.length"); } else if(len == 0) { return; } // Determine the requested length in bytes. int byteLen = 4*len; // Get the mapped buffer. ByteBuffer byteBuffer = getMappedBuffer(byteLen); // Ensure enough bytes remain. if(byteBuffer.remaining() < byteLen) { throw new EOFException(); } // Get the view Buffer. FloatBuffer viewBuffer = byteBuffer.asFloatBuffer(); // Get the floats. viewBuffer.get(f, off, len); // Update the position. seek(streamPos + byteLen); } public void readFully(double[] d, int off, int len) throws IOException { if(off < 0 || len < 0 || off + len > d.length) { // NullPointerException will be thrown before this if d is null. throw new IndexOutOfBoundsException ("off < 0 || len < 0 || off + len > d.length"); } else if(len == 0) { return; } // Determine the requested length in bytes. int byteLen = 8*len; // Get the mapped buffer. ByteBuffer byteBuffer = getMappedBuffer(byteLen); // Ensure enough bytes remain. if(byteBuffer.remaining() < byteLen) { throw new EOFException(); } // Get the view Buffer. DoubleBuffer viewBuffer = byteBuffer.asDoubleBuffer(); // Get the doubles. viewBuffer.get(d, off, len); // Update the position. seek(streamPos + byteLen); } /** * Returns the number of bytes currently in the FileChannel. * If an IOException is encountered when querying the * channel's size, -1L will be returned. * * @return The number of bytes in the channel * -1L to indicate unknown length. */ public long length() { // Initialize to value indicating unknown length. long length = -1L; // Set length to current size with respect to initial position. try { length = channel.size(); } catch(IOException e) { // Default to unknown length. } return length; } /** * Invokes the superclass method and sets the position within the * memory mapped buffer. A new region is mapped if necessary. The * position of the source FileChannel is not changed, i.e., * {@link java.nio.channels.FileChannel#position(long)} is not invoked. */ public void seek(long pos) throws IOException { super.seek(pos); if(pos >= mappedPos && pos < mappedUpperBound) { // Seeking to location within mapped buffer: set buffer position. mappedBuffer.position((int)(pos - mappedPos)); } else { // Seeking to location outside mapped buffer: get a new mapped // buffer at current position with maximal size. int len = (int)Math.min(channel.size() - pos, Integer.MAX_VALUE); mappedBuffer = getMappedBuffer(len); } } public void setByteOrder(ByteOrder networkByteOrder) { super.setByteOrder(networkByteOrder); mappedBuffer.order(networkByteOrder); } } jai-imageio-core-1.2/src/share/classes/com/sun/media/imageio/stream/StreamSegmentMapper.java0000664000175100017510000001142010203036165031142 0ustar tilletille/* * $RCSfile: StreamSegmentMapper.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.1 $ * $Date: 2005-02-11 05:01:21 $ * $State: Exp $ */ package com.sun.media.imageio.stream; /** * An interface for use with the SegmentedImageInputStream * class. An instance of the StreamSegmentMapper * interface provides the location and length of a segment of a source * ImageInputStream corresponding to the initial portion of * a desired segment of the output stream. * *

As an example, consider a mapping between a source * ImageInputStream src and a SegmentedImageInputStream * dst comprising bytes 100-149 and 200-249 of the source * stream. The dst stream has a reference to an instance * mapper of StreamSegmentMapper. * *

A call to dst.seek(0); dst.read(buf, 0, 10) will * result in a call to mapper.getStreamSegment(0, 10), * returning a new StreamSegment with a starting * position of 100 and a length of 10 (or less). This indicates that * in order to read bytes 0-9 of the segmented stream, bytes 100-109 * of the source stream should be read. * *

A call to dst.seek(10); int nbytes = dst.read(buf, 0, * 100) is somewhat more complex, since it will require data * from both segments of src. The method * mapper.getStreamSegment(10, 100) will be called. This * method will return a new StreamSegment with a starting * position of 110 and a length of 40 (or less). The length is * limited to 40 since a longer value would result in a read past the * end of the first segment. The read will stop after the first 40 * bytes and an addition read or reads will be required to obtain the * data contained in the second segment. */ public interface StreamSegmentMapper { /** * Returns a StreamSegment object indicating the * location of the initial portion of a desired segment in the * source stream. The length of the returned * StreamSegment may be smaller than the desired * length. * * @param pos The desired starting position in the * SegmentedImageInputStream, as a long. * @param length The desired segment length. * @return a StreamSegment object */ StreamSegment getStreamSegment(long pos, int length); /** * Sets the values of a StreamSegment object * indicating the location of the initial portion of a desired * segment in the source stream. The length of the returned * StreamSegment may be smaller than the desired * length. * * @param pos The desired starting position in the * SegmentedImageInputStream, as a long. * @param length The desired segment length. * @param seg A StreamSegment object to be overwritten. */ void getStreamSegment(long pos, int length, StreamSegment seg); } jai-imageio-core-1.2/src/share/classes/com/sun/media/imageio/stream/package.html0000664000175100017510000001240310203036165026637 0ustar tilletille Provides ImageInputStream and ImageOutputStream classes for use with the Java Image I/O Framework. The FileChannel-based classes use the new I/O {@link java.nio} package to accelerate reading and writing of image data.

FileChannelImageInputStream

FileChannelImageInputStream uses memory mapping and NIO view Buffers to perform its data reading. It may be created by direct instantiation given a FileChannel or via the Java Image I/O plug-in mechanism, for example from ImageIO.createImageInputStream().

A service provider is also registered which creates an ImageInputStream given a {@link java.nio.channels.ReadableByteChannel}. If the ReadableByteChannel is a FileChannel then the ImageInputStream will be a FileChannelImageInputStream. Otherwise an InputStream will be derived from the Channel and wrapped by a FileCacheImageInputStream if a disk cache is being used and does not cause a security violation, or a MemoryCacheImageInputStream if disk caching is disabled or not permitted.

FileChannelImageOutputStream

FileChannelImageOutputStream uses memory mapping and NIO view Buffers to perform its data reading and direct NIO and view Buffers to perform its data writing. It may be created by direct instantiation given a FileChannel or via the Java Image I/O plug-in mechanism, for example from ImageIO.createImageOutputStream().

A service provider is also registered which creates an ImageOutputStream given a {@link java.nio.channels.WritableByteChannel}. If the WritableByteChannel is a FileChannel which has been opened for both reading and writing, then the ImageOutputStream will be a FileChannelImageOutputStream. Otherwise an OutputStream will be derived from the Channel and wrapped by a FileCacheImageOutputStream if a disk cache is being used and does not cause a security violation, or a MemoryCacheImageOutputStream if disk caching is disabled or not permitted.

RawImageInputStream

A RawImageInputStream provides a data input source for the "raw" image format ImageReader plug-in. The RawImageInputStream constructor which requires an {@link org.xml.sax.InputSource} parameter allows an application to use a pre-established XML description of the raw image file. This may be useful in cases where groups of files have the same layout in which case identical or similar XML description files may be re-used. Such a description file would be used to create a FileInputStream from which the InputSource would be created.

SegmentedImageInputStream

A SegmentedImageInputStream provides a contiguous view of another ImageInputStream which itself consists of a sequence of discontiguous segments containing the image data of interest. Such a stream may be used for example in conjunction with a RawImageInputStream to enable reading from a data source which has non-image data interspersed with the image data. For example, an image could be stored in a line-oriented fashion with prefix data such as a time stamp embedded in each line. @since 1.0 ././@LongLink0000000000000000000000000000014600000000000011566 Lustar rootrootjai-imageio-core-1.2/src/share/classes/com/sun/media/imageio/stream/FileChannelImageOutputStream.javajai-imageio-core-1.2/src/share/classes/com/sun/media/imageio/stream/FileChannelImageOutputStream.jav0000664000175100017510000005603710203036165032603 0ustar tilletille/* * $RCSfile: FileChannelImageOutputStream.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.1 $ * $Date: 2005-02-11 05:01:20 $ * $State: Exp $ */ package com.sun.media.imageio.stream; import java.io.File; import java.io.IOException; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.CharBuffer; import java.nio.DoubleBuffer; import java.nio.FloatBuffer; import java.nio.IntBuffer; import java.nio.LongBuffer; import java.nio.ShortBuffer; import java.nio.channels.FileChannel; import javax.imageio.stream.ImageInputStream; import javax.imageio.stream.ImageOutputStreamImpl; /** * A class which implements ImageOutputStream using a * FileChannel as the eventual data destination. * *

Memory mapping is used for reading and direct buffers for writing. * Only methods which provide significant performance improvement with * respect to the superclass implementation are overridden. Overridden * methods are not commented individually unless some noteworthy aspect * of the implementation must be described.

* *

The methods of this class are not synchronized.

* * @see javax.imageio.stream.ImageOutputStream * @see java.nio * @see java.nio.channels.FileChannel */ public class FileChannelImageOutputStream extends ImageOutputStreamImpl { /** The size of the write buffer. */ // XXX Should this be a different value? Smaller? // Should there be an instance variable with public // accessor/mutator methods? private static final int DEFAULT_WRITE_BUFFER_SIZE = 1048576; /** The FileChannel data destination. */ private FileChannel channel; /** A ByteBuffer used for writing to the channel. */ private ByteBuffer byteBuffer; /** An ImageInputStream used for reading. */ private ImageInputStream readStream = null; /** * Test method. * * @param args Command line arguments (ignored). * @throws Throwable for any Exception or Error. */ /* XXX public static void main(String[] args) throws Throwable { // Create files. java.io.RandomAccessFile fileFIOS = new java.io.RandomAccessFile("fios.tmp", "rw"); java.io.RandomAccessFile fileFCIOS = new java.io.RandomAccessFile("fcios.tmp", "rw"); // Create streams. javax.imageio.stream.ImageOutputStream fios = new javax.imageio.stream.FileImageOutputStream(fileFIOS); javax.imageio.stream.ImageOutputStream fcios = new FileChannelImageOutputStream(fileFCIOS.getChannel()); int datumSize = 4; // Write some ints (257, 258) fios.writeInts(new int[] {(int)256, (int)257, (int)258, (int)59}, 1, 2); fcios.writeInts(new int[] {(int)256, (int)257, (int)258, (int)259}, 1, 2); // Write a byte. fios.write(127); fcios.write(127); // Write some more ints (262, 263, 264). fios.writeInts(new int[] {(int)260, (int)261, (int)262, (int)263, (int)264, (int)265}, 2, 3); fcios.writeInts(new int[] {(int)260, (int)261, (int)262, (int)263, (int)264, (int)265}, 2, 3); // Seek to byte location. fios.seek(2*datumSize); fcios.seek(2*datumSize); // Read and print the byte. System.out.println(fios.read()); System.out.println(fcios.read()); // Seek to beginning. fios.seek(0); fcios.seek(0); int[] fiosInts = new int[10]; int[] fciosInts = new int[10]; // Read the ints. fios.readFully(fiosInts, 1, 2); fcios.readFully(fciosInts, 1, 2); // Print the ints for(int i = 0; i < 2; i++) { System.out.println((int)fiosInts[i+1]+" "+(int)fciosInts[i+1]); } // Seek to second set of ints fios.seek(2*datumSize+1); fcios.seek(2*datumSize+1); // Read the ints. fios.readFully(fiosInts, 1, 3); fcios.readFully(fciosInts, 1, 3); // Print the ints for(int i = 0; i < 3; i++) { System.out.println((int)fiosInts[i+1]+" "+(int)fciosInts[i+1]); } } */ /** * Constructs a FileChannelImageOutputStream from a * FileChannel. The initial position of the stream * stream is taken to be the position of the FileChannel * parameter when this constructor is invoked. The stream and flushed * positions are therefore both initialized to * channel.position(). * * @param channel the destination FileChannel. * * @throws IllegalArgumentException if channel is * null or is not open. * @throws IOException if a method invoked on channel * throws an IOException. */ public FileChannelImageOutputStream(FileChannel channel) throws IOException { // Check the parameter. if(channel == null) { throw new IllegalArgumentException("channel == null"); } else if(!channel.isOpen()) { throw new IllegalArgumentException("channel.isOpen() == false"); } // Save the channel reference. this.channel = channel; // Set stream and flushed positions to initial channel position. this.streamPos = this.flushedPos = channel.position(); // Allocate the write buffer. byteBuffer = ByteBuffer.allocateDirect(DEFAULT_WRITE_BUFFER_SIZE); // Create the read stream (initially zero-sized). readStream = new FileChannelImageInputStream(channel); } /** * Returns an ImageInputStream for reading. The * returned stream has byte order, stream and flushed positions, * and bit offset set to the current values for this stream. */ private ImageInputStream getImageInputStream() throws IOException { // Write any unwritten bytes. flushBuffer(); // Sync input stream state to state of this stream. readStream.setByteOrder(byteOrder); readStream.seek(streamPos); readStream.flushBefore(flushedPos); readStream.setBitOffset(bitOffset); return readStream; } /** * Write to the FileChannel any remaining bytes in * the byte output buffer. */ private void flushBuffer() throws IOException { if(byteBuffer.position() != 0) { // Set the limit to the position. byteBuffer.limit(byteBuffer.position()); // Set the position to zero. byteBuffer.position(0); // Write all bytes between zero and the previous position. channel.write(byteBuffer); // Prepare for subsequent put() calls if any. byteBuffer.clear(); } } // --- Implementation of superclass abstract methods. --- public int read() throws IOException { checkClosed(); bitOffset = 0; ImageInputStream inputStream = getImageInputStream(); streamPos++; return inputStream.read(); } public int read(byte[] b, int off, int len) throws IOException { // Check parameters. if(off < 0 || len < 0 || off + len > b.length) { throw new IndexOutOfBoundsException ("off < 0 || len < 0 || off + len > b.length"); } else if(len == 0) { return 0; } checkClosed(); bitOffset = 0; ImageInputStream inputStream = getImageInputStream(); int numBytesRead = inputStream.read(b, off, len); streamPos += numBytesRead; return numBytesRead; } public void write(int b) throws IOException { write(new byte[] {(byte)(b&0xff)}, 0, 1); } public void write(byte[] b, int off, int len) throws IOException { // Check parameters. if(off < 0 || len < 0 || off + len > b.length) { // NullPointerException will be thrown before this if b is null. throw new IndexOutOfBoundsException ("off < 0 || len < 0 || off + len > b.length"); } else if(len == 0) { return; } // Flush any bits in the current byte. flushBits(); // Zero the number of bytes to put. int numPut = 0; // Loop until all bytes have been put. do { // Determine number of bytes to put. int numToPut = Math.min(len - numPut, byteBuffer.remaining()); // If no bytes to put, the buffer has to be full as len // is always greater than numPut so flush it and return // to start of loop. if(numToPut == 0) { flushBuffer(); continue; } // Put the bytes in the buffer. byteBuffer.put(b, off + numPut, numToPut); // Increment the put counter. numPut += numToPut; } while(numPut < len); // Increment the stream position. streamPos += len; } // --- Overriding of superclass methods. --- // --- Bulk read methods --- public void readFully(char[] c, int off, int len) throws IOException { getImageInputStream().readFully(c, off, len); streamPos += 2*len; } public void readFully(short[] s, int off, int len) throws IOException { getImageInputStream().readFully(s, off, len); streamPos += 2*len; } public void readFully(int[] i, int off, int len) throws IOException { getImageInputStream().readFully(i, off, len); streamPos += 4*len; } public void readFully(long[] l, int off, int len) throws IOException { getImageInputStream().readFully(l, off, len); streamPos += 8*len; } public void readFully(float[] f, int off, int len) throws IOException { getImageInputStream().readFully(f, off, len); streamPos += 4*len; } public void readFully(double[] d, int off, int len) throws IOException { getImageInputStream().readFully(d, off, len); streamPos += 8*len; } // --- Bulk write methods --- public void writeChars(char[] c, int off, int len) throws IOException { // Check parameters. if(off < 0 || len < 0 || off + len > c.length) { // NullPointerException will be thrown before this if c is null. throw new IndexOutOfBoundsException ("off < 0 || len < 0 || off + len > c.length"); } else if(len == 0) { return; } // Flush any bits in the current byte. flushBits(); // Zero the number of chars put. int numPut = 0; // Get view buffer. CharBuffer viewBuffer = byteBuffer.asCharBuffer(); // Loop until all chars have been put. do { // Determine number of chars to put. int numToPut = Math.min(len - numPut, viewBuffer.remaining()); // If no chars to put, the buffer has to be full as len // is always greater than numPut so flush it and return // to start of loop. if(numToPut == 0) { flushBuffer(); continue; } // Put the chars in the buffer. viewBuffer.put(c, off + numPut, numToPut); // Sync the ByteBuffer position. byteBuffer.position(byteBuffer.position() + 2*numToPut); // Increment the put counter. numPut += numToPut; } while(numPut < len); // Increment the stream position. streamPos += 2*len; } public void writeShorts(short[] s, int off, int len) throws IOException { // Check parameters. if(off < 0 || len < 0 || off + len > s.length) { // NullPointerException will be thrown before this if s is null. throw new IndexOutOfBoundsException ("off < 0 || len < 0 || off + len > c.length"); } else if(len == 0) { return; } // Flush any bits in the current byte. flushBits(); // Zero the number of shorts put. int numPut = 0; // Get view buffer. ShortBuffer viewBuffer = byteBuffer.asShortBuffer(); // Loop until all shorts have been put. do { // Determine number of shorts to put. int numToPut = Math.min(len - numPut, viewBuffer.remaining()); // If no shorts to put, the buffer has to be full as len // is always greater than numPut so flush it and return // to start of loop. if(numToPut == 0) { flushBuffer(); continue; } // Put the shorts in the buffer. viewBuffer.put(s, off + numPut, numToPut); // Sync the ByteBuffer position. byteBuffer.position(byteBuffer.position() + 2*numToPut); // Increment the put counter. numPut += numToPut; } while(numPut < len); // Increment the stream position. streamPos += 2*len; } public void writeInts(int[] i, int off, int len) throws IOException { // Check parameters. if(off < 0 || len < 0 || off + len > i.length) { // NullPointerException will be thrown before this if i is null. throw new IndexOutOfBoundsException ("off < 0 || len < 0 || off + len > c.length"); } else if(len == 0) { return; } // Flush any bits in the current byte. flushBits(); // Zero the number of ints put. int numPut = 0; // Get view buffer. IntBuffer viewBuffer = byteBuffer.asIntBuffer(); // Loop until all ints have been put. do { // Determine number of ints to put. int numToPut = Math.min(len - numPut, viewBuffer.remaining()); // If no ints to put, the buffer has to be full as len // is always greater than numPut so flush it and return // to start of loop. if(numToPut == 0) { flushBuffer(); continue; } // Put the ints in the buffer. viewBuffer.put(i, off + numPut, numToPut); // Sync the ByteBuffer position. byteBuffer.position(byteBuffer.position() + 4*numToPut); // Increment the put counter. numPut += numToPut; } while(numPut < len); // Increment the stream position. streamPos += 4*len; } public void writeLongs(long[] l, int off, int len) throws IOException { // Check parameters. if(off < 0 || len < 0 || off + len > l.length) { // NullPointerException will be thrown before this if l is null. throw new IndexOutOfBoundsException ("off < 0 || len < 0 || off + len > c.length"); } else if(len == 0) { return; } // Flush any bits in the current byte. flushBits(); // Zero the number of longs put. int numPut = 0; // Get view buffer. LongBuffer viewBuffer = byteBuffer.asLongBuffer(); // Loop until all longs have been put. do { // Determine number of longs to put. int numToPut = Math.min(len - numPut, viewBuffer.remaining()); // If no longs to put, the buffer has to be full as len // is always greater than numPut so flush it and return // to start of loop. if(numToPut == 0) { flushBuffer(); continue; } // Put the longs in the buffer. viewBuffer.put(l, off + numPut, numToPut); // Sync the ByteBuffer position. byteBuffer.position(byteBuffer.position() + 8*numToPut); // Increment the put counter. numPut += numToPut; } while(numPut < len); // Increment the stream position. streamPos += 8*len; } public void writeFloats(float[] f, int off, int len) throws IOException { // Check parameters. if(off < 0 || len < 0 || off + len > f.length) { // NullPointerException will be thrown before this if c is null. throw new IndexOutOfBoundsException ("off < 0 || len < 0 || off + len > f.length"); } else if(len == 0) { return; } // Flush any bits in the current byte. flushBits(); // Zero the number of floats put. int numPut = 0; // Get view buffer. FloatBuffer viewBuffer = byteBuffer.asFloatBuffer(); // Loop until all floats have been put. do { // Determine number of floats to put. int numToPut = Math.min(len - numPut, viewBuffer.remaining()); // If no floats to put, the buffer has to be full as len // is always greater than numPut so flush it and return // to start of loop. if(numToPut == 0) { flushBuffer(); continue; } // Put the floats in the buffer. viewBuffer.put(f, off + numPut, numToPut); // Sync the ByteBuffer position. byteBuffer.position(byteBuffer.position() + 4*numToPut); // Increment the put counter. numPut += numToPut; } while(numPut < len); // Increment the stream position. streamPos += 4*len; } public void writeDoubles(double[] d, int off, int len) throws IOException { // Check parameters. if(off < 0 || len < 0 || off + len > d.length) { // NullPointerException will be thrown before this if d is null. throw new IndexOutOfBoundsException ("off < 0 || len < 0 || off + len > d.length"); } else if(len == 0) { return; } // Flush any bits in the current byte. flushBits(); // Zero the number of doubles put. int numPut = 0; // Get view buffer. DoubleBuffer viewBuffer = byteBuffer.asDoubleBuffer(); // Loop until all doubles have been put. do { // Determine number of doubles to put. int numToPut = Math.min(len - numPut, viewBuffer.remaining()); // If no doubles to put, the buffer has to be full as len // is always greater than numPut so flush it and return // to start of loop. if(numToPut == 0) { flushBuffer(); continue; } // Put the doubles in the buffer. viewBuffer.put(d, off + numPut, numToPut); // Sync the ByteBuffer position. byteBuffer.position(byteBuffer.position() + 8*numToPut); // Increment the put counter. numPut += numToPut; } while(numPut < len); // Increment the stream position. streamPos += 8*len; } // --- Other methods --- /** * Invokes the superclass method, writes any unwritten data, and * sets the internal reference to the source FileChannel * to null. The source FileChannel is not * closed. * * @exception IOException if an error occurs. */ // Note that this method is called by the superclass finalize() // so this class does not need to implement finalize(). public void close() throws IOException { // Flush any unwritten data in the buffer. flushBuffer(); // Close the read channel and clear the reference to it. readStream.close(); readStream = null; // Clear reference to the channel. channel = null; // Clear reference to the internal ByteBuffer. byteBuffer = null; // Chain to the superclass. super.close(); } /** * Returns the number of bytes currently in the FileChannel. * If an IOException is encountered when querying the * channel's size, -1L will be returned. * * @return The number of bytes in the channel * -1L to indicate unknown length. */ public long length() { // Initialize to value indicating unknown length. long length = -1L; // Set length to current size with respect to initial position. try { length = channel.size(); } catch(IOException e) { // Default to unknown length. } return length; } /** * Invokes the superclass method, writes any unwritten data, * and sets the channel position to the supplied parameter. */ public void seek(long pos) throws IOException { super.seek(pos); // Flush any unwritten data in the buffer. flushBuffer(); // Set the FileChannel position for WritableByteChannel.write(). channel.position(pos); } public void setByteOrder(ByteOrder networkByteOrder) { super.setByteOrder(networkByteOrder); byteBuffer.order(networkByteOrder); } } jai-imageio-core-1.2/src/share/classes/com/sun/media/imageio/stream/properties0000664000175100017510000000117610203036165026502 0ustar tilletille# # $RCSfile: properties,v $ # # Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved. # # Use is subject to license terms. # # $Revision: 1.1 $ # $Date: 2005-02-11 05:01:21 $ # $State: Exp $ # # Internationalization file for com.sun.media.imageio.stream RawImageInputStream0=Image offset and dimension arrays must be non-null and \ have the same length. RawImageInputStream1=Incorrect parser configuration. RawImageInputStream2=Number of width elements does not equal number of \ height elements. RawImageInputStream3=Image index is out of bounds. RawImageInputStream4=Cannot create a ColorModel for the supplied SampleModel. jai-imageio-core-1.2/src/share/classes/com/sun/media/imageio/stream/SegmentedImageInputStream.java0000664000175100017510000003654010664673230032316 0ustar tilletille/* * $RCSfile: SegmentedImageInputStream.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.2 $ * $Date: 2007-08-28 01:12:56 $ * $State: Exp $ */ package com.sun.media.imageio.stream; import java.io.IOException; import javax.imageio.stream.ImageInputStream; import javax.imageio.stream.ImageInputStreamImpl; /** * An implementation of the StreamSegmentMapper interface * that requires an explicit list of the starting locations and * lengths of the source segments. */ class StreamSegmentMapperImpl implements StreamSegmentMapper { private long[] segmentPositions; private int[] segmentLengths; public StreamSegmentMapperImpl(long[] segmentPositions, int[] segmentLengths) { this.segmentPositions = (long[])segmentPositions.clone(); this.segmentLengths = (int[])segmentLengths.clone(); } public StreamSegment getStreamSegment(long position, int length) { int numSegments = segmentLengths.length; for (int i = 0; i < numSegments; i++) { int len = segmentLengths[i]; if (position < len) { return new StreamSegment(segmentPositions[i] + position, Math.min(len - (int)position, length)); } position -= len; } return null; } public void getStreamSegment(long position, int length, StreamSegment seg) { int numSegments = segmentLengths.length; for (int i = 0; i < numSegments; i++) { int len = segmentLengths[i]; if (position < len) { seg.setStartPos(segmentPositions[i] + position); seg.setSegmentLength(Math.min(len - (int)position, length)); return; } position -= len; } seg.setStartPos(-1); seg.setSegmentLength(-1); return; } long length() { int numSegments = segmentLengths.length; long len = 0L; for(int i = 0; i < numSegments; i++) { len += segmentLengths[i]; } return len; } } /** * An implementation of the StreamSegmentMapper interface * for segments of equal length. */ class SectorStreamSegmentMapper implements StreamSegmentMapper { long[] segmentPositions; int segmentLength; int totalLength; int lastSegmentLength; public SectorStreamSegmentMapper(long[] segmentPositions, int segmentLength, int totalLength) { this.segmentPositions = (long[])segmentPositions.clone(); this.segmentLength = segmentLength; this.totalLength = totalLength; this.lastSegmentLength = totalLength - (segmentPositions.length - 1)*segmentLength; } public StreamSegment getStreamSegment(long position, int length) { int index = (int) (position/segmentLength); // Compute segment length int len = (index == segmentPositions.length - 1) ? lastSegmentLength : segmentLength; // Compute position within the segment position -= index*segmentLength; // Compute maximum legal length len -= position; if (len > length) { len = length; } return new StreamSegment(segmentPositions[index] + position, len); } public void getStreamSegment(long position, int length, StreamSegment seg) { int index = (int) (position/segmentLength); // Compute segment length int len = (index == segmentPositions.length - 1) ? lastSegmentLength : segmentLength; // Compute position within the segment position -= index*segmentLength; // Compute maximum legal length len -= position; if (len > length) { len = length; } seg.setStartPos(segmentPositions[index] + position); seg.setSegmentLength(len); } long length() { return (long)totalLength; } } /** * A SegmentedImageInputStream provides a view of a * subset of another ImageInputStream consiting of a series * of segments with given starting positions in the source stream and * lengths. The resulting stream behaves like an ordinary * ImageInputStream. * *

For example, given a ImageInputStream containing * data in a format consisting of a number of sub-streams stored in * non-contiguous sectors indexed by a directory, it is possible to * construct a set of SegmentedImageInputStreams, one for * each sub-stream, that each provide a view of the sectors comprising * a particular stream by providing the positions and lengths of the * stream's sectors as indicated by the directory. The complex * multi-stream structure of the original stream may be ignored by * users of the SegmentedImageInputStream, who see a * separate ImageInputStream for each sub-stream and do not * need to understand the directory structure at all. * *

For further efficiency, a directory structure such as in the * example described above need not be fully parsed in order to build * a SegmentedImageInputStream. Instead, the * StreamSegmentMapper interface allows the association * between a desired region of the output and an input segment to be * provided dynamically. This mapping might be computed by reading * from a directory in piecemeal fashion in order to avoid consuming * memory resources. */ public class SegmentedImageInputStream extends ImageInputStreamImpl { private ImageInputStream stream; private StreamSegmentMapper mapper; /** * Constructs a SegmentedImageInputStream * given a ImageInputStream as input * and an instance of StreamSegmentMapper. * * @param stream A source ImageInputStream * @param mapper An instance of the StreamSegmentMapper * interface. */ public SegmentedImageInputStream(ImageInputStream stream, StreamSegmentMapper mapper) { super(); this.stream = stream; this.mapper = mapper; } /** * Constructs a SegmentedImageInputStream given a * ImageInputStream as input and a list of the starting * positions and lengths of the segments of the source stream. * * @param stream A source ImageInputStream * @param segmentPositions An array of longs * giving the starting positions of the segments in the * source stream. * @param segmentLengths An array of ints * giving the lengths of segments in the source stream. */ public SegmentedImageInputStream(ImageInputStream stream, long[] segmentPositions, int[] segmentLengths) { this(stream, new StreamSegmentMapperImpl(segmentPositions, segmentLengths)); } /** * Constructs a SegmentedImageInputStream given a * ImageInputStream as input, a list of the starting * positions of the segments of the source stream, the common * length of each segment, and the total length of the segments. * *

This constructor is useful for selecting substreams * of sector-oriented file formats in which each segment * of the substream (except possibly the final segment) * occupies a fixed-length sector. * * @param stream A source ImageInputStream * @param segmentPositions An array of longs * giving the starting positions of the segments in the * source stream. * @param segmentLength The common length of each segment. * @param totalLength The total length of the source segments. */ public SegmentedImageInputStream(ImageInputStream stream, long[] segmentPositions, int segmentLength, int totalLength) { this(stream, new SectorStreamSegmentMapper(segmentPositions, segmentLength, totalLength)); } private StreamSegment streamSegment = new StreamSegment(); /** * Reads the next byte of data from the input stream. The value byte is * returned as an int in the range 0 to * 255. If no byte is available because the end of the stream * has been reached, the value -1 is returned. This method * blocks until input data is available, the end of the stream is detected, * or an exception is thrown. * * @return the next byte of data, or -1 if the end of the * stream is reached. * @exception IOException if an I/O error occurs. */ public int read() throws IOException { mapper.getStreamSegment(streamPos, 1, streamSegment); int streamSegmentLength = streamSegment.getSegmentLength(); if(streamSegmentLength < 0) { return -1; } stream.seek(streamSegment.getStartPos()); // XXX What happens if streamSegmentLength == 0? Should this // method also return -1 as above for streamSegmentLength < 0? int val = stream.read(); ++streamPos; return val; } /** * Reads up to len bytes of data from the input stream into * an array of bytes. An attempt is made to read as many as * len bytes, but a smaller number may be read, possibly * zero. The number of bytes actually read is returned as an integer. * *

This method blocks until input data is available, end of stream is * detected, or an exception is thrown. * *

If b is null, a * NullPointerException is thrown. * *

If off is negative, or len is negative, or * off+len is greater than the length of the array * b, then an IndexOutOfBoundsException is * thrown. * *

If len is zero, then no bytes are read and * 0 is returned; otherwise, there is an attempt to read at * least one byte. If no byte is available because the stream is at end of * stream, the value -1 is returned; otherwise, at least one * byte is read and stored into b. * *

The first byte read is stored into element b[off], the * next one into b[off+1], and so on. The number of bytes read * is, at most, equal to len. Let k be the number of * bytes actually read; these bytes will be stored in elements * b[off] through b[off+k-1], * leaving elements b[off+k] through * b[off+len-1] unaffected. * *

In every case, elements b[0] through * b[off] and elements b[off+len] through * b[b.length-1] are unaffected. * *

If the first byte cannot be read for any reason other than end of * stream, then an IOException is thrown. In particular, an * IOException is thrown if the input stream has been closed. * * @param b the buffer into which the data is read. * @param off the start offset in array b * at which the data is written. * @param len the maximum number of bytes to read. * @return the total number of bytes read into the buffer, or * -1 if there is no more data because the end of * the stream has been reached. * @exception IOException if an I/O error occurs. */ public int read(byte[] b, int off, int len) throws IOException { if (b == null) { throw new NullPointerException(); } if ((off < 0) || (len < 0) || (off + len > b.length)) { throw new IndexOutOfBoundsException(); } if (len == 0) { return 0; } mapper.getStreamSegment(streamPos, len, streamSegment); int streamSegmentLength = streamSegment.getSegmentLength(); if(streamSegmentLength < 0) { return -1; } stream.seek(streamSegment.getStartPos()); int nbytes = stream.read(b, off, streamSegmentLength); streamPos += nbytes; return nbytes; } public long length() { long len; if(mapper instanceof StreamSegmentMapperImpl) { len = ((StreamSegmentMapperImpl)mapper).length(); } else if(mapper instanceof SectorStreamSegmentMapper) { len = ((SectorStreamSegmentMapper)mapper).length(); } else if(mapper != null) { long pos = len = 0L; StreamSegment seg = mapper.getStreamSegment(pos, Integer.MAX_VALUE); while((len = seg.getSegmentLength()) > 0) { pos += len; seg.setSegmentLength(0); mapper.getStreamSegment(pos, Integer.MAX_VALUE, seg); } len = pos; } else { len = super.length(); } return len; } } jai-imageio-core-1.2/src/share/classes/com/sun/media/imageio/stream/I18N.java0000664000175100017510000000416310203036165025704 0ustar tilletille/* * $RCSfile: I18N.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.1 $ * $Date: 2005-02-11 05:01:20 $ * $State: Exp $ */ package com.sun.media.imageio.stream; import com.sun.media.imageioimpl.common.I18NImpl; final class I18N extends I18NImpl { static String getString(String key) { return getString("com.sun.media.imageio.stream.I18N", key); } } jai-imageio-core-1.2/src/share/classes/com/sun/media/imageio/stream/StreamSegment.java0000664000175100017510000000715410203036165030006 0ustar tilletille/* * $RCSfile: StreamSegment.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.1 $ * $Date: 2005-02-11 05:01:20 $ * $State: Exp $ */ package com.sun.media.imageio.stream; /** * A utility class representing a segment within a stream as a * long starting position and an int * length. */ public class StreamSegment { private long startPos = 0L; private int segmentLength = 0; /** * Constructs a StreamSegment. * The starting position and length are set to 0. */ public StreamSegment() {} /** * Constructs a StreamSegment with a * given starting position and length. * * @param startPos The initial position of the segment. * @param segmentLength The length of the segment. */ public StreamSegment(long startPos, int segmentLength) { this.startPos = startPos; this.segmentLength = segmentLength; } /** * Returns the starting position of the segment. * * @return The initial position of the segment. * @see #setStartPos */ public final long getStartPos() { return startPos; } /** * Sets the starting position of the segment. * * @param startPos The initial position of the segment. * @see #getStartPos */ public final void setStartPos(long startPos) { this.startPos = startPos; } /** * Returns the length of the segment. * * @return The length of the segment. * @see #setSegmentLength */ public final int getSegmentLength() { return segmentLength; } /** * Sets the length of the segment. * * @param segmentLength The length of the segment. * @see #getSegmentLength */ public final void setSegmentLength(int segmentLength) { this.segmentLength = segmentLength; } } jai-imageio-core-1.2/src/share/classes/com/sun/media/imageio/plugins/0000775000175100017510000000000011650556206024556 5ustar tilletillejai-imageio-core-1.2/src/share/classes/com/sun/media/imageio/plugins/jpeg2000/0000775000175100017510000000000011650556206026005 5ustar tilletille././@LongLink0000000000000000000000000000014500000000000011565 Lustar rootrootjai-imageio-core-1.2/src/share/classes/com/sun/media/imageio/plugins/jpeg2000/J2KImageReadParam.javajai-imageio-core-1.2/src/share/classes/com/sun/media/imageio/plugins/jpeg2000/J2KImageReadParam.java0000664000175100017510000001256310507271454031764 0ustar tilletille/* * $RCSfile: J2KImageReadParam.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.3 $ * $Date: 2006-09-29 19:25:32 $ * $State: Exp $ */ package com.sun.media.imageio.plugins.jpeg2000; import javax.imageio.ImageReadParam; /** * A subclass of ImageReadParam for reading images in * the JPEG 2000 format. * *

The decoding parameters for JPEG 2000 are listed below: * *

* * * * * * * * * * *
JPEG 2000 Plugin Decoding Parameters
Parameter Name Description
decodingRateSpecifies the decoding rate in bits per pixel (bpp) where the * number of pixels is related to the image's original size (Note: * this parameter is not affected by resolution). * The default is Double.MAX_VALUE. * It means decoding with the encoding rate. *
resolutionSpecifies the resolution level wanted for the decoded image * (0 means the lowest available resolution, the resolution * level gives an image with the original dimension). If the given index * is greater than the number of available resolution levels of the * compressed image, the decoded image has the lowest available * resolution (among all tile-components). This parameter affects only * the inverse wavelet transform and not the number of bytes read by the * codestream parser, which depends only on decodingRate. * The default value, -1, means to use the resolution level at encoding. *
*/ public class J2KImageReadParam extends ImageReadParam { /** Specifies the decoding rate in bits per pixel (bpp) where the * number of pixels is related to the image's original size * (Note: this number is not affected by resolution). */ private double decodingRate = Double.MAX_VALUE; /** Specifies the resolution level wanted for the decoded image * (0 means the lowest available resolution, the resolution * level gives an image with the original dimension). If the given index * is greater than the number of available resolution levels of the * compressed image, the decoded image has the lowest available * resolution (among all tile-components). This parameter * affects only the inverse wavelet transform but not the number * of bytes read by the codestream parser, which * depends only on decodingRate. */ private int resolution = -1; /** Constructs a default instance of J2KImageReadParam. */ public J2KImageReadParam() { super(); } /** * Sets decodingRate. * * @param rate the decoding rate in bits per pixel. * @see #getDecodingRate() */ public void setDecodingRate(double rate) { this.decodingRate = rate; } /** * Gets decodingRate. * * @return the decoding rate in bits per pixel. * @see #setDecodingRate(double) */ public double getDecodingRate() { return decodingRate; } /** * Sets resolution. * * @param resolution the resolution level with 0 being * the lowest available. * @see #getResolution() */ public void setResolution(int resolution) { this.resolution = Math.max(resolution, -1); } /** * Gets resolution. * * @return the resolution level with 0 being * the lowest available. * @see #setResolution(int) */ public int getResolution() { return resolution; } } jai-imageio-core-1.2/src/share/classes/com/sun/media/imageio/plugins/jpeg2000/package.html0000664000175100017510000010053010203036165030253 0ustar tilletille Package containing the public classes used by the Sun JPEG 2000 plug-in for the Image I/O Framework.

Image Metadata

Document Type Definition

The DTD for the native image metadata format is as follows:

<!DOCTYPE "com_sun_media_imageio_plugins_jpeg2000_image_1.0" [ 

  <!ELEMENT com_sun_media_imageio_plugins_jpeg2000_image_1.0 (JPEG2000SignatureBox,
                                              JPEG2000FileTypeBox,
                                              OtherBoxes) >

  <!-- JPEG2000HeaderSuperBox should be before JPEG2000CodeStreamBox;  This
      is the only constraint for the sequence of these boxes -->
  <!ELEMENT OtherBoxes (JPEG2000HeaderSuperBox,
                          JPEG2000CodeStreamBox,
                          JPEG2000IntellectualPropertyRightsBox*,
                          JPEG2000XMLBox*,
                          JPEG2000UUIDBox*,
                          JPEG2000UUIDInfoBox*)>

  <!-- JPEG 2000 Signature box -->
  <!ELEMENT JPEG2000SignatureBox EMPTY>
    <!ATTLIST JPEG2000SignatureBox
              Length CDATA #FIXED "12"
              Type CDATA #FIXED "jP  "
              Signature CDATA #FIXED "0x0D0A870A">

  <!-- JPEG 2000 File type box -->
  <!ELEMENT JPEG2000FileTypeBox (Brand, MinorVersion, CompatibilityList) >
    <!ELEMENT Brand (#PCDATA)>
    <!ELEMENT MinorVersion (#PCDATA)>
    <!ELEMENT CompatibilityList (#PCDATA)>
    <!ATTLIST JPEG2000FileTypeBox
              Length CDATA #FIXED "12"
              Type CDATA #FIXED "jP  "
              ExtraLength CDATA #IMPLIED>

  <!-- JPEG 2000 header super box-->
  <!ELEMENT JPEG2000HeaderSuperBox (JPEG2000HeaderBox, OptionalBoxes) >
    <!ELEMENT OptionalBoxes (JPEG2000BitsPerComponentBox,
                                JPEG2000ColorSpecificationBox,
                                JPEG2000PaletteBox?,
                                JPEG2000ComponentMappingBox?,
                                JPEG2000ChannelDefinitionBox?,
                                JPEG2000ResolutionBox?)>
    <!ATTLIST JPEG2000HeaderSuperBox
              Length CDATA #REQUIRED
              Type CDATA #FIXED "jp2h"
              ExtraLength CDATA #IMPLIED>

  <!-- JPEG 2000 image header box -->
  <!ELEMENT JPEG2000HeaderBox (Width, Height, NumComponents, BitDepth,
                                 CompressionType, UnknownColorspace,
                                 IntellectualProperty)>
    <!ELEMENT Width (#PCDATA)>
    <!ELEMENT Height (#PCDATA)>
    <!ELEMENT NumComponents (#PCDATA)>
    <!ELEMENT BitDepth (#PCDATA)>
    <!ELEMENT CompressionType (#PCDATA)>
    <!ELEMENT UnknownColorspace (#PCDATA)>
    <!ELEMENT IntellectualProperty (#PCDATA)>
    <!ATTLIST JPEG2000HeaderBox
              Length CDATA #FIXED "22"
              Type CDATA #FIXED "ihdr">

  <!-- JPEG 2000 bits per component box -->
  <!ELEMENT JPEG2000BitsPerComponentBox (BitDepth)>
    <!ATTLIST JPEG2000BitsPerComponentBox
              Length CDATA #REQUIRED
              Type CDATA #FIXED "bpcc"
              ExtraLength CDATA #IMPLIED>

  <!-- JPEG 2000 color specification box -->
  <!ELEMENT JPEG2000ColorSpecificationBox (Method, Precedence,
                                             ApproximationAccuracy,
                                             EnumeratedColorSpace,
                                             ICCProfile)>
    <!ELEMENT Method (#PCDATA)>
    <!ELEMENT Precedence (#PCDATA)>
    <!ELEMENT ApproximationAccuracy (#PCDATA)>
    <!ELEMENT EnumeratedColorSpace (#PCDATA)>
    <!ELEMENT ICCProfile (#PCDATA)>
    <!ATTLIST JPEG2000ColorSpecificationBox
              Length CDATA #REQUIRED
              Type CDATA #FIXED "colr"
              ExtraLength CDATA #IMPLIED>

  <!-- JPEG 2000 palette box -->
  <!ELEMENT JPEG2000PaletteBox (NumberEntries, NumberColors,
                                  BitDepth,
                                  LUT)>
    <!ELEMENT NumberEntries (#PCDATA)>
    <!ELEMENT NumberColors (#PCDATA)>
    <!ELEMENT LUT (LUTRow*)>
    <!ELEMENT LUTRow (#PCDATA)>
    <!ATTLIST JPEG2000PaletteBox
              Length CDATA #REQUIRED
              Type CDATA #FIXED "pclr"
              ExtraLength CDATA #IMPLIED>

  <!-- JPEG 2000 component mapping box-->
  <!ELEMENT JPEG2000ComponentMappingBox (Component, ComponentType,
                                           ComponentAssociation)>
    <!ELEMENT Component (#PCDATA)>
    <!ELEMENT ComponentType (#PCDATA)>
    <!ELEMENT ComponentAssociation (#PCDATA)>
    <!ATTLIST JPEG2000ComponentMappingBox
              Length CDATA #REQUIRED
              Type CDATA #FIXED "cmap"
              ExtraLength CDATA #IMPLIED>

  <!-- JPEG 2000 channel definition box-->
  <!ELEMENT JPEG2000ChannelDefinitionBox (NumberOfDefinition, Definitions)>
    <!ELEMENT NumberOfDefinition (#PCDATA)>
    <!ELEMENT Definitions (ChannelNumber, ChannelType)*>
    <!ELEMENT ChannelNumber (#PCDATA)>
    <!ELEMENT ChannelType (#PCDATA)>
    <!ELEMENT ChannelAssociation (#PCDATA)>
    <!ATTLIST JPEG2000ChannelDefinitionBox
              Length CDATA #REQUIRED
              Type CDATA #FIXED "cdef"
              ExtraLength CDATA #IMPLIED>

  <!-- JPEG 2000 resolution box-->
  <!ELEMENT JPEG2000ResolutionBox (JPEG2000CaptureResolutionBox,
                                     JPEG2000DefaultDisplayResolutionBox)>
    <!ATTLIST JPEG2000ResolutionBox
              Length CDATA #REQUIRED
              Type CDATA #FIXED "res "
              ExtraLength CDATA #IMPLIED>

  <!-- JPEG 2000 capture resolution box-->
  <!ELEMENT JPEG2000CaptureResolutionBox (VerticalResolutionNumerator,
                                            VerticalResolutionDenominator,
                                            HorizontalResolutionNumerator,
                                            HorizontalResolutionDenominator,
                                            VerticalResolutionExponent,
                                            HorizontalResolutionExponent)>
    <!ELEMENT VerticalResolutionNumerator (#PCDATA)>
    <!ELEMENT VerticalResolutionDenominator (#PCDATA)>
    <!ELEMENT HorizontalResolutionNumerator (#PCDATA)>
    <!ELEMENT HorizontalResolutionDenominator (#PCDATA)>
    <!ELEMENT VerticalResolutionExponent (#PCDATA)>
    <!ELEMENT HorizontalResolutionExponent (#PCDATA)>
    <!ATTLIST JPEG2000CaptureResolutionBox
              Length CDATA #REQUIRED
              Type CDATA #FIXED "resc"
              ExtraLength CDATA #IMPLIED>

  <!-- JPEG 2000 default display resolution box-->
  <!ELEMENT JPEG2000DefaultDisplayResolutionBox (VerticalResolutionNumerator,
                                            VerticalResolutionDenominator,
                                            HorizontalResolutionNumerator,
                                            HorizontalResolutionDenominator,
                                            VerticalResolutionExponent,
                                            HorizontalResolutionExponent)>
    <!ATTLIST JPEG2000DefaultDisplayResolutionBox
              Length CDATA #REQUIRED
              Type CDATA #FIXED "resd"
              ExtraLength CDATA #IMPLIED>

  <!-- JPEG 2000 code stream box-->
  <!ELEMENT JPEG2000CodeStreamBox (CodeStream)>
    <!ELEMENT CodeStream (#PCDATA)>
    <!ATTLIST JPEG2000CodeStreamBox
              Length CDATA #REQUIRED
              Type CDATA #FIXED "jp2c"
              ExtraLength CDATA #IMPLIED>

  <!-- JPEG 2000 intellectual property rights box-->
  <!ELEMENT JPEG2000IntellectualPropertyRightsBox (Content)>
    <!ELEMENT Content (#PCDATA)>
    <!ATTLIST JPEG2000IntellectualPropertyRightsBox
              Length CDATA #REQUIRED
              Type CDATA #FIXED "jp2i"
              ExtraLength CDATA #IMPLIED>

  <!-- JPEG 2000 XML box-->
  <!ELEMENT JPEG2000XMLBox (Content)>
    <!ATTLIST JPEG2000XMLBox
              Length CDATA #REQUIRED
              Type CDATA #FIXED "xml "
              ExtraLength CDATA #IMPLIED>

  <!-- JPEG 2000 UUID box-->
  <!ELEMENT JPEG2000UUIDBox (UUID, Data)>
    <!ELEMENT UUID (#PCDATA)>
    <!ELEMENT Data (#PCDATA)>
    <!ATTLIST JPEG2000UUIDBox
              Length CDATA #REQUIRED
              Type CDATA #FIXED "uuid"
              ExtraLength CDATA #IMPLIED>

  <!-- JPEG 2000 UUID info box-->
  <!ELEMENT JPEG2000UUIDInfoBox (JPEG2000UUIDListBox, JPEG2000DataEntryURLBox)>
    <!ATTLIST JPEG2000UUIDInfoBox
              Length CDATA #REQUIRED
              Type CDATA #FIXED "uinf"
              ExtraLength CDATA #IMPLIED>

  <!-- JPEG 2000 UUID list box-->
  <!ELEMENT JPEG2000UUIDListBox (NumberUUID, UUID*)>
    <!ELEMENT NumberUUID (#PCDATA)>
    <!ATTLIST JPEG2000UUIDListBox
              Length CDATA #REQUIRED
              Type CDATA #FIXED "ulst"
              ExtraLength CDATA #IMPLIED>

  <!-- JPEG 2000 Data Entry URL box-->
  <!ELEMENT JPEG2000DataEntryURLBox (Version, Flags, Location)>
    <!ELEMENT Version (#PCDATA)>
    <!ELEMENT Flags (#PCDATA)>
    <!ELEMENT URL (#PCDATA)>
    <!ATTLIST JPEG2000DataEntryURLBox
              Length CDATA #REQUIRED
              Type CDATA #FIXED "url "
              ExtraLength CDATA #IMPLIED> ]

XML Schema

The XML schema for the native image metadata format is as follows:

<?xml version="1.0" ?>
<!--Schema for JPEG 2000 image format -->

<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
	    xmlns="http://com.sun.media.imageio"
	    targetNamespace="http://com.sun.media.imageio">

  <!-- JPEG 2000 Image File-->
  <xsd:element name="com_sun_media_imageio_plugins_jpeg2000_image_1.0">
    <xsd:complexType>
      <xsd:sequence>
        <xsd:element ref="JPEG2000SignatureBox" />
        <xsd:element ref="JPEG2000FileTypeBox" />
        <!-- JPEG2000HeaderSuperBox should be before JPEG2000CodeStreamBox;
          This is the only constraint for the sequence of these boxes -->
        <xsd:element name="OtherBoxes">
        <xsd:complexType>
          <xsd:all>
            <xsd:element ref="JPEG2000HeaderSuperBox" />
            <xsd:element ref="JPEG2000CodeStreamBox" />

            <xsd:element ref="JPEG2000IntellectualPropertyRightsBox" minOccurs="0" maxOccurs="unbounded" />
            <xsd:element ref="JPEG2000XMLBox" minOccurs="0" maxOccurs="unbounded" />
            <xsd:element ref="JPEG2000UUIDBox" minOccurs="0" maxOccurs="unbounded" />
            <xsd:element ref="JPEG2000UUIDInfoBox" minOccurs="0" maxOccurs="unbounded" />
          </xsd:all>
        </xsd:complexType>
        </xsd:element>
      </xsd:sequence>
    </xsd:complexType>
  </xsd:element>

  <!-- JPEG 2000 Signature box -->
  <xsd:element name="JPEG2000SignatureBox">
    <xsd:complexType>
      <xsd:attribute name="Length" type="xsd:unsignedInt" use="required" fixed="12" />
      <xsd:attribute name="Type" type="xsd:string" use="required" fixed="jP  " />
      <xsd:attribute name="Signature" type="xsd:hexBinary" use="required" fixed="0D0A870A" />
    </xsd:complexType>
  </xsd:element>

  <!-- JPEG 2000 File type box -->
  <xsd:element name="JPEG2000FileTypeBox">
    <xsd:complexType>
      <xsd:sequence>
        <xsd:element name="Brand" type = "xsd:unsignedInt" />

        <xsd:element name="MinorVersion" minOccurs="0">
          <xsd:simpleType>
            <xsd:restriction base="xsd:unsignedInt">
              <xsd:enumeration value="0" />
            </xsd:restriction>
          </xsd:simpleType>
        </xsd:element>

        <xsd:element name="CompatibilityList" type="IntegerList" />
      </xsd:sequence>
      <xsd:attribute name="Length" type="xsd:unsignedInt" use="required" />
      <xsd:attribute name="Type" type="xsd:string" use="required" fixed="ftyp" />
      <xsd:attribute name="ExtraLength" type="LongNoLessThan16" use="optional" />
    </xsd:complexType>
  </xsd:element>

  <!-- JPEG 2000 header super box-->
  <xsd:element name="JPEG2000HeaderSuperBox">
    <xsd:complexType>
      <xsd:sequence>
        <xsd:element ref="JPEG2000HeaderBox" />
        <xsd:element name="OptionalBoxes" minOccurs="0" >
          <xsd:complexType>
            <xsd:all>
              <xsd:element ref="JPEG2000BitsPerComponentBox" />
              <xsd:element ref="JPEG2000ColorSpecificationBox" />
              <xsd:element ref="JPEG2000PaletteBox" minOccurs="0" />
              <xsd:element ref="JPEG2000ComponentMappingBox" minOccurs="0" />
              <xsd:element ref="JPEG2000ChannelDefinitionBox" minOccurs="0" />
              <xsd:element ref="JPEG2000ResolutionBox" minOccurs="0" />
            </xsd:all>
          </xsd:complexType>
        </xsd:element>
      </xsd:sequence>
      <xsd:attribute name="Length" type="xsd:unsignedInt" use="required" />
      <xsd:attribute name="Type" type="xsd:string" use="required" fixed="jp2h" />
      <xsd:attribute name="ExtraLength" type="LongNoLessThan16" use="optional" />
    </xsd:complexType>
  </xsd:element>

  <!-- JPEG 2000 image header box -->
  <xsd:element name="JPEG2000HeaderBox">
    <xsd:complexType>
      <xsd:sequence>
        <xsd:element name="Width" type="xsd:unsignedInt" />
        <xsd:element name="Height" type="xsd:unsignedInt" />
        <xsd:element name="NumComponents" type="xsd:unsignedShort" />
        <xsd:element name="BitDepth" type="xsd:byte" />
        <xsd:element name="CompressionType" type="xsd:unsignedByte" />
        <xsd:element name="UnknownColorspace" type="xsd:unsignedByte" />
        <xsd:element name="IntellectualProperty">
          <xsd:simpleType>
            <xsd:restriction base="xsd:unsignedByte">
              <xsd:enumeration value="0" />
              <xsd:enumeration value="1" />
            </xsd:restriction>
          </xsd:simpleType>
        </xsd:element>

      </xsd:sequence>
      <xsd:attribute name="Length" type="xsd:unsignedInt" use="required" fixed="22" />
      <xsd:attribute name="Type" type="xsd:string" use="required" fixed="ihdr" />
      <xsd:attribute name="ExtraLength" type="LongNoLessThan16" use="optional" />
    </xsd:complexType>
  </xsd:element>

  <!-- JPEG 2000 bits per component box -->
  <xsd:element name="JPEG2000BitsPerComponentBox">
    <xsd:complexType>
      <xsd:sequence>
        <xsd:element name="BitDepth" type="ByteList" />
      </xsd:sequence>
      <xsd:attribute name="Length" type="xsd:unsignedInt" use="required" />
      <xsd:attribute name="Type" type="xsd:string" use="required" fixed="bpcc" />
      <xsd:attribute name="ExtraLength" type="LongNoLessThan16" use="optional" />
    </xsd:complexType>
  </xsd:element>

  <!-- JPEG 2000 color specification box -->
  <xsd:element name="JPEG2000ColorSpecificationBox">
    <xsd:complexType>
      <xsd:sequence>

        <xsd:element name="Method">
          <xsd:simpleType>
            <xsd:restriction base="xsd:unsignedByte">
              <xsd:enumeration value="1" />
              <xsd:enumeration value="2" />
            </xsd:restriction>
          </xsd:simpleType>
        </xsd:element>

        <xsd:element name="Precedence" type="xsd:byte" />
        <xsd:element name="ApproximationAccuracy" type="xsd:byte" />
        <xsd:element name="EnumeratedColorSpace" type="xsd:unsignedInt" />
        <xsd:element name="ICCProfile" type="xsd:anyType" />

      </xsd:sequence>
      <xsd:attribute name="Length" type="xsd:unsignedInt" use="required" />
      <xsd:attribute name="Type" type="xsd:string" use="required" fixed="colr" />
      <xsd:attribute name="ExtraLength" type="LongNoLessThan16" use="optional" />
    </xsd:complexType>
  </xsd:element>

  <!-- JPEG 2000 palette box -->
  <xsd:element name="JPEG2000PaletteBox">
    <xsd:complexType>
      <xsd:sequence>

        <xsd:element name="NumberEntries">
          <xsd:simpleType>
            <xsd:restriction base="xsd:unsignedShort">
              <xsd:minInclusive value="1" />
              <xsd:maxInclusive value="1024" />
            </xsd:restriction>
          </xsd:simpleType>
        </xsd:element>

        <xsd:element name="NumberColors">
          <xsd:simpleType>
            <xsd:restriction base="xsd:unsignedShort">
              <xsd:minInclusive value="1" />
              <xsd:maxInclusive value="255" />
            </xsd:restriction>
          </xsd:simpleType>
        </xsd:element>

        <xsd:element name="BitDepth" type="ByteList" />

        <xsd:element name="LUT">
          <xsd:complexType>
            <xsd:sequence>
              <xsd:element name="LUTRow" maxOccurs="unbounded" type="ByteList" />
            </xsd:sequence>
          </xsd:complexType>
        </xsd:element>

      </xsd:sequence>
      <xsd:attribute name="Length" type="xsd:unsignedInt" use="required" />
      <xsd:attribute name="Type" type="xsd:string" use="required" fixed="pclr" />
      <xsd:attribute name="ExtraLength" type="LongNoLessThan16" use="optional" />
    </xsd:complexType>
  </xsd:element>

  <!-- JPEG 2000 component mapping box-->
  <xsd:element name="JPEG2000ComponentMappingBox">
    <xsd:complexType>
      <xsd:sequence maxOccurs="unbounded">
        <xsd:element name="Component" type="xsd:unsignedShort" />
        <xsd:element name="ComponentType" type="xsd:unsignedByte" />
        <xsd:element name="ComponentAssociation" type="xsd:unsignedByte" />
      </xsd:sequence>
      <xsd:attribute name="Length" type="xsd:unsignedInt" use="required" />
      <xsd:attribute name="Type" type="xsd:string" use="required" fixed="cmap" />
      <xsd:attribute name="ExtraLength" type="LongNoLessThan16" use="optional" />
    </xsd:complexType>
  </xsd:element>

  <!-- JPEG 2000 channel definition box-->
  <xsd:element name="JPEG2000ChannelDefinitionBox">
    <xsd:complexType>
      <xsd:sequence>
        <xsd:element name="NumberOfDefinition" type="xsd:unsignedShort" />
        <xsd:element name="Definitions">
          <xsd:complexType>
            <xsd:sequence maxOccurs="unbounded">
              <xsd:element name="ChannelNumber" type="xsd:unsignedShort" />
              <xsd:element name="ChannelType">
                <xsd:simpleType>
                  <xsd:restriction base="xsd:unsignedShort">
                    <xsd:enumeration value="0" />
                    <xsd:enumeration value="1" />
                    <xsd:enumeration value="2" />
                    <xsd:enumeration value="65535" />
                  </xsd:restriction>
                </xsd:simpleType>
              </xsd:element>
              <xsd:element name="ChannelAssociation" type="xsd:unsignedShort" />
            </xsd:sequence>
          </xsd:complexType>
        </xsd:element>
      </xsd:sequence>
      <xsd:attribute name="Length" type="xsd:unsignedInt" use="required" />
      <xsd:attribute name="Type" type="xsd:string" use="required" fixed="cdef" />
      <xsd:attribute name="ExtraLength" type="LongNoLessThan16" use="optional" />
    </xsd:complexType>
  </xsd:element>

  <!-- JPEG 2000 resolution box-->
  <xsd:element name="JPEG2000ResolutionBox">
    <xsd:complexType>
      <xsd:sequence>
        <xsd:element ref="JPEG2000CaptureResolutionBox" minOccurs="0" />
        <xsd:element ref="JPEG2000DefaultDisplayResolutionBox" minOccurs="0" />
      </xsd:sequence>

      <xsd:attribute name="Length" type="xsd:unsignedInt" use="required" />
      <xsd:attribute name="Type" type="xsd:string" use="required" fixed="res " />
      <xsd:attribute name="ExtraLength" type="LongNoLessThan16" use="optional" />
    </xsd:complexType>
  </xsd:element>

  <!-- JPEG 2000 capture resolution box-->
  <xsd:element name="JPEG2000CaptureResolutionBox">
    <xsd:complexType>

      <xsd:sequence>
        <xsd:element name="VerticalResolutionNumerator" type="xsd:unsignedShort" />
        <xsd:element name="VerticalResolutionDenominator" type="xsd:unsignedShort" />
        <xsd:element name="HorizontalResolutionNumerator" type="xsd:unsignedShort" />
        <xsd:element name="HorizontalResolutionDenominator" type="xsd:unsignedShort" />
        <xsd:element name="VerticalResolutionExponent" type="xsd:byte" />
        <xsd:element name="HorizontalResolutionExponent" type="xsd:byte" />
      </xsd:sequence>

      <xsd:attribute name="Length" type="xsd:unsignedInt" use="required" fixed ="18" />
      <xsd:attribute name="Type" type="xsd:string" use="required" fixed="resc" />
      <xsd:attribute name="ExtraLength" type="LongNoLessThan16" use="optional" />
    </xsd:complexType>
  </xsd:element>

  <!-- JPEG 2000 default display resolution box-->
  <xsd:element name="JPEG2000DefaultDisplayResolutionBox">
    <xsd:complexType>

      <xsd:sequence>
        <xsd:element name="VerticalResolutionNumerator" type="xsd:unsignedShort" />
        <xsd:element name="VerticalResolutionDenominator" type="xsd:unsignedShort" />
        <xsd:element name="HorizontalResolutionNumerator" type="xsd:unsignedShort" />
        <xsd:element name="HorizontalResolutionDenominator" type="xsd:unsignedShort" />
        <xsd:element name="VerticalResolutionExponent" type="xsd:byte" />
        <xsd:element name="HorizontalResolutionExponent" type="xsd:byte" />
      </xsd:sequence>

      <xsd:attribute name="Length" type="xsd:unsignedInt" use="required" fixed ="18" />
      <xsd:attribute name="Type" type="xsd:string" use="required" fixed="resd" />
      <xsd:attribute name="ExtraLength" type="LongNoLessThan16" use="optional" />
    </xsd:complexType>
  </xsd:element>

  <!-- JPEG 2000 code stream box-->
  <xsd:element name="JPEG2000CodeStreamBox" >
    <xsd:complexType>
      <xsd:sequence>
        <xsd:element name="CodeStream" type="xsd:anyType" />
      </xsd:sequence>
      <xsd:attribute name="Length" type="xsd:unsignedInt" use="required" />
      <xsd:attribute name="Type" type="xsd:string" use="required" fixed="jp2c" />
      <xsd:attribute name="ExtraLength" type="LongNoLessThan16" use="optional" />
    </xsd:complexType>
  </xsd:element>

  <!-- JPEG 2000 intellectual property rights box-->
  <xsd:element name="JPEG2000IntellectualPropertyRightsBox" >
    <xsd:complexType>
      <xsd:sequence>
        <!-- The structure of this box is defined in Part 2 so keep it
                  general -->
        <xsd:element name="Content" type="xsd:anyType"  />
      </xsd:sequence>
      <xsd:attribute name="Length" type="xsd:unsignedInt" use="required" />
      <xsd:attribute name="Type" type="xsd:string" use="required" fixed="jp2i" />
      <xsd:attribute name="ExtraLength" type="LongNoLessThan16" use="optional" />
    </xsd:complexType>
  </xsd:element>

  <!-- JPEG 2000 XML box-->
  <xsd:element name="JPEG2000XMLBox">
    <xsd:complexType>
      <xsd:sequence>
        <xsd:element name="Content" type="xsd:string" />
      </xsd:sequence>
      <xsd:attribute name="Length" type="xsd:unsignedInt" use="required" />
      <xsd:attribute name="Type" type="xsd:string" use="required" fixed="xml " />
      <xsd:attribute name="ExtraLength" type="LongNoLessThan16" use="optional" />
    </xsd:complexType>
  </xsd:element>

  <!-- JPEG 2000 UUID box-->
  <xsd:element name="JPEG2000UUIDBox">
    <xsd:complexType>
      <xsd:sequence>
        <xsd:element name="UUID">
          <xsd:simpleType>
            <xsd:restriction base="ByteList">
              <xsd:length value="16" />
            </xsd:restriction>
          </xsd:simpleType>
        </xsd:element>
        <xsd:element name="Data" type="xsd:anyType" />
      </xsd:sequence>

      <xsd:attribute name="Length" type="xsd:unsignedInt" use="required" />
      <xsd:attribute name="Type" type="xsd:string" use="required" fixed="uuid" />
      <xsd:attribute name="ExtraLength" type="LongNoLessThan16" use="optional" />
    </xsd:complexType>
  </xsd:element>

  <!-- JPEG 2000 UUID info box-->
  <xsd:element name="JPEG2000UUIDInfoBox">
    <xsd:complexType>
      <xsd:sequence>
        <xsd:element ref="JPEG2000UUIDListBox" />
        <xsd:element ref="JPEG2000DataEntryURLBox" />
      </xsd:sequence>
      <xsd:attribute name="Length" type="xsd:unsignedInt" use="required" />
      <xsd:attribute name="Type" type="xsd:string" use="required" fixed="uinf" />
      <xsd:attribute name="ExtraLength" type="LongNoLessThan16" use="optional" />
    </xsd:complexType>
  </xsd:element>

  <!-- JPEG 2000 UUID list box-->
  <xsd:element name="JPEG2000UUIDListBox">
    <xsd:complexType>
      <xsd:sequence>
        <xsd:element name="NumberUUID" type="xsd:unsignedShort" />
        <xsd:element name="UUID" maxOccurs="unbounded">
          <xsd:simpleType>
            <xsd:restriction base="ByteList">
              <xsd:length value="16" />
            </xsd:restriction>
          </xsd:simpleType>
        </xsd:element>
      </xsd:sequence>
      <xsd:attribute name="Length" type="xsd:unsignedInt" use="required" />
      <xsd:attribute name="Type" type="xsd:string" use="required" fixed="ulst" />
      <xsd:attribute name="ExtraLength" type="LongNoLessThan16" use="optional" />
    </xsd:complexType>
  </xsd:element>

  <!-- JPEG 2000 Data Entry URL box-->
  <xsd:element name="JPEG2000DataEntryURLBox">
    <xsd:complexType>
      <xsd:sequence>
        <xsd:element name="Version" type="xsd:unsignedByte" />
        <xsd:element name="Flags">
          <xsd:simpleType>
            <xsd:restriction base="ByteList">
              <xsd:length value="3" />
            </xsd:restriction>
          </xsd:simpleType>
        </xsd:element>
        <xsd:element name="URL" type="xsd:anyURI" />
      </xsd:sequence>
      <xsd:attribute name="Length" type="xsd:unsignedInt" use="required" />
      <xsd:attribute name="Type" type="xsd:string" use="required" fixed="url " />
      <xsd:attribute name="ExtraLength" type="LongNoLessThan16" use="optional" />
    </xsd:complexType>
  </xsd:element>

  <!-- The basic types defined and used in JPEG 2000 schema -->
  <xsd:simpleType name="IntegerList">
    <xsd:list itemType="xsd:unsignedInt" />
  </xsd:simpleType>

  <xsd:simpleType name="ByteList">
    <xsd:list itemType="xsd:byte" />
  </xsd:simpleType>

  <xsd:simpleType name="LongNoLessThan16">
    <xsd:restriction base="xsd:long">
      <xsd:minInclusive value="16" />
    </xsd:restriction>
  </xsd:simpleType>

</xsd:schema>

Standard Image Metadata Derivation

The conversion between the native image metadata format and the standard image metadata format is based on the following mapping:
Standard Metadata Attribute        JP2 Box Element
---------------------------        ---------------
/Chroma
    /ColorSpaceType
	@name			   if UnknownColorSpace in header box is 0
				   then if EnumeratedColorSpace in
					color specification box is 16 --> RGB
				        if EnumeratedColorSpace in
                                        color specification box is 17 -->GRAY
    /NumChannels
	@value			   if palette box exists
					the component number in palette box 
				   else
					the component number in header box
    /Palette			   if palette box exits
	/PaletteEntry
	    @index		   
	    @red		   lut[index][0]
	    @green		   lut[index][1]
	    @blue		   lut[index][2]
	    @alpha 		   lut[index][3] if the component number is 4

/Compression
    @value			   "JPEG2000"

/Data
    /SampleFormat
	@value			   if the palette box exists, -->"Index"
				   else if bit depth in header box or 
					bits per component box has the sign bit
					     --> "SignedIntegral"
					else --> "UnsignedIntegral"
    /BitsPerSample
	@value			   derive from the bit depth of header box
				   or bits per component box
    /PlanarConfiguration
	@value			   --> "TileInterleaved"

/Dimension
    /PixelAspectRatio
	@value			   the ratio of the horizontal and vertical
				   resolution in the capture resolution box
    /HorizontalPhysicalPixelSpacing
	@value			   derived from the horizontal resolution
				   (in pixel-per-meter) in the capture 
				   resolution box
    /VerticalPhysicalPixelSpacing 
        @value                     derived from the vertical resolution         
                                   (in pixel-per-meter) in the capture i
				   resolution box
/Transparency
    /Alpha
	@value			   --> "none" if no channel definition box or
					no alpha channel is defined in channel
					definition box
				   --> "nonpremultiplied" if no premultiplied
					channel is defined in the channel 
					definition box
				   --> "premultiplied" if any premultiplied
					channel(s) defined in the channel 
					definition box
/Text
    /TextEntry
	@value			   The content of any XML box; each XML box
				   defines a TextEntry
@since 1.0 ././@LongLink0000000000000000000000000000014600000000000011566 Lustar rootrootjai-imageio-core-1.2/src/share/classes/com/sun/media/imageio/plugins/jpeg2000/J2KImageWriteParam.javajai-imageio-core-1.2/src/share/classes/com/sun/media/imageio/plugins/jpeg2000/J2KImageWriteParam.jav0000664000175100017510000003442610504346562032044 0ustar tilletille/* * $RCSfile: J2KImageWriteParam.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.2 $ * $Date: 2006-09-20 23:23:30 $ * $State: Exp $ */ package com.sun.media.imageio.plugins.jpeg2000; import java.awt.Rectangle; import java.awt.image.Raster; import java.awt.image.RenderedImage; import java.util.Collections; import java.util.Locale; import java.util.Iterator; import javax.imageio.ImageWriteParam; /** * A subclass of ImageWriteParam for writing images in * the JPEG 2000 format. * *

JPEG 2000 plugin supports to losslessly or lossy compress gray-scale, * RGB, and RGBA images with byte, unsigned short or short data type. It also * supports losslessly compress bilevel, and 8-bit color indexed images. The * result data is in the of JP2 format -- JPEG 2000 Part 1 or baseline format. * *

The parameters for encoding JPEG 2000 are listed in the following table: * *

* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
JPEG 2000 Plugin Decoding Parameters
Parameter Name Description
numDecompositionLevels The number of decomposition levels to generate. This value must * be in the range * 0 ≤ numDecompositionLevels ≤ 32 * . The default value is 5. Note that the number * of resolution levels is * numDecompositionLevels + 1. * The number of decomposition levels is constant across * all components and all tiles. *
encodingRate The bitrate in bits-per-pixel for encoding. Should be set when * lossy compression scheme is used. With the default value * Double.MAX_VALUE, a lossless compression will be done. *
lossless Indicates using the lossless scheme or not. It is equivalent to * use reversible quantization and 5x3 integer wavelet filters. The * default is true. *
componentTransformation Specifies to utilize the component transformation on some tiles. * If the wavelet transform is reversible (w5x3 filter), the Reversible * Component Transformation (RCT) is applied. If not reversible * (w9x7 filter), the Irreversible Component Transformation (ICT) is used. *
filters Specifies which wavelet filters to use for the specified * tile-components. JPEG 2000 part I only supports w5x3 and w9x7 filters. *
codeBlockSize Specifies the maximum code-block size to use for tile-component. * The maximum width and height is 1024, however the block size * (i.e. width x height) must not exceed 4096. The minimum width and * height is 4. The default values are (64, 64). *
progressionType Specifies which type of progression should be used when generating * the codestream. *

The format is ont of the progression types defined below: * *

res : Resolution-Layer-Component-Position *

layer: Layer-Resolution-Component-Position *

res-pos: Resolution-Position-Component-Layer *

pos-comp: Position-Component-Resolution-Layer *

comp-pos: Component-Position-Resolution-Layer *

SOPSpecifies whether start of packet (SOP) markers should be used. * true enables, false disables it. The default value is false. *
EPHSpecifies whether end of packet header (EPH) markers should be used. * true enables, false disables it. The default value is false. *
writeCodeStreamOnlySpecifies whether write only the jpeg2000 code stream, i.e, no any * box is written. The default value is false. *
*/ public class J2KImageWriteParam extends ImageWriteParam { /** The filter for lossy compression. */ public static final String FILTER_97 = "w9x7"; /** The filter for lossless compression. */ public static final String FILTER_53 = "w5x3"; /** * The number of decomposition levels. */ private int numDecompositionLevels = 5; /** * The bitrate in bits-per-pixel for encoding. Should be set when lossy * compression scheme is used. The default is * Double.MAX_VALUE. */ private double encodingRate = Double.MAX_VALUE; /** * Indicates using the lossless scheme or not. It is equivalent to * use reversible quantization and 5x3 integer wavelet filters. */ private boolean lossless = true; /** Specifies to utilize the component transformation with some tiles. * If the wavelet transform is reversible (w5x3 filter), the * Reversible Component Transformation (RCT) is applied. If not reversible * (w9x7 filter), the Irreversible Component Transformation (ICT) * is used. */ private boolean componentTransformation = true; /** Specifies which filters to use for the specified tile-components. * JPEG 2000 part I only supports w5x3 and w9x7 filters. */ private String filter = FILTER_53; /** Specifies the maximum code-block size to use for tile-component. * The maximum width and height is 1024, however the image area * (i.e. width x height) must not exceed 4096. The minimum * width and height is 4. Default: 64 64. */ private int[] codeBlockSize = new int[]{64, 64}; /** See above. */ private String progressionType = "layer"; /** Specifies whether end of packet header (EPH) markers should be used. * true enables, false disables it. Default: false. */ private boolean EPH = false; /** Specifies whether start of packet (SOP) markers should be used. * true enables, false disables it. Default: false. */ private boolean SOP = false; /** Specifies whether write only the jpeg2000 code stream, i.e, no any * box is written. The default value is false. */ private boolean writeCodeStreamOnly = false; /** * Constructor which sets the Locale. * * @param locale a Locale to be used to localize * compression type names and quality descriptions, or * null. */ public J2KImageWriteParam(Locale locale) { super(locale); setDefaults(); } /** * Constructs a J2KImageWriteParam object with default * values for all parameters. */ public J2KImageWriteParam() { super(); setDefaults(); } /** Set source */ private void setDefaults() { // override the params in the super class canOffsetTiles = true; canWriteTiles = true; canOffsetTiles = true; compressionTypes = new String[] {"JPEG2000"}; canWriteCompressed = true; tilingMode = MODE_EXPLICIT; } /** * Sets numDecompositionLevels. * * @param numDecompositionLevels the number of decomposition levels. * @throws IllegalArgumentException if numDecompositionLevels * is negative or greater than 32. * @see #getNumDecompositionLevels */ public void setNumDecompositionLevels(int numDecompositionLevels) { if(numDecompositionLevels < 0 || numDecompositionLevels > 32) { throw new IllegalArgumentException ("numDecompositionLevels < 0 || numDecompositionLevels > 32"); } this.numDecompositionLevels = numDecompositionLevels; } /** * Gets numDecompositionLevels. * * @return the number of decomposition levels. * @see #setNumDecompositionLevels */ public int getNumDecompositionLevels() { return numDecompositionLevels; } /** * Sets encodingRate. * * @param rate the encoding rate in bits-per-pixel. * @see #getEncodingRate() */ public void setEncodingRate(double rate) { this.encodingRate = rate; if (encodingRate != Double.MAX_VALUE) { lossless = false; filter = FILTER_97; } else { lossless = true; filter = FILTER_53; } } /** * Gets encodingRate. * * @return the encoding rate in bits-per-pixel. * @see #setEncodingRate(double) */ public double getEncodingRate() { return encodingRate; } /** * Sets lossless. * * @param lossless whether the compression scheme is lossless. * @see #getLossless() */ public void setLossless(boolean lossless) { this.lossless = lossless; } /** * Gets lossless. * * @return whether the compression scheme is lossless. * @see #setLossless(boolean) */ public boolean getLossless() { return lossless; } /** * Sets filter. * * @param value which wavelet filters to use for the specified * tile-components. * @see #getFilter() */ public void setFilter(String value) { filter = value; } /** * Gets filters. * * @return which wavelet filters to use for the specified * tile-components. * @see #setFilter(String) */ public String getFilter() { return filter; } /** * Sets componentTransformation. * * @param value whether to utilize the component transformation. * @see #getComponentTransformation() */ public void setComponentTransformation(boolean value) { componentTransformation = value; } /** * Gets componentTransformation. * * @return whether to utilize the component transformation. * @see #setComponentTransformation(boolean) */ public boolean getComponentTransformation() { return componentTransformation; } /** * Sets codeBlockSize. * * @param value the maximum code-block size to use per tile-component. * @see #getCodeBlockSize() */ public void setCodeBlockSize(int[] value) { codeBlockSize = value; } /** * Gets codeBlockSize. * * @return the maximum code-block size to use per tile-component. * @see #setCodeBlockSize(int[]) */ public int[] getCodeBlockSize() { return codeBlockSize; } /** * Sets SOP. * * @param value whether start of packet (SOP) markers should be used. * @see #getSOP() */ public void setSOP(boolean value) { SOP = value; } /** * Gets SOP. * * @return whether start of packet (SOP) markers should be used. * @see #setSOP(boolean) */ public boolean getSOP() { return SOP; } /** * Sets EPH. * * @param value whether end of packet header (EPH) markers should be used. * @see #getEPH() */ public void setEPH(boolean value) { EPH = value; } /** * Gets EPH. * * @return whether end of packet header (EPH) markers should be used. * @see #setEPH(boolean) */ public boolean getEPH() { return EPH; } /** * Sets progressionType. * * @param value which type of progression should be used when generating * the codestream. * @see #getProgressionType() */ public void setProgressionType(String value) { progressionType = value; } /** * Gets progressionType. * * @return which type of progression should be used when generating * the codestream. * @see #setProgressionType(String) */ public String getProgressionType() { return progressionType; } /** Sets writeCodeStreamOnly. * * @param value Whether the jpeg2000 code stream only or the jp2 format * will be written into the output. * @see #getWriteCodeStreamOnly() */ public void setWriteCodeStreamOnly(boolean value) { writeCodeStreamOnly = value; } /** Gets writeCodeStreamOnly. * * @return whether the jpeg2000 code stream only or the jp2 format * will be written into the output. * @see #setWriteCodeStreamOnly(boolean) */ public boolean getWriteCodeStreamOnly() { return writeCodeStreamOnly; } } jai-imageio-core-1.2/src/share/classes/com/sun/media/imageio/plugins/pnm/0000775000175100017510000000000011650556206025350 5ustar tilletillejai-imageio-core-1.2/src/share/classes/com/sun/media/imageio/plugins/pnm/package.html0000664000175100017510000000762410203036165027630 0ustar tilletille Package containing the public classes used by the Sun PNM plug-in for the Image I/O Framework.

Image Metadata

The XML schema for the native image metadata format is as follows:
<?xml version="1.0" encoding="UTF-8"?>

<!-- Schema for PNM native image metadata format. -->

<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
            xmlns="http://com.sun.media.imageio.plugins"
            targetNamespace="http://com.sun.media.imageio.plugins">

  <xsd:element name="com_sun_media_imageio_plugins_pnm_image_1.0">
    <xsd:complexType>
      <xsd:sequence>

	<!-- The specific format name -->
        <xsd:element name="FormatName">
          <xsd:simpleType>
            <xsd:restriction base="xsd:string">
              <xsd:enumeration value="PBM"/>
              <xsd:enumeration value="PGM"/>
              <xsd:enumeration value="PPM"/>
            </xsd:restriction>
          </xsd:simpleType>
        </xsd:element> <!-- FormatName -->

	<!-- The variant -->
        <xsd:element name="Variant">
          <xsd:simpleType>
            <xsd:restriction base="xsd:string">
              <xsd:enumeration value="ASCII"/>
              <xsd:enumeration value="RAWBITS"/>
            </xsd:restriction>
          </xsd:simpleType>
        </xsd:element> <!-- Variant -->

        <!-- Image width -->
        <xsd:element name="Width" type="xsd:unsignedInt"/>

        <!-- Image height -->
        <xsd:element name="Height" type="xsd:unsignedInt"/>

	<!-- The maximum sample value (PGM and PPM only) -->
        <xsd:element name="MaximumSample" type="xsd:unsignedByte"
	             minOccurs="0"/>

	<!-- Comment block(s) if present -->
        <xsd:element name="Comment" type="xsd:string"
                     minOccurs="0" maxOccurs="unbounded"/>

      </xsd:sequence>
    </xsd:complexType>
  </xsd:element> <!-- pnm_image_1.0 -->

</xsd:schema>

@since 1.0 jai-imageio-core-1.2/src/share/classes/com/sun/media/imageio/plugins/pnm/PNMImageWriteParam.java0000664000175100017510000000617510203036165031603 0ustar tilletille/* * $RCSfile: PNMImageWriteParam.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.1 $ * $Date: 2005-02-11 05:01:16 $ * $State: Exp $ */ package com.sun.media.imageio.plugins.pnm; import javax.imageio.ImageWriteParam; /** * A subclass of ImageWriteParam for writing images in * the PNM format. * *

This class allows for the specification of whether to write * in the ASCII or raw variants of the PBM, PGM, and PPM formats; * by default, the raw variant is used. */ public class PNMImageWriteParam extends ImageWriteParam { private boolean raw = true; /** * Constructs a PNMImageWriteParam object with default values * for parameters. */ public PNMImageWriteParam() {} /** * Sets the representation to be used. If the raw * parameter is true, the raw representation will be used; * otherwise the ASCII representation will be used. * * @param raw true if raw format is to be used. * @see #getRaw() */ public void setRaw(boolean raw) { this.raw = raw; } /** * Returns the value of the raw parameter. The default * value is true. * * @return whether the data are written in raw representation. * @see #setRaw(boolean) */ public boolean getRaw() { return raw; } } jai-imageio-core-1.2/src/share/classes/com/sun/media/imageio/plugins/bmp/0000775000175100017510000000000011650556206025334 5ustar tilletillejai-imageio-core-1.2/src/share/classes/com/sun/media/imageio/plugins/bmp/BMPImageWriteParam.java0000664000175100017510000002143510420012324031537 0ustar tilletille/* * $RCSfile: BMPImageWriteParam.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.2 $ * $Date: 2006-04-14 21:32:04 $ * $State: Exp $ */ package com.sun.media.imageio.plugins.bmp; import java.util.Locale; import javax.imageio.ImageWriteParam; import com.sun.media.imageioimpl.plugins.bmp.BMPConstants; /** * A subclass of ImageWriteParam for encoding images in * the BMP format. * *

This class allows for the specification of various parameters * while writing a BMP format image file. By default, the data layout * is bottom-up, such that the pixels are stored in bottom-up order, * the first scanline being stored last. * *

The particular compression scheme to be used can be specified by using * the setCompressionType() method with the appropriate type * string. The compression scheme specified will be honored if and only if it * is compatible with the type of image being written. If the specified * compression scheme is not compatible with the type of image being written * then the IOException will be thrown by the BMP image writer. * If the compression type is not set explicitly then getCompressionType() * will return null. In this case the BMP image writer will select * a compression type that supports encoding of the given image without loss * of the color resolution. *

The compression type strings and the image type(s) each supports are * listed in the following * table: * *

* * * * * * * *
Compression Types
Type String Description Image Types
BI_RGB Uncompressed RLE <= 8-bits/sample
BI_RLE8 8-bit Run Length Encoding <= 8-bits/sample
BI_RLE4 4-bit Run Length Encoding <= 4-bits/sample
BI_BITFIELDS Packed data 16 or 32 bits/sample
BI_JPEG JPEG encoded grayscale or RGB image
* *

When BI_BITFIELDS is used, if the image encoded has a * DirectColorModel, the bit mask in the color model will be * written into the stream. Otherwise, only 5-5-5 16-bit image or 8-8-8 * 32-bit images are supported. * */ public class BMPImageWriteParam extends ImageWriteParam { // deprecated version constants /** * Constant for BMP version 2. * * @deprecated */ public static final int VERSION_2 = 0; /** * Constant for BMP version 3. * * @deprecated */ public static final int VERSION_3 = 1; /** * Constant for BMP version 4. * * @deprecated */ public static final int VERSION_4 = 2; /** * Constant for BMP version 5. * * @deprecated */ public static final int VERSION_5 = 3; private boolean topDown = false; /** * Constructs a BMPImageWriteParam set to use a given * Locale and with default values for all parameters. * * @param locale a Locale to be used to localize * compression type names and quality descriptions, or * null. */ public BMPImageWriteParam(Locale locale) { super(locale); // Set compression types ("BI_RGB" denotes uncompressed). compressionTypes = BMPConstants.compressionTypeNames; // Set compression flag. canWriteCompressed = true; compressionMode = MODE_COPY_FROM_METADATA; compressionType = compressionTypes[BMPConstants.BI_RGB]; } /** * Constructs an BMPImageWriteParam object with default * values for all parameters and a null Locale. */ public BMPImageWriteParam() { this(null); } /** * Returns the BMP version to be used. The default is * VERSION_3. * * @deprecated * @return the BMP version number. */ public int getVersion() { return VERSION_3; } /** * If set, the data will be written out in a top-down manner, the first * scanline being written first. * * Any compression other than BI_RGB or * BI_BITFIELDS is incompatible with the data being * written in top-down order. Setting the topDown argument * to true will be honored only when the compression * type at the time of writing the image is one of the two mentioned * above. Otherwise, the topDown setting will be ignored. * * @param topDown whether the data are written in top-down order. */ public void setTopDown(boolean topDown) { this.topDown = topDown; } /** * Returns the value of the topDown parameter. * The default is false. * * @return whether the data are written in top-down order. */ public boolean isTopDown() { return topDown; } // Override superclass implementation to add a new check that compression // is not being set when image has been specified to be encoded in a top // down fashion /** * Sets the compression type to one of the values indicated by * getCompressionTypes. If a value of * null is passed in, any previous setting is * removed. * *

The method first invokes * {@link javax.imageio.ImageWriteParam.#setCompressionType(String) * setCompressionType()} * with the supplied value of compressionType. Next, * if {@link #isTopDown()} returns true and the * value of compressionType is incompatible with top-down * order, {@link #setTopDown(boolean)} is invoked with parameter * topDown set to false. The image will * then be written in bottom-up order with the specified * compressionType.

* * @param compressionType one of the Strings returned * by getCompressionTypes, or null to * remove any previous setting. * * @exception UnsupportedOperationException if the writer does not * support compression. * @exception IllegalStateException if the compression mode is not * MODE_EXPLICIT. * @exception UnsupportedOperationException if there are no * settable compression types. * @exception IllegalArgumentException if * compressionType is non-null but is not * one of the values returned by getCompressionTypes. * * @see #isTopDown * @see #setTopDown * @see #getCompressionTypes * @see #getCompressionType * @see #unsetCompression */ public void setCompressionType(String compressionType) { super.setCompressionType(compressionType); if (!(compressionType.equals("BI_RGB")) && !(compressionType.equals("BI_BITFIELDS")) && topDown == true) { topDown = false; } } } jai-imageio-core-1.2/src/share/classes/com/sun/media/imageio/plugins/bmp/package.html0000664000175100017510000001555110203036165027612 0ustar tilletille Package containing the public classes used by the Sun BMP plug-in for the Image I/O Framework.

Image Metadata

The XML schema for the native image metadata format is as follows:
<?xml version="1.0" encoding="UTF-8"?>

<!-- Schema for BMP native image metadata format. -->

<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
            xmlns="http://com.sun.media.imageio.plugins"
            targetNamespace="http://com.sun.media.imageio.plugins">

  <!-- Coordinates of a point in the CIE XYZ color space. -->
  <xsd:complexType name="XYZPoint">
    <xsd:sequence>
      <xsd:element name="X" type="xsd:double"/>
      <xsd:element name="Y" type="xsd:double"/>
      <xsd:element name="Z" type="xsd:double"/>
    </xsd:sequence>
  </xsd:complexType>

  <!-- BMP Schema 1.0 root element. -->
  <xsd:element name="com_sun_media_imageio_plugins_bmp_image_1.0">
    <xsd:complexType>
      <xsd:sequence>

        <!-- BMP version string -->
        <xsd:element name="BMPVersion" type="xsd:string"/>

        <!-- Bitmap width -->
        <xsd:element name="Width" type="xsd:unsignedInt"/>

        <!-- Bitmap height -->
        <xsd:element name="Height" type="xsd:unsignedInt"/>

        <!-- Number of bits per pixel -->
        <xsd:element name="BitsPerPixel" type="xsd:unsignedShort"/>

        <!-- Compression type -->
        <xsd:element name="Compression" type="xsd:unsignedInt" minOccurs="0"/>

        <!-- Image size in bytes -->
        <xsd:element name="ImageSize" type="xsd:unsignedInt" minOccurs="0"/>

	<!-- Resolution in pixels per unit distance -->
        <xsd:element name="PixelsPerMeter" minOccurs="0">
	  <xsd:complexType>
            <xsd:sequence>
              <xsd:element name="X" type="xsd:unsignedInt"/>
              <xsd:element name="Y" type="xsd:unsignedInt"/>
            </xsd:sequence>
	  </xsd:complexType>
        </xsd:element> <!-- PixelsPerMeter -->


	<!-- Number of color indexes in the color table actually used -->
        <xsd:element name="ColorsUsed" type="xsd:unsignedInt" minOccurs="0"/>

	<!-- Number of color indexes considered important for display -->
        <xsd:element name="ColorsImportant" type="xsd:unsignedInt"
		     minOccurs="0"/>

	<!-- Color masks; present for BI_BITFIELDS compression only -->
        <xsd:element name="Mask" minOccurs="0">
	  <xsd:complexType>
            <xsd:sequence>
              <xsd:element name="Red" type="xsd:unsignedInt"/>
              <xsd:element name="Green" type="xsd:unsignedInt"/>
              <xsd:element name="Blue" type="xsd:unsignedInt"/>
              <xsd:element name="Alpha" type="xsd:unsignedInt" minOccurs="0"/>
            </xsd:sequence>
	  </xsd:complexType>
	</xsd:element>

        <!-- Color space  -->
        <xsd:element name="ColorSpaceType" type="xsd:unsignedInt" 
		     minOccurs="0"/>

	<!-- CIE XYZ for the LCS_CALIBRATED_RGB color space -->
        <xsd:element name="CIEXYZEndpoints" minOccurs="0">
	  <xsd:complexType>
            <xsd:sequence>
              <xsd:element name="Red" type="XYZPoint"/>
              <xsd:element name="Green" type="XYZPoint"/>
              <xsd:element name="Blue" type="XYZPoint"/>
            </xsd:sequence>
	  </xsd:complexType>
        </xsd:element>

	<!-- Gamma values for the LCS_CALIBRATED_RGB color space -->
        <xsd:element name="Gamma" minOccurs="0">
	  <xsd:complexType>
            <xsd:sequence>
              <xsd:element name="Red" type="xsd:unsignedInt"/>
              <xsd:element name="Green" type="xsd:unsignedInt"/>
              <xsd:element name="Blue" type="xsd:unsignedInt"/>
            </xsd:sequence>
	  </xsd:complexType>
	</xsd:element>

	<!-- Rendering intent -->
        <xsd:element name="Intent" type="xsd:unsignedInt" minOccurs="0"/>

	<!-- The image colormap -->
        <xsd:element name="Palette" minOccurs="0">
	  <xsd:complexType>
            <xsd:sequence>
              <xsd:element name="PaletteEntry">
	        <xsd:complexType>
                  <xsd:sequence>
                    <xsd:element name="Red" type="xsd:unsignedByte"/>
                    <xsd:element name="Green" type="xsd:unsignedByte"/>
                    <xsd:element name="Blue" type="xsd:unsignedByte"/>
                    <xsd:element name="Alpha" type="xsd:unsignedByte" minOccurs="0"/>
                  </xsd:sequence>
	        </xsd:complexType>
              </xsd:element>
            </xsd:sequence>
	  </xsd:complexType>
	</xsd:element>

      </xsd:sequence>
    </xsd:complexType>
  </xsd:element> <!-- bmp_image_1.0 -->

</xsd:schema>
@since 1.0 jai-imageio-core-1.2/src/share/classes/com/sun/media/imageio/plugins/bmp/properties0000664000175100017510000000050310203036165027437 0ustar tilletille# # $RCSfile: properties,v $ # # Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved. # # Use is subject to license terms. # # $Revision: 1.1 $ # $Date: 2005-02-11 05:01:15 $ # $State: Exp $ # # Internationalization file for com.sun.media.imageio.plugins.bmp BMPImageWriteParam0=Only versions 2-5 are supported. jai-imageio-core-1.2/src/share/classes/com/sun/media/imageio/plugins/bmp/I18N.java0000664000175100017510000000417510203036165026653 0ustar tilletille/* * $RCSfile: I18N.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.1 $ * $Date: 2005-02-11 05:01:14 $ * $State: Exp $ */ package com.sun.media.imageio.plugins.bmp; import com.sun.media.imageioimpl.common.I18NImpl; final class I18N extends I18NImpl { static String getString(String key) { return getString("com.sun.media.imageio.plugins.bmp.I18N", key); } } jai-imageio-core-1.2/src/share/classes/com/sun/media/imageio/plugins/tiff/0000775000175100017510000000000011650556206025506 5ustar tilletillejai-imageio-core-1.2/src/share/classes/com/sun/media/imageio/plugins/tiff/TIFFTagSet.java0000664000175100017510000001474110203036165030206 0ustar tilletille/* * $RCSfile: TIFFTagSet.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.1 $ * $Date: 2005-02-11 05:01:19 $ * $State: Exp $ */ package com.sun.media.imageio.plugins.tiff; // Should implement Set? import java.util.Collections; import java.util.Iterator; import java.util.List; import java.util.Set; import java.util.SortedMap; import java.util.SortedSet; import java.util.TreeMap; import java.util.TreeSet; /** * A class representing a set of TIFF tags. Each tag in the set must * have a unique number (this is a limitation of the TIFF * specification itself). * *

This class and its subclasses are responsible for mapping * between raw tag numbers and TIFFTag objects, which * contain additional information about each tag, such as the tag's * name, legal data types, and mnemonic names for some or all of ts * data values. * * @see TIFFTag */ public class TIFFTagSet { private SortedMap allowedTagsByNumber = new TreeMap(); private SortedMap allowedTagsByName = new TreeMap(); /** * Constructs a TIFFTagSet. */ private TIFFTagSet() {} /** * Constructs a TIFFTagSet, given a List * of TIFFTag objects. * * @param tags a List object containing * TIFFTag objects to be added to this tag set. * * @throws IllegalArgumentException if tags is * null, or contains objects that are not instances * of the TIFFTag class. */ public TIFFTagSet(List tags) { if (tags == null) { throw new IllegalArgumentException("tags == null!"); } Iterator iter = tags.iterator(); while (iter.hasNext()) { Object o = iter.next(); if (!(o instanceof TIFFTag)) { throw new IllegalArgumentException( "tags contains a non-TIFFTag!"); } TIFFTag tag = (TIFFTag)o; allowedTagsByNumber.put(new Integer(tag.getNumber()), tag); allowedTagsByName.put(tag.getName(), tag); } } /** * Returns the TIFFTag from this set that is * associated with the given tag number, or null if * no tag exists for that number. * * @param tagNumber the number of the tag to be retrieved. * * @return the numbered TIFFTag, or null. */ public TIFFTag getTag(int tagNumber) { return (TIFFTag)allowedTagsByNumber.get(new Integer(tagNumber)); } /** * Returns the TIFFTag having the given tag name, or * null if the named tag does not belong to this tag set. * * @param tagName the name of the tag to be retrieved, as a * String. * * @return the named TIFFTag, or null. * * @throws IllegalArgumentException if tagName is * null. */ public TIFFTag getTag(String tagName) { if (tagName == null) { throw new IllegalArgumentException("tagName == null!"); } return (TIFFTag)allowedTagsByName.get(tagName); } /** * Retrieves an unmodifiable numerically increasing set of tag numbers. * *

The returned object is unmodifiable and contains the tag * numbers of all TIFFTags in this TIFFTagSet * sorted into ascending order according to * {@link Integer#compareTo(Object)}.

* * @return All tag numbers in this set. */ public SortedSet getTagNumbers() { Set tagNumbers = allowedTagsByNumber.keySet(); SortedSet sortedTagNumbers; if(tagNumbers instanceof SortedSet) { sortedTagNumbers = (SortedSet)tagNumbers; } else { sortedTagNumbers = new TreeSet(tagNumbers); } return Collections.unmodifiableSortedSet(sortedTagNumbers); } /** * Retrieves an unmodifiable lexicographically increasing set of tag names. * *

The returned object is unmodifiable and contains the tag * names of all TIFFTags in this TIFFTagSet * sorted into ascending order according to * {@link String#compareTo(Object)}.

* * @return All tag names in this set. */ public SortedSet getTagNames() { Set tagNames = allowedTagsByName.keySet(); SortedSet sortedTagNames; if(tagNames instanceof SortedSet) { sortedTagNames = (SortedSet)tagNames; } else { sortedTagNames = new TreeSet(tagNames); } return Collections.unmodifiableSortedSet(sortedTagNames); } } ././@LongLink0000000000000000000000000000015200000000000011563 Lustar rootrootjai-imageio-core-1.2/src/share/classes/com/sun/media/imageio/plugins/tiff/EXIFInteroperabilityTagSet.javajai-imageio-core-1.2/src/share/classes/com/sun/media/imageio/plugins/tiff/EXIFInteroperabilityTagSet0000664000175100017510000001020110330454115032522 0ustar tilletille/* * $RCSfile: EXIFInteroperabilityTagSet.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.1 $ * $Date: 2005-10-28 16:56:45 $ * $State: Exp $ */ package com.sun.media.imageio.plugins.tiff; import java.util.ArrayList; import java.util.List; /** * A class representing the tags found in an EXIF Interoperability IFD. * * @see EXIFTIFFTagSet */ public class EXIFInteroperabilityTagSet extends TIFFTagSet { /** * A tag indicating the identification of the Interoperability rule * (type ASCII). * * @see #INTEROPERABILITY_INDEX_R98 * @see #INTEROPERABILITY_INDEX_THM */ public static final int TAG_INTEROPERABILITY_INDEX = 1; /** * A value to be used with the "InteroperabilityIndex" tag. Indicates * a file conforming to the R98 file specification of Recommended Exif * Interoperability Rules (ExifR98) or to the DCF basic file stipulated * by the Design Rule for Camera File System (type ASCII). * * @see #TAG_INTEROPERABILITY_INDEX */ public static final String INTEROPERABILITY_INDEX_R98 = "R98"; /** * A value to be used with the "InteroperabilityIndex" tag. Indicates * a file conforming to the DCF thumbnail file stipulated by the Design * rule for Camera File System (type ASCII). * * @see #TAG_INTEROPERABILITY_INDEX */ public static final String INTEROPERABILITY_INDEX_THM = "THM"; private static EXIFInteroperabilityTagSet theInstance = null; static class InteroperabilityIndex extends TIFFTag { public InteroperabilityIndex() { super("InteroperabilityIndex", TAG_INTEROPERABILITY_INDEX, 1 << TIFFTag.TIFF_ASCII); } } private static List tags; private static void initTags() { tags = new ArrayList(42); tags.add(new EXIFInteroperabilityTagSet.InteroperabilityIndex()); } private EXIFInteroperabilityTagSet() { super(tags); } /** * Returns the shared instance of * EXIFInteroperabilityTagSet. * * @return the EXIFInteroperabilityTagSet instance. */ public synchronized static EXIFInteroperabilityTagSet getInstance() { if (theInstance == null) { initTags(); theInstance = new EXIFInteroperabilityTagSet(); tags = null; } return theInstance; } } jai-imageio-core-1.2/src/share/classes/com/sun/media/imageio/plugins/tiff/TIFFDecompressor.java0000664000175100017510000033617610574340060031500 0ustar tilletille/* * $RCSfile: TIFFDecompressor.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.3 $ * $Date: 2007-03-09 20:14:40 $ * $State: Exp $ */ package com.sun.media.imageio.plugins.tiff; import java.awt.Rectangle; import java.awt.Transparency; import java.awt.color.ColorSpace; import java.awt.image.BufferedImage; import java.awt.image.ColorModel; import java.awt.image.ComponentColorModel; import java.awt.image.ComponentSampleModel; import java.awt.image.DataBuffer; import java.awt.image.DataBufferByte; import java.awt.image.DataBufferFloat; import java.awt.image.DataBufferInt; import java.awt.image.DataBufferShort; import java.awt.image.DataBufferUShort; import java.awt.image.IndexColorModel; import java.awt.image.MultiPixelPackedSampleModel; import java.awt.image.PixelInterleavedSampleModel; import java.awt.image.Raster; import java.awt.image.SampleModel; import java.awt.image.SinglePixelPackedSampleModel; import java.awt.image.WritableRaster; import java.io.ByteArrayInputStream; import java.io.IOException; import java.nio.ByteOrder; import javax.imageio.IIOException; import javax.imageio.ImageReader; import javax.imageio.ImageTypeSpecifier; import javax.imageio.metadata.IIOMetadata; import javax.imageio.stream.ImageInputStream; import javax.imageio.stream.MemoryCacheImageInputStream; import com.sun.media.imageioimpl.common.BogusColorSpace; import com.sun.media.imageioimpl.common.ImageUtil; import com.sun.media.imageioimpl.common.SimpleCMYKColorSpace; /** * A class defining a pluggable TIFF decompressor. * *

The mapping between source and destination Y coordinates is * given by the equations: * *

 * dx = (sx - sourceXOffset)/subsampleX + dstXOffset;
 * dy = (sy - sourceYOffset)/subsampleY + dstYOffset;
 * 
* * Note that the mapping from source coordinates to destination * coordinates is not one-to-one if subsampling is being used, since * only certain source pixels are to be copied to the * destination. However, * the inverse mapping is always one-to-one: * *
 * sx = (dx - dstXOffset)*subsampleX + sourceXOffset;
 * sy = (dy - dstYOffset)*subsampleY + sourceYOffset;
 * 
* *

Decompressors may be written with various levels of complexity. * The most complex decompressors will override the * decode method, and will perform all the work of * decoding, subsampling, offsetting, clipping, and format conversion. * This approach may be the most efficient, since it is possible to * avoid the use of extra image buffers, and it may be possible to * avoid decoding portions of the image that will not be copied into * the destination. * *

Less ambitious decompressors may override the * decodeRaw method, which is responsible for * decompressing the entire tile or strip into a byte array (or other * appropriate datatype). The default implementation of * decode will perform all necessary setup of buffers, * call decodeRaw to perform the actual decoding, perform * subsampling, and copy the results into the final destination image. * Where possible, it will pass the real image buffer to * decodeRaw in order to avoid making an extra copy. * *

Slightly more ambitious decompressors may override * decodeRaw, but avoid writing pixels that will be * discarded in the subsampling phase. */ public abstract class TIFFDecompressor { private static final boolean DEBUG = false; // XXX false for release! /** * The ImageReader calling this * TIFFDecompressor. */ protected ImageReader reader; /** * The IIOMetadata object containing metadata for the * current image. */ protected IIOMetadata metadata; /** * The value of the PhotometricInterpretation tag. * Legal values are {@link * BaselineTIFFTagSet#PHOTOMETRIC_INTERPRETATION_WHITE_IS_ZERO }, * {@link * BaselineTIFFTagSet#PHOTOMETRIC_INTERPRETATION_BLACK_IS_ZERO}, * {@link BaselineTIFFTagSet#PHOTOMETRIC_INTERPRETATION_RGB}, * {@link * BaselineTIFFTagSet#PHOTOMETRIC_INTERPRETATION_PALETTE_COLOR}, * {@link * BaselineTIFFTagSet#PHOTOMETRIC_INTERPRETATION_TRANSPARENCY_MASK}, * {@link BaselineTIFFTagSet#PHOTOMETRIC_INTERPRETATION_Y_CB_CR}, * {@link BaselineTIFFTagSet#PHOTOMETRIC_INTERPRETATION_CIELAB}, * {@link BaselineTIFFTagSet#PHOTOMETRIC_INTERPRETATION_ICCLAB}, * or other value defined by a TIFF extension. */ protected int photometricInterpretation; /** * The value of the Compression tag. Legal values are * {@link BaselineTIFFTagSet#COMPRESSION_NONE}, {@link * BaselineTIFFTagSet#COMPRESSION_CCITT_RLE}, {@link * BaselineTIFFTagSet#COMPRESSION_CCITT_T_4}, {@link * BaselineTIFFTagSet#COMPRESSION_CCITT_T_6}, {@link * BaselineTIFFTagSet#COMPRESSION_LZW}, {@link * BaselineTIFFTagSet#COMPRESSION_OLD_JPEG}, {@link * BaselineTIFFTagSet#COMPRESSION_JPEG}, {@link * BaselineTIFFTagSet#COMPRESSION_ZLIB}, {@link * BaselineTIFFTagSet#COMPRESSION_PACKBITS}, {@link * BaselineTIFFTagSet#COMPRESSION_DEFLATE}, or other value * defined by a TIFF extension. */ protected int compression; /** * true if the image is encoded using separate planes. */ protected boolean planar; /** * The value of the SamplesPerPixel tag. */ protected int samplesPerPixel; /** * The value of the BitsPerSample tag. * */ protected int[] bitsPerSample; /** * The value of the SampleFormat tag. Legal values * are {@link BaselineTIFFTagSet#SAMPLE_FORMAT_UNSIGNED_INTEGER}, * {@link BaselineTIFFTagSet#SAMPLE_FORMAT_SIGNED_INTEGER}, {@link * BaselineTIFFTagSet#SAMPLE_FORMAT_FLOATING_POINT}, {@link * BaselineTIFFTagSet#SAMPLE_FORMAT_UNDEFINED}, or other value * defined by a TIFF extension. */ protected int[] sampleFormat = new int[] {BaselineTIFFTagSet.SAMPLE_FORMAT_UNSIGNED_INTEGER}; /** * The value of the ExtraSamples tag. Legal values * are {@link BaselineTIFFTagSet#EXTRA_SAMPLES_UNSPECIFIED}, * {@link BaselineTIFFTagSet#EXTRA_SAMPLES_ASSOCIATED_ALPHA}, * {@link BaselineTIFFTagSet#EXTRA_SAMPLES_UNASSOCIATED_ALPHA}, * or other value defined by a TIFF extension. */ protected int[] extraSamples; /** * The value of the ColorMap tag. * */ protected char[] colorMap; // Region of input stream containing the data /** * The ImageInputStream containing the TIFF source * data. */ protected ImageInputStream stream; /** * The offset in the source ImageInputStream of the * start of the data to be decompressed. */ protected long offset; /** * The number of bytes of data from the source * ImageInputStream to be decompressed. */ protected int byteCount; // Region of the file image represented in the stream // This is unaffected by subsampling /** * The X coordinate of the upper-left pixel of the source region * being decoded from the source stream. This value is not affected * by source subsampling. */ protected int srcMinX; /** * The Y coordinate of the upper-left pixel of the source region * being decoded from the source stream. This value is not affected * by source subsampling. */ protected int srcMinY; /** * The width of the source region being decoded from the source * stream. This value is not affected by source subsampling. */ protected int srcWidth; /** * The height of the source region being decoded from the source * stream. This value is not affected by source subsampling. */ protected int srcHeight; // Subsampling to be performed /** * The source X offset used, along with dstXOffset * and subsampleX, to map between horizontal source * and destination pixel coordinates. */ protected int sourceXOffset; /** * The horizontal destination offset used, along with * sourceXOffset and subsampleX, to map * between horizontal source and destination pixel coordinates. * See the comment for {@link #sourceXOffset * sourceXOffset} for the mapping equations. */ protected int dstXOffset; /** * The source Y offset used, along with dstYOffset * and subsampleY, to map between vertical source and * destination pixel coordinates. */ protected int sourceYOffset; /** * The vertical destination offset used, along with * sourceYOffset and subsampleY, to map * between horizontal source and destination pixel coordinates. * See the comment for {@link #sourceYOffset * sourceYOffset} for the mapping equations. */ protected int dstYOffset; /** * The horizontal subsampling factor. A factor of 1 means that * every column is copied to the destination; a factor of 2 means * that every second column is copied, etc. */ protected int subsampleX; /** * The vertical subsampling factor. A factor of 1 means that * every row is copied to the destination; a factor of 2 means * that every second row is copied, etc. */ protected int subsampleY; // Band subsetting/rearrangement /** * The sequence of source bands that are to be copied into the * destination. */ protected int[] sourceBands; /** * The sequence of destination bands to receive the source data. */ protected int[] destinationBands; // Destination for decodeRaw /** * A BufferedImage for the decodeRaw * method to write into. */ protected BufferedImage rawImage; // Destination /** * The final destination image. */ protected BufferedImage image; /** * The X coordinate of the upper left pixel to be written in the * destination image. */ protected int dstMinX; /** * The Y coordinate of the upper left pixel to be written in the * destination image. */ protected int dstMinY; /** * The width of the region of the destination image to be written. */ protected int dstWidth; /** * The height of the region of the destination image to be written. */ protected int dstHeight; // Region of source contributing to the destination /** * The X coordinate of the upper-left source pixel that will * actually be copied into the destination image, taking into * account all subsampling, offsetting, and clipping. That is, * the pixel at (activeSrcMinX, * activeSrcMinY) is to be copied into the * destination pixel at (dstMinX, * dstMinY). * *

The pixels in the source region to be copied are * those with X coordinates of the form activeSrcMinX + * k*subsampleX, where k is an integer such * that 0 <= k < dstWidth. */ protected int activeSrcMinX; /** * The Y coordinate of the upper-left source pixel that will * actually be copied into the destination image, taking into account * all subsampling, offsetting, and clipping. * *

The pixels in the source region to be copied are * those with Y coordinates of the form activeSrcMinY + * k*subsampleY, where k is an integer such * that 0 <= k < dstHeight. */ protected int activeSrcMinY; /** * The width of the source region that will actually be copied * into the destination image, taking into account all * susbampling, offsetting, and clipping. * *

The active source width will always be equal to * (dstWidth - 1)*subsampleX + 1. */ protected int activeSrcWidth; /** * The height of the source region that will actually be copied * into the destination image, taking into account all * susbampling, offsetting, and clipping. * *

The active source height will always be equal to * (dstHeight - 1)*subsampleY + 1. */ protected int activeSrcHeight; /** * A TIFFColorConverter object describing the color space of * the encoded pixel data, or null. */ protected TIFFColorConverter colorConverter; boolean isBilevel; boolean isContiguous; boolean isImageSimple; boolean adjustBitDepths; int[][] bitDepthScale; // source pixel at (sx, sy) should map to dst pixel (dx, dy), where: // // dx = (sx - sourceXOffset)/subsampleX + dstXOffset; // dy = (sy - sourceYOffset)/subsampleY + dstYOffset; // // Note that this mapping is many-to-one. Source pixels such that // (sx - sourceXOffset) % subsampleX != 0 should not be copied // (and similarly for y). // // The backwards mapping from dest to source is one-to-one: // // sx = (dx - dstXOffset)*subsampleX + sourceXOffset; // sy = (dy - dstYOffset)*subsampleY + sourceYOffset; // // The reader will always hand us the full source region as it // exists in the file. It will take care of clipping the dest region // to exactly those dest pixels that are present in the source region. /** * Create a PixelInterleavedSampleModel for use in creating * an ImageTypeSpecifier. Its dimensions will be 1x1 and * it will have ascending band offsets as {0, 1, 2, ..., numBands}. * * @param dataType The data type (DataBuffer.TYPE_*). * @param numBands The number of bands. * @return A PixelInterleavedSampleModel. */ // XXX Maybe don't need to have this as a separate method? static SampleModel createInterleavedSM(int dataType, int numBands) { int[] bandOffsets = new int[numBands]; for(int i = 0; i < numBands; i++) { bandOffsets[i] = i; } return new PixelInterleavedSampleModel(dataType, 1, // width 1, // height numBands, // pixelStride, numBands, // scanlineStride bandOffsets); } /** * Create a ComponentColorModel for use in creating * an ImageTypeSpecifier. */ // This code was copied from javax.imageio.ImageTypeSpecifier and // modified to support floating point data. static ColorModel createComponentCM(ColorSpace colorSpace, int numBands, int dataType, boolean hasAlpha, boolean isAlphaPremultiplied) { int transparency = hasAlpha ? Transparency.TRANSLUCENT : Transparency.OPAQUE; ColorModel colorModel; if(dataType == DataBuffer.TYPE_FLOAT || dataType == DataBuffer.TYPE_DOUBLE) { colorModel = new ComponentColorModel(colorSpace, hasAlpha, isAlphaPremultiplied, transparency, dataType); } else { int[] numBits = new int[numBands]; int bits; if (dataType == DataBuffer.TYPE_BYTE) { bits = 8; } else if (dataType == DataBuffer.TYPE_SHORT || dataType == DataBuffer.TYPE_USHORT) { bits = 16; } else if (dataType == DataBuffer.TYPE_INT) { bits = 32; } else { throw new IllegalArgumentException("dataType = " + dataType); } for (int i = 0; i < numBands; i++) { numBits[i] = bits; } colorModel = new ComponentColorModel(colorSpace, numBits, hasAlpha, isAlphaPremultiplied, transparency, dataType); } return colorModel; } private static int createMask(int[] bitsPerSample, int band) { int mask = (1 << bitsPerSample[band]) - 1; for (int i = band + 1; i < bitsPerSample.length; i++) { mask <<= bitsPerSample[i]; } return mask; } private static int getDataTypeFromNumBits(int numBits, boolean isSigned) { int dataType; if (numBits <= 8) { dataType = DataBuffer.TYPE_BYTE; } else if (numBits <= 16) { dataType = isSigned ? DataBuffer.TYPE_SHORT : DataBuffer.TYPE_USHORT; } else { dataType = DataBuffer.TYPE_INT; } return dataType; } private static boolean areIntArraysEqual(int[] a, int[] b) { if(a == null || b == null) { if(a == null && b == null) { return true; } else { // one is null and one is not return false; } } if(a.length != b.length) { return false; } int length = a.length; for(int i = 0; i < length; i++) { if(a[i] != b[i]) { return false; } } return true; } /** * Return the number of bits occupied by dataType * which must be one of the DataBuffer TYPEs. */ private static int getDataTypeSize(int dataType) throws IIOException { int dataTypeSize = 0; switch(dataType) { case DataBuffer.TYPE_BYTE: dataTypeSize = 8; break; case DataBuffer.TYPE_SHORT: case DataBuffer.TYPE_USHORT: dataTypeSize = 16; break; case DataBuffer.TYPE_INT: case DataBuffer.TYPE_FLOAT: dataTypeSize = 32; break; case DataBuffer.TYPE_DOUBLE: dataTypeSize = 64; break; default: throw new IIOException("Unknown data type "+dataType); } return dataTypeSize; } /** * Returns the number of bits per pixel. */ private static int getBitsPerPixel(SampleModel sm) { int bitsPerPixel = 0; int[] sampleSize = sm.getSampleSize(); int numBands = sampleSize.length; for(int i = 0; i < numBands; i++) { bitsPerPixel += sampleSize[i]; } return bitsPerPixel; } /** * Returns whether all samples have the same number of bits. */ private static boolean areSampleSizesEqual(SampleModel sm) { boolean allSameSize = true; int[] sampleSize = sm.getSampleSize(); int sampleSize0 = sampleSize[0]; int numBands = sampleSize.length; for(int i = 1; i < numBands; i++) { if(sampleSize[i] != sampleSize0) { allSameSize = false; break; } } return allSameSize; } /** * Determines whether the DataBuffer is filled without * any interspersed padding bits. */ private static boolean isDataBufferBitContiguous(SampleModel sm) throws IIOException { int dataTypeSize = getDataTypeSize(sm.getDataType()); if(sm instanceof ComponentSampleModel) { int numBands = sm.getNumBands(); for(int i = 0; i < numBands; i++) { if(sm.getSampleSize(i) != dataTypeSize) { // Sample does not fill data element. return false; } } } else if(sm instanceof MultiPixelPackedSampleModel) { MultiPixelPackedSampleModel mppsm = (MultiPixelPackedSampleModel)sm; if(dataTypeSize % mppsm.getPixelBitStride() != 0) { // Pixels do not fill the data element. return false; } } else if(sm instanceof SinglePixelPackedSampleModel) { SinglePixelPackedSampleModel sppsm = (SinglePixelPackedSampleModel)sm; int numBands = sm.getNumBands(); int numBits = 0; for(int i = 0; i < numBands; i++) { numBits += sm.getSampleSize(i); } if(numBits != dataTypeSize) { // Pixel does not fill the data element. return false; } } else { // Unknown SampleModel class. return false; } return true; } /** * Reformats data read as bytes into a short or int buffer. */ private static void reformatData(byte[] buf, int bytesPerRow, int numRows, short[] shortData, int[] intData, int outOffset, int outStride) throws IIOException { if(shortData != null) { if(DEBUG) { System.out.println("Reformatting data to short"); } int inOffset = 0; int shortsPerRow = bytesPerRow/2; int numExtraBytes = bytesPerRow % 2; for(int j = 0; j < numRows; j++) { int k = outOffset; for(int i = 0; i < shortsPerRow; i++) { shortData[k++] = (short)(((buf[inOffset++]&0xff) << 8) | (buf[inOffset++]&0xff)); } if(numExtraBytes != 0) { shortData[k++] = (short)((buf[inOffset++]&0xff) << 8); } outOffset += outStride; } } else if(intData != null) { if(DEBUG) { System.out.println("Reformatting data to int"); } int inOffset = 0; int intsPerRow = bytesPerRow/4; int numExtraBytes = bytesPerRow % 4; for(int j = 0; j < numRows; j++) { int k = outOffset; for(int i = 0; i < intsPerRow; i++) { intData[k++] = ((buf[inOffset++]&0xff) << 24) | ((buf[inOffset++]&0xff) << 16) | ((buf[inOffset++]&0xff) << 8) | (buf[inOffset++]&0xff); } if(numExtraBytes != 0) { int shift = 24; int ival = 0; for(int b = 0; b < numExtraBytes; b++) { ival |= (buf[inOffset++]&0xff) << shift; shift -= 8; } intData[k++] = ival; } outOffset += outStride; } } else { throw new IIOException("shortData == null && intData == null!"); } } /** * Reformats bit-discontiguous data into the DataBuffer * of the supplied WritableRaster. */ private static void reformatDiscontiguousData(byte[] buf, int stride, int w, int h, WritableRaster raster) throws IOException { if(DEBUG) { System.out.println("Reformatting discontiguous data"); } // Get SampleModel info. SampleModel sm = raster.getSampleModel(); int numBands = sm.getNumBands(); int[] sampleSize = sm.getSampleSize(); // Initialize input stream. ByteArrayInputStream is = new ByteArrayInputStream(buf); ImageInputStream iis = new MemoryCacheImageInputStream(is); // Reformat. long iisPosition = 0L; int y = raster.getMinY(); for(int j = 0; j < h; j++, y++) { iis.seek(iisPosition); int x = raster.getMinX(); for(int i = 0; i < w; i++, x++) { for(int b = 0; b < numBands; b++) { long bits = iis.readBits(sampleSize[b]); raster.setSample(x, y, b, (int)bits); } } iisPosition += stride; } } /** * A utility method that returns an * ImageTypeSpecifier suitable for decoding an image * with the given parameters. * * @param photometricInterpretation the value of the * PhotometricInterpretation field. * @param compression the value of the Compression field. * @param samplesPerPixel the value of the * SamplesPerPixel field. * @param bitsPerSample the value of the BitsPerSample field. * @param sampleFormat the value of the SampleFormat field. * @param extraSamples the value of the ExtraSamples field. * @param colorMap the value of the ColorMap field. * * @return a suitable ImageTypeSpecifier, or * null if it is not possible to create one. */ public static ImageTypeSpecifier getRawImageTypeSpecifier(int photometricInterpretation, int compression, int samplesPerPixel, int[] bitsPerSample, int[] sampleFormat, int[] extraSamples, char[] colorMap) { // XXX BEGIN /* XXX System.out.println("samplesPerPixel: "+samplesPerPixel); System.out.print("bitsPerSample:"); for(int i = 0; i < bitsPerSample.length; i++) { System.out.print(" "+bitsPerSample[i]); } System.out.println(""); System.out.print("sampleFormat:"); for(int i = 0; i < sampleFormat.length; i++) { System.out.print(" "+sampleFormat[i]); } System.out.println(""); if(extraSamples != null) { System.out.print("extraSamples:"); for(int i = 0; i < extraSamples.length; i++) { System.out.print(" "+extraSamples[i]); } System.out.println(""); } */ // XXX END // // Types to support: // // 1, 2, 4, 8, or 16 bit grayscale or indexed // 8,8-bit gray+alpha // 16,16-bit gray+alpha // 8,8,8-bit RGB // 8,8,8,8-bit CMYK // 8,8,8,8-bit RGB+alpha // 16,16,16-bit RGB // 16,16,16,16-bit RGB+alpha // 1,1,1,1 or 2,2,2,2 or 4,4,4,4 CMYK // R+G+B = 8-bit RGB // R+G+B+A = 8-bit RGB // R+G+B = 16-bit RGB // R+G+B+A = 16-bit RGB // 8X-bits/sample, arbitrary numBands. // Arbitrary non-indexed, non-float layouts (discontiguous). // // Band-sequential if(DEBUG) { System.out.println("\n ---- samplesPerPixel = "+samplesPerPixel+ "\n ---- bitsPerSample[0] = "+bitsPerSample[0]+ "\n ---- sampleFormat[0] = "+sampleFormat[0]); } // 1, 2, 4, 8, or 16 bit grayscale or indexed images if (samplesPerPixel == 1 && (bitsPerSample[0] == 1 || bitsPerSample[0] == 2 || bitsPerSample[0] == 4 || bitsPerSample[0] == 8 || bitsPerSample[0] == 16)) { // 2 and 16 bits images are not in the baseline // specification, but we will allow them anyway // since they fit well into Java2D // // this raises the issue of how to write such images... if (colorMap == null) { // Grayscale boolean isSigned = (sampleFormat[0] == BaselineTIFFTagSet.SAMPLE_FORMAT_SIGNED_INTEGER); int dataType; if (bitsPerSample[0] <= 8) { dataType = DataBuffer.TYPE_BYTE; } else { dataType = sampleFormat[0] == BaselineTIFFTagSet.SAMPLE_FORMAT_SIGNED_INTEGER ? DataBuffer.TYPE_SHORT : DataBuffer.TYPE_USHORT; } return ImageTypeSpecifier.createGrayscale(bitsPerSample[0], dataType, isSigned); } else { // Indexed int mapSize = 1 << bitsPerSample[0]; byte[] redLut = new byte[mapSize]; byte[] greenLut = new byte[mapSize]; byte[] blueLut = new byte[mapSize]; byte[] alphaLut = null; int idx = 0; for (int i = 0; i < mapSize; i++) { redLut[i] = (byte)((colorMap[i]*255)/65535); greenLut[i] = (byte)((colorMap[mapSize + i]*255)/65535); blueLut[i] = (byte)((colorMap[2*mapSize + i]*255)/65535); } int dataType = bitsPerSample[0] == 8 ? DataBuffer.TYPE_BYTE : DataBuffer.TYPE_USHORT; return ImageTypeSpecifier.createIndexed(redLut, greenLut, blueLut, alphaLut, bitsPerSample[0], dataType); } } // 8-bit gray-alpha if (samplesPerPixel == 2 && bitsPerSample[0] == 8 && bitsPerSample[1] == 8) { int dataType = DataBuffer.TYPE_BYTE; boolean alphaPremultiplied = false; if (extraSamples != null && extraSamples[0] == BaselineTIFFTagSet.EXTRA_SAMPLES_ASSOCIATED_ALPHA) { alphaPremultiplied = true; } //System.out.println("alphaPremultiplied = "+alphaPremultiplied);//XXX return ImageTypeSpecifier.createGrayscale(8, dataType, false, alphaPremultiplied); } // 16-bit gray-alpha if (samplesPerPixel == 2 && bitsPerSample[0] == 16 && bitsPerSample[1] == 16) { int dataType = sampleFormat[0] == BaselineTIFFTagSet.SAMPLE_FORMAT_SIGNED_INTEGER ? DataBuffer.TYPE_SHORT : DataBuffer.TYPE_USHORT; boolean alphaPremultiplied = false; if (extraSamples != null && extraSamples[0] == BaselineTIFFTagSet.EXTRA_SAMPLES_ASSOCIATED_ALPHA) { alphaPremultiplied = true; } //System.out.println("alphaPremultiplied = "+alphaPremultiplied);//XXX boolean isSigned = dataType == DataBuffer.TYPE_SHORT; return ImageTypeSpecifier.createGrayscale(16, dataType, isSigned, alphaPremultiplied); } ColorSpace rgb = ColorSpace.getInstance(ColorSpace.CS_sRGB); // 8-bit RGB if (samplesPerPixel == 3 && bitsPerSample[0] == 8 && bitsPerSample[1] == 8 && bitsPerSample[2] == 8) { int[] bandOffsets = new int[3]; bandOffsets[0] = 0; bandOffsets[1] = 1; bandOffsets[2] = 2; int dataType = DataBuffer.TYPE_BYTE; ColorSpace theColorSpace; if((photometricInterpretation == BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_Y_CB_CR && compression != BaselineTIFFTagSet.COMPRESSION_JPEG && compression != BaselineTIFFTagSet.COMPRESSION_OLD_JPEG) || photometricInterpretation == BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_CIELAB) { theColorSpace = ColorSpace.getInstance(ColorSpace.CS_LINEAR_RGB); } else { theColorSpace = rgb; } return ImageTypeSpecifier.createInterleaved(theColorSpace, bandOffsets, dataType, false, false); } // 8-bit RGBA if (samplesPerPixel == 4 && bitsPerSample[0] == 8 && bitsPerSample[1] == 8 && bitsPerSample[2] == 8 && bitsPerSample[3] == 8) { int[] bandOffsets = new int[4]; bandOffsets[0] = 0; bandOffsets[1] = 1; bandOffsets[2] = 2; bandOffsets[3] = 3; int dataType = DataBuffer.TYPE_BYTE; ColorSpace theColorSpace; boolean hasAlpha; boolean alphaPremultiplied = false; if(photometricInterpretation == BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_CMYK) { theColorSpace = SimpleCMYKColorSpace.getInstance(); hasAlpha = false; } else { theColorSpace = rgb; hasAlpha = true; if (extraSamples != null && extraSamples[0] == BaselineTIFFTagSet.EXTRA_SAMPLES_ASSOCIATED_ALPHA) { alphaPremultiplied = true; } } return ImageTypeSpecifier.createInterleaved(theColorSpace, bandOffsets, dataType, hasAlpha, alphaPremultiplied); } // 16-bit RGB if (samplesPerPixel == 3 && bitsPerSample[0] == 16 && bitsPerSample[1] == 16 && bitsPerSample[2] == 16) { int[] bandOffsets = new int[3]; bandOffsets[0] = 0; bandOffsets[1] = 1; bandOffsets[2] = 2; int dataType = sampleFormat[0] == BaselineTIFFTagSet.SAMPLE_FORMAT_SIGNED_INTEGER ? DataBuffer.TYPE_SHORT : DataBuffer.TYPE_USHORT; return ImageTypeSpecifier.createInterleaved(rgb, bandOffsets, dataType, false, false); } // 16-bit RGBA if (samplesPerPixel == 4 && bitsPerSample[0] == 16 && bitsPerSample[1] == 16 && bitsPerSample[2] == 16 && bitsPerSample[3] == 16) { int[] bandOffsets = new int[4]; bandOffsets[0] = 0; bandOffsets[1] = 1; bandOffsets[2] = 2; bandOffsets[3] = 3; int dataType = sampleFormat[0] == BaselineTIFFTagSet.SAMPLE_FORMAT_SIGNED_INTEGER ? DataBuffer.TYPE_SHORT : DataBuffer.TYPE_USHORT; boolean alphaPremultiplied = false; if (extraSamples != null && extraSamples[0] == BaselineTIFFTagSet.EXTRA_SAMPLES_ASSOCIATED_ALPHA) { alphaPremultiplied = true; } return ImageTypeSpecifier.createInterleaved(rgb, bandOffsets, dataType, true, alphaPremultiplied); } // Support for Tiff files containing half-tone data // in more than 1 channel if((photometricInterpretation == BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_CMYK) && (bitsPerSample[0] == 1 || bitsPerSample[0] == 2 || bitsPerSample[0] == 4)) { ColorSpace cs = null; if(samplesPerPixel == 4) cs = SimpleCMYKColorSpace.getInstance(); else cs = new BogusColorSpace(samplesPerPixel); // By specifying the bits per sample the color values // will scale on display ColorModel cm = new ComponentColorModel(cs, bitsPerSample, false, false, Transparency.OPAQUE, DataBuffer.TYPE_BYTE); return new ImageTypeSpecifier(cm, cm.createCompatibleSampleModel(1, 1)); } // Compute bits per pixel. int totalBits = 0; for (int i = 0; i < bitsPerSample.length; i++) { totalBits += bitsPerSample[i]; } // Packed: 3- or 4-band, 8- or 16-bit. if ((samplesPerPixel == 3 || samplesPerPixel == 4) && (totalBits == 8 || totalBits == 16)) { int redMask = createMask(bitsPerSample, 0); int greenMask = createMask(bitsPerSample, 1); int blueMask = createMask(bitsPerSample, 2); int alphaMask = (samplesPerPixel == 4) ? createMask(bitsPerSample, 3) : 0; int transferType = totalBits == 8 ? DataBuffer.TYPE_BYTE : DataBuffer.TYPE_USHORT; boolean alphaPremultiplied = false; if (extraSamples != null && extraSamples[0] == BaselineTIFFTagSet.EXTRA_SAMPLES_ASSOCIATED_ALPHA) { alphaPremultiplied = true; } return ImageTypeSpecifier.createPacked(rgb, redMask, greenMask, blueMask, alphaMask, transferType, alphaPremultiplied); } // Generic components with 8X bits per sample. if(bitsPerSample[0] % 8 == 0) { // Check whether all bands have same bit depth. boolean allSameBitDepth = true; for(int i = 1; i < bitsPerSample.length; i++) { if(bitsPerSample[i] != bitsPerSample[i-1]) { allSameBitDepth = false; break; } } // Proceed if all bands have same bit depth. if(allSameBitDepth) { // Determine the data type. int dataType = -1; boolean isDataTypeSet = false; switch(bitsPerSample[0]) { case 8: if(sampleFormat[0] != BaselineTIFFTagSet.SAMPLE_FORMAT_FLOATING_POINT) { // Ignore whether signed or unsigned: // treat all as unsigned. dataType = DataBuffer.TYPE_BYTE; isDataTypeSet = true; } break; case 16: if(sampleFormat[0] != BaselineTIFFTagSet.SAMPLE_FORMAT_FLOATING_POINT) { if(sampleFormat[0] == BaselineTIFFTagSet.SAMPLE_FORMAT_SIGNED_INTEGER) { dataType = DataBuffer.TYPE_SHORT; } else { dataType = DataBuffer.TYPE_USHORT; } isDataTypeSet = true; } break; case 32: if(sampleFormat[0] == BaselineTIFFTagSet.SAMPLE_FORMAT_FLOATING_POINT) { dataType = DataBuffer.TYPE_FLOAT; } else { dataType = DataBuffer.TYPE_INT; } isDataTypeSet = true; break; } if(isDataTypeSet) { // Create the SampleModel. SampleModel sm = createInterleavedSM(dataType, samplesPerPixel); // Create the ColorModel. ColorModel cm; if(samplesPerPixel >= 1 && samplesPerPixel <= 4 && (dataType == DataBuffer.TYPE_INT || dataType == DataBuffer.TYPE_FLOAT)) { // Handle the 32-bit cases for 1-4 bands. ColorSpace cs = samplesPerPixel <= 2 ? ColorSpace.getInstance(ColorSpace.CS_GRAY) : rgb; boolean hasAlpha = ((samplesPerPixel % 2) == 0); boolean alphaPremultiplied = false; if(hasAlpha && extraSamples != null && extraSamples[0] == BaselineTIFFTagSet.EXTRA_SAMPLES_ASSOCIATED_ALPHA) { alphaPremultiplied = true; } cm = createComponentCM(cs, samplesPerPixel, dataType, hasAlpha, alphaPremultiplied); } else { ColorSpace cs = new BogusColorSpace(samplesPerPixel); cm = createComponentCM(cs, samplesPerPixel, dataType, false, // hasAlpha false); // alphaPremultiplied } //System.out.println(cm); // XXX return new ImageTypeSpecifier(cm, sm); } } } // Other more bizarre cases including discontiguous DataBuffers // such as for the image in bug 4918959. if(colorMap == null && sampleFormat[0] != BaselineTIFFTagSet.SAMPLE_FORMAT_FLOATING_POINT) { // Determine size of largest sample. int maxBitsPerSample = 0; for(int i = 0; i < bitsPerSample.length; i++) { if(bitsPerSample[i] > maxBitsPerSample) { maxBitsPerSample = bitsPerSample[i]; } } // Determine whether data are signed. boolean isSigned = (sampleFormat[0] == BaselineTIFFTagSet.SAMPLE_FORMAT_SIGNED_INTEGER); // Grayscale if(samplesPerPixel == 1) { int dataType = getDataTypeFromNumBits(maxBitsPerSample, isSigned); return ImageTypeSpecifier.createGrayscale(maxBitsPerSample, dataType, isSigned); } // Gray-alpha if (samplesPerPixel == 2) { boolean alphaPremultiplied = false; if (extraSamples != null && extraSamples[0] == BaselineTIFFTagSet.EXTRA_SAMPLES_ASSOCIATED_ALPHA) { alphaPremultiplied = true; } int dataType = getDataTypeFromNumBits(maxBitsPerSample, isSigned); return ImageTypeSpecifier.createGrayscale(maxBitsPerSample, dataType, false, alphaPremultiplied); } if (samplesPerPixel == 3 || samplesPerPixel == 4) { if(totalBits <= 32 && !isSigned) { // Packed RGB or RGBA int redMask = createMask(bitsPerSample, 0); int greenMask = createMask(bitsPerSample, 1); int blueMask = createMask(bitsPerSample, 2); int alphaMask = (samplesPerPixel == 4) ? createMask(bitsPerSample, 3) : 0; int transferType = getDataTypeFromNumBits(totalBits, false); boolean alphaPremultiplied = false; if (extraSamples != null && extraSamples[0] == BaselineTIFFTagSet.EXTRA_SAMPLES_ASSOCIATED_ALPHA) { alphaPremultiplied = true; } return ImageTypeSpecifier.createPacked(rgb, redMask, greenMask, blueMask, alphaMask, transferType, alphaPremultiplied); } else if(samplesPerPixel == 3) { // Interleaved RGB int[] bandOffsets = new int[] {0, 1, 2}; int dataType = getDataTypeFromNumBits(maxBitsPerSample, isSigned); return ImageTypeSpecifier.createInterleaved(rgb, bandOffsets, dataType, false, false); } else if(samplesPerPixel == 4) { // Interleaved RGBA int[] bandOffsets = new int[] {0, 1, 2, 3}; int dataType = getDataTypeFromNumBits(maxBitsPerSample, isSigned); boolean alphaPremultiplied = false; if (extraSamples != null && extraSamples[0] == BaselineTIFFTagSet.EXTRA_SAMPLES_ASSOCIATED_ALPHA) { alphaPremultiplied = true; } return ImageTypeSpecifier.createInterleaved(rgb, bandOffsets, dataType, true, alphaPremultiplied); } } else { // Arbitrary Interleaved. int dataType = getDataTypeFromNumBits(maxBitsPerSample, isSigned); SampleModel sm = createInterleavedSM(dataType, samplesPerPixel); ColorSpace cs = new BogusColorSpace(samplesPerPixel); ColorModel cm = createComponentCM(cs, samplesPerPixel, dataType, false, // hasAlpha false); // alphaPremultiplied return new ImageTypeSpecifier(cm, sm); } } if(DEBUG) { System.out.println("\nNo raw ITS available:"); System.out.println("photometricInterpretation = " + photometricInterpretation); System.out.println("compression = " + compression); System.out.println("samplesPerPixel = " + samplesPerPixel); if (bitsPerSample != null) { for (int i = 0; i < bitsPerSample.length; i++) { System.out.println("bitsPerSample[" + i + "] = " + (int)bitsPerSample[i]); } } if (sampleFormat != null) { for (int i = 0; i < sampleFormat.length; i++) { System.out.println("sampleFormat[" + i + "] = " + (int)sampleFormat[i]); } } if (extraSamples != null) { for (int i = 0; i < extraSamples.length; i++) { System.out.println("extraSamples[" + i + "] = " + (int)extraSamples[i]); } } System.out.println("colorMap = " + colorMap); if (colorMap != null) { System.out.println("colorMap.length = " + colorMap.length); } throw new RuntimeException("Unable to create an ImageTypeSpecifier"); } return null; } /** * Sets the value of the reader field. * *

If this method is called, the beginDecoding * method must be called prior to calling any of the decode * methods. * * @param reader the current ImageReader. */ public void setReader(ImageReader reader) { this.reader = reader; } /** * Sets the value of the metadata field. * *

If this method is called, the beginDecoding * method must be called prior to calling any of the decode * methods. * * @param metadata the IIOMetadata object for the * image being read. */ public void setMetadata(IIOMetadata metadata) { this.metadata = metadata; } /** * Sets the value of the photometricInterpretation * field. * *

If this method is called, the beginDecoding * method must be called prior to calling any of the decode * methods. * * @param photometricInterpretation the photometric interpretation * value. */ public void setPhotometricInterpretation(int photometricInterpretation) { this.photometricInterpretation = photometricInterpretation; } /** * Sets the value of the compression field. * *

If this method is called, the beginDecoding * method must be called prior to calling any of the decode * methods. * * @param compression the compression type. */ public void setCompression(int compression) { this.compression = compression; } /** * Sets the value of the planar field. * *

If this method is called, the beginDecoding * method must be called prior to calling any of the decode * methods. * * @param planar true if the image to be decoded is * stored in planar format. */ public void setPlanar(boolean planar) { this.planar = planar; } /** * Sets the value of the samplesPerPixel field. * *

If this method is called, the beginDecoding * method must be called prior to calling any of the decode * methods. * * @param samplesPerPixel the number of samples in each source * pixel. */ public void setSamplesPerPixel(int samplesPerPixel) { this.samplesPerPixel = samplesPerPixel; } /** * Sets the value of the bitsPerSample field. * *

If this method is called, the beginDecoding * method must be called prior to calling any of the decode * methods. * * @param bitsPerSample the number of bits for each source image * sample. */ public void setBitsPerSample(int[] bitsPerSample) { this.bitsPerSample = bitsPerSample == null ? null : (int[])bitsPerSample.clone(); } /** * Sets the value of the sampleFormat field. * *

If this method is called, the beginDecoding * method must be called prior to calling any of the decode * methods. * * @param sampleFormat the format of the source image data, * for example unsigned integer or floating-point. */ public void setSampleFormat(int[] sampleFormat) { this.sampleFormat = sampleFormat == null ? new int[] {BaselineTIFFTagSet.SAMPLE_FORMAT_UNSIGNED_INTEGER} : (int[])sampleFormat.clone(); } /** * Sets the value of the extraSamples field. * *

If this method is called, the beginDecoding * method must be called prior to calling any of the decode * methods. * * @param extraSamples the interpretation of any samples in the * source file beyond those used for basic color or grayscale * information. */ public void setExtraSamples(int[] extraSamples) { this.extraSamples = extraSamples == null ? null : (int[])extraSamples.clone(); } /** * Sets the value of the colorMap field. * *

If this method is called, the beginDecoding * method must be called prior to calling any of the decode * methods. * * @param colorMap the color map to apply to the source data, * as an array of chars. */ public void setColorMap(char[] colorMap) { this.colorMap = colorMap == null ? null : (char[])colorMap.clone(); } /** * Sets the value of the stream field. * *

If this method is called, the beginDecoding * method must be called prior to calling any of the decode * methods. * * @param stream the ImageInputStream to be read. */ public void setStream(ImageInputStream stream) { this.stream = stream; } /** * Sets the value of the offset field. * *

If this method is called, the beginDecoding * method must be called prior to calling any of the decode * methods. * * @param offset the offset of the beginning of the compressed * data. */ public void setOffset(long offset) { this.offset = offset; } /** * Sets the value of the byteCount field. * *

If this method is called, the beginDecoding * method must be called prior to calling any of the decode * methods. * * @param byteCount the number of bytes of compressed data. */ public void setByteCount(int byteCount) { this.byteCount = byteCount; } // Region of the file image represented in the stream /** * Sets the value of the srcMinX field. * *

If this method is called, the beginDecoding * method must be called prior to calling any of the decode * methods. * * @param srcMinX the minimum X coordinate of the source region * being decoded, irrespective of how it will be copied into the * destination. */ public void setSrcMinX(int srcMinX) { this.srcMinX = srcMinX; } /** * Sets the value of the srcMinY field. * *

If this method is called, the beginDecoding * method must be called prior to calling any of the decode * methods. * * @param srcMinY the minimum Y coordinate of the source region * being decoded, irrespective of how it will be copied into the * destination. */ public void setSrcMinY(int srcMinY) { this.srcMinY = srcMinY; } /** * Sets the value of the srcWidth field. * *

If this method is called, the beginDecoding * method must be called prior to calling any of the decode * methods. * * @param srcWidth the width of the source region being decoded, * irrespective of how it will be copied into the destination. */ public void setSrcWidth(int srcWidth) { this.srcWidth = srcWidth; } /** * Sets the value of the srcHeight field. * *

If this method is called, the beginDecoding * method must be called prior to calling any of the decode * methods. * * @param srcHeight the height of the source region being decoded, * irrespective of how it will be copied into the destination. */ public void setSrcHeight(int srcHeight) { this.srcHeight = srcHeight; } // First source pixel to be read /** * Sets the value of the sourceXOffset field. * *

If this method is called, the beginDecoding * method must be called prior to calling any of the decode * methods. * * @param sourceXOffset the horizontal source offset to be used when * mapping between source and destination coordinates. */ public void setSourceXOffset(int sourceXOffset) { this.sourceXOffset = sourceXOffset; } /** * Sets the value of the dstXOffset field. * *

If this method is called, the beginDecoding * method must be called prior to calling any of the decode * methods. * * @param dstXOffset the horizontal destination offset to be * used when mapping between source and destination coordinates. */ public void setDstXOffset(int dstXOffset) { this.dstXOffset = dstXOffset; } /** * Sets the value of the sourceYOffset. * *

If this method is called, the beginDecoding * method must be called prior to calling any of the decode * methods. * * @param sourceYOffset the vertical source offset to be used when * mapping between source and destination coordinates. */ public void setSourceYOffset(int sourceYOffset) { this.sourceYOffset = sourceYOffset; } /** * Sets the value of the dstYOffset field. * *

If this method is called, the beginDecoding * method must be called prior to calling any of the decode * methods. * * @param dstYOffset the vertical destination offset to be * used when mapping between source and destination coordinates. */ public void setDstYOffset(int dstYOffset) { this.dstYOffset = dstYOffset; } // Subsampling to be performed /** * Sets the value of the subsampleX field. * *

If this method is called, the beginDecoding * method must be called prior to calling any of the decode * methods. * * @param subsampleX the horizontal subsampling factor. * * @throws IllegalArgumentException if subsampleX is * less than or equal to 0. */ public void setSubsampleX(int subsampleX) { if (subsampleX <= 0) { throw new IllegalArgumentException("subsampleX <= 0!"); } this.subsampleX = subsampleX; } /** * Sets the value of the subsampleY field. * *

If this method is called, the beginDecoding * method must be called prior to calling any of the decode * methods. * * @param subsampleY the vertical subsampling factor. * * @throws IllegalArgumentException if subsampleY is * less than or equal to 0. */ public void setSubsampleY(int subsampleY) { if (subsampleY <= 0) { throw new IllegalArgumentException("subsampleY <= 0!"); } this.subsampleY = subsampleY; } // Band subsetting/rearrangement /** * Sets the value of the sourceBands field. * *

If this method is called, the beginDecoding * method must be called prior to calling any of the decode * methods. * * @param sourceBands an array of ints * specifying the source bands to be read. */ public void setSourceBands(int[] sourceBands) { this.sourceBands = sourceBands == null ? null : (int[])sourceBands.clone(); } /** * Sets the value of the destinationBands field. * *

If this method is called, the beginDecoding * method must be called prior to calling any of the decode * methods. * * @param destinationBands an array of ints * specifying the destination bands to be written. */ public void setDestinationBands(int[] destinationBands) { this.destinationBands = destinationBands == null ? null : (int[])destinationBands.clone(); } // Destination image and region /** * Sets the value of the image field. * *

If this method is called, the beginDecoding * method must be called prior to calling any of the decode * methods. * * @param image the destination BufferedImage. */ public void setImage(BufferedImage image) { this.image = image; } /** * Sets the value of the dstMinX field. * *

If this method is called, the beginDecoding * method must be called prior to calling any of the decode * methods. * * @param dstMinX the minimum X coordinate of the destination * region. */ public void setDstMinX(int dstMinX) { this.dstMinX = dstMinX; } /** * Sets the value of the dstMinY field. * *

If this method is called, the beginDecoding * method must be called prior to calling any of the decode * methods. * * @param dstMinY the minimum Y coordinate of the destination * region. */ public void setDstMinY(int dstMinY) { this.dstMinY = dstMinY; } /** * Sets the value of the dstWidth field. * *

If this method is called, the beginDecoding * method must be called prior to calling any of the decode * methods. * * @param dstWidth the width of the destination region. */ public void setDstWidth(int dstWidth) { this.dstWidth = dstWidth; } /** * Sets the value of the dstHeight field. * *

If this method is called, the beginDecoding * method must be called prior to calling any of the decode * methods. * * @param dstHeight the height of the destination region. */ public void setDstHeight(int dstHeight) { this.dstHeight = dstHeight; } // Active source region /** * Sets the value of the activeSrcMinX field. * *

If this method is called, the beginDecoding * method must be called prior to calling any of the decode * methods. * * @param activeSrcMinX the minimum X coordinate of the active * source region. */ public void setActiveSrcMinX(int activeSrcMinX) { this.activeSrcMinX = activeSrcMinX; } /** * Sets the value of the activeSrcMinY field. * *

If this method is called, the beginDecoding * method must be called prior to calling any of the decode * methods. * * @param activeSrcMinY the minimum Y coordinate of the active * source region. */ public void setActiveSrcMinY(int activeSrcMinY) { this.activeSrcMinY = activeSrcMinY; } /** * Sets the value of the activeSrcWidth field. * *

If this method is called, the beginDecoding * method must be called prior to calling any of the decode * methods. * * @param activeSrcWidth the width of the active source region. */ public void setActiveSrcWidth(int activeSrcWidth) { this.activeSrcWidth = activeSrcWidth; } /** * Sets the value of the activeSrcHeight field. * *

If this method is called, the beginDecoding * method must be called prior to calling any of the decode * methods. * * @param activeSrcHeight the height of the active source region. */ public void setActiveSrcHeight(int activeSrcHeight) { this.activeSrcHeight = activeSrcHeight; } /** * Sets the TIFFColorConverter object describing the color * space of the encoded data in the input stream. If no * TIFFColorConverter is set, no conversion will be performed. * * @param colorConverter a TIFFColorConverter object, or * null. */ public void setColorConverter(TIFFColorConverter colorConverter) { this.colorConverter = colorConverter; } /** * Returns an ImageTypeSpecifier describing an image * whose underlying data array has the same format as the raw * source pixel data. * * @return an ImageTypeSpecifier. */ public ImageTypeSpecifier getRawImageType() { ImageTypeSpecifier its = getRawImageTypeSpecifier(photometricInterpretation, compression, samplesPerPixel, bitsPerSample, sampleFormat, extraSamples, colorMap); return its; } /** * Creates a BufferedImage whose underlying data * array will be suitable for holding the raw decoded output of * the decodeRaw method. * *

The default implementation calls * getRawImageType, and calls the resulting * ImageTypeSpecifier's * createBufferedImage method. * * @return a BufferedImage whose underlying data * array has the same format as the raw source pixel data, or * null if it is not possible to create such an * image. */ public BufferedImage createRawImage() { if (planar) { // Create a single-banded image of the appropriate data type. // Get the number of bits per sample. int bps = bitsPerSample[sourceBands[0]]; // Determine the data type. int dataType; if(sampleFormat[0] == BaselineTIFFTagSet.SAMPLE_FORMAT_FLOATING_POINT) { dataType = DataBuffer.TYPE_FLOAT; } else if(bps <= 8) { dataType = DataBuffer.TYPE_BYTE; } else if(bps <= 16) { if(sampleFormat[0] == BaselineTIFFTagSet.SAMPLE_FORMAT_SIGNED_INTEGER) { dataType = DataBuffer.TYPE_SHORT; } else { dataType = DataBuffer.TYPE_USHORT; } } else { dataType = DataBuffer.TYPE_INT; } ColorSpace csGray = ColorSpace.getInstance(ColorSpace.CS_GRAY); ImageTypeSpecifier its = null; // For planar images with 1, 2 or 4 bits per sample, we need to // use a MultiPixelPackedSampleModel so that when the TIFF // decoder properly decodes the data per pixel, we know how to // extract it back out into individual pixels. This is how the // pixels are actually stored in the planar bands. if(bps == 1 || bps == 2 || bps == 4) { int bits = bps; int size = 1 << bits; byte[] r = new byte[size]; byte[] g = new byte[size]; byte[] b = new byte[size]; for(int j=0; jbyte * array b, starting at the offset given by * dstOffset. Each pixel occupies * bitsPerPixel bits, with no padding between pixels. * Scanlines are separated by scanlineStride * bytes. * * @param b a byte array to be written. * @param dstOffset the starting offset in b to be * written. * @param bitsPerPixel the number of bits for each pixel. * @param scanlineStride the number of bytes to * advance between that starting pixels of each scanline. * * @throws IOException if an error occurs reading from the source * ImageInputStream. */ public abstract void decodeRaw(byte[] b, int dstOffset, int bitsPerPixel, int scanlineStride) throws IOException; /** * Decodes the source data into the provided short * array s, starting at the offset given by * dstOffset. Each pixel occupies * bitsPerPixel bits, with no padding between pixels. * Scanlines are separated by scanlineStride * shorts * *

The default implementation calls decodeRaw(byte[] b, * ...) and copies the resulting data into s. * * @param s a short array to be written. * @param dstOffset the starting offset in s to be * written. * @param bitsPerPixel the number of bits for each pixel. * @param scanlineStride the number of shorts to * advance between that starting pixels of each scanline. * * @throws IOException if an error occurs reading from the source * ImageInputStream. */ public void decodeRaw(short[] s, int dstOffset, int bitsPerPixel, int scanlineStride) throws IOException { int bytesPerRow = (srcWidth*bitsPerPixel + 7)/8; int shortsPerRow = bytesPerRow/2; byte[] b = new byte[bytesPerRow*srcHeight]; decodeRaw(b, 0, bitsPerPixel, bytesPerRow); int bOffset = 0; if(stream.getByteOrder() == ByteOrder.BIG_ENDIAN) { for (int j = 0; j < srcHeight; j++) { for (int i = 0; i < shortsPerRow; i++) { short hiVal = b[bOffset++]; short loVal = b[bOffset++]; short sval = (short)((hiVal << 8) | (loVal & 0xff)); s[dstOffset + i] = sval; } dstOffset += scanlineStride; } } else { // ByteOrder.LITLE_ENDIAN for (int j = 0; j < srcHeight; j++) { for (int i = 0; i < shortsPerRow; i++) { short loVal = b[bOffset++]; short hiVal = b[bOffset++]; short sval = (short)((hiVal << 8) | (loVal & 0xff)); s[dstOffset + i] = sval; } dstOffset += scanlineStride; } } } /** * Decodes the source data into the provided int * array i, starting at the offset given by * dstOffset. Each pixel occupies * bitsPerPixel bits, with no padding between pixels. * Scanlines are separated by scanlineStride * ints. * *

The default implementation calls decodeRaw(byte[] b, * ...) and copies the resulting data into i. * * @param i an int array to be written. * @param dstOffset the starting offset in i to be * written. * @param bitsPerPixel the number of bits for each pixel. * @param scanlineStride the number of ints to * advance between that starting pixels of each scanline. * * @throws IOException if an error occurs reading from the source * ImageInputStream. */ public void decodeRaw(int[] i, int dstOffset, int bitsPerPixel, int scanlineStride) throws IOException { int numBands = bitsPerPixel/32; int intsPerRow = srcWidth*numBands; int bytesPerRow = intsPerRow*4; byte[] b = new byte[bytesPerRow*srcHeight]; decodeRaw(b, 0, bitsPerPixel, bytesPerRow); int bOffset = 0; if(stream.getByteOrder() == ByteOrder.BIG_ENDIAN) { for (int j = 0; j < srcHeight; j++) { for (int k = 0; k < intsPerRow; k++) { int v0 = b[bOffset++] & 0xff; int v1 = b[bOffset++] & 0xff; int v2 = b[bOffset++] & 0xff; int v3 = b[bOffset++] & 0xff; int ival = (v0 << 24) | (v1 << 16) | (v2 << 8) | v3; i[dstOffset + k] = ival; } dstOffset += scanlineStride; } } else { // ByteOrder.LITLE_ENDIAN for (int j = 0; j < srcHeight; j++) { for (int k = 0; k < intsPerRow; k++) { int v3 = b[bOffset++] & 0xff; int v2 = b[bOffset++] & 0xff; int v1 = b[bOffset++] & 0xff; int v0 = b[bOffset++] & 0xff; int ival = (v0 << 24) | (v1 << 16) | (v2 << 8) | v3; i[dstOffset + k] = ival; } dstOffset += scanlineStride; } } } /** * Decodes the source data into the provided float * array f, starting at the offset given by * dstOffset. Each pixel occupies * bitsPerPixel bits, with no padding between pixels. * Scanlines are separated by scanlineStride * floats. * *

The default implementation calls decodeRaw(byte[] b, * ...) and copies the resulting data into f. * * @param f a float array to be written. * @param dstOffset the starting offset in f to be * written. * @param bitsPerPixel the number of bits for each pixel. * @param scanlineStride the number of floats to * advance between that starting pixels of each scanline. * * @throws IOException if an error occurs reading from the source * ImageInputStream. */ public void decodeRaw(float[] f, int dstOffset, int bitsPerPixel, int scanlineStride) throws IOException { int numBands = bitsPerPixel/32; int floatsPerRow = srcWidth*numBands; int bytesPerRow = floatsPerRow*4; byte[] b = new byte[bytesPerRow*srcHeight]; decodeRaw(b, 0, bitsPerPixel, bytesPerRow); int bOffset = 0; if(stream.getByteOrder() == ByteOrder.BIG_ENDIAN) { for (int j = 0; j < srcHeight; j++) { for (int i = 0; i < floatsPerRow; i++) { int v0 = b[bOffset++] & 0xff; int v1 = b[bOffset++] & 0xff; int v2 = b[bOffset++] & 0xff; int v3 = b[bOffset++] & 0xff; int ival = (v0 << 24) | (v1 << 16) | (v2 << 8) | v3; float fval = Float.intBitsToFloat(ival); f[dstOffset + i] = fval; } dstOffset += scanlineStride; } } else { // ByteOrder.LITLE_ENDIAN for (int j = 0; j < srcHeight; j++) { for (int i = 0; i < floatsPerRow; i++) { int v3 = b[bOffset++] & 0xff; int v2 = b[bOffset++] & 0xff; int v1 = b[bOffset++] & 0xff; int v0 = b[bOffset++] & 0xff; int ival = (v0 << 24) | (v1 << 16) | (v2 << 8) | v3; float fval = Float.intBitsToFloat(ival); f[dstOffset + i] = fval; } dstOffset += scanlineStride; } } } // // Values used to prevent unneeded recalculation of bit adjustment table. // private boolean isFirstBitDepthTable = true; private boolean planarCache = false; private int[] destBitsPerSampleCache = null; private int[] sourceBandsCache = null; private int[] bitsPerSampleCache = null; private int[] destinationBandsCache = null; /** * This routine is called prior to a sequence of calls to the * decode method, in order to allow any necessary * tables or other structures to be initialized based on metadata * values. This routine is guaranteed to be called any time the * metadata values have changed. * *

The default implementation computes tables used by the * decode method to rescale components to different * bit depths. Thus, if this method is overridden, it is * important for the subclass method to call super(), * unless it overrides decode as well. */ public void beginDecoding() { // Note: This method assumes that sourceBands, destinationBands, // and bitsPerSample are all non-null which is true as they are // set up that way in TIFFImageReader. Also the lengths and content // of sourceBands and destinationBands are checked in TIFFImageReader // before the present method is invoked. // Determine if all of the relevant output bands have the // same bit depth as the source data this.adjustBitDepths = false; int numBands = destinationBands.length; int[] destBitsPerSample = null; if(planar) { int totalNumBands = bitsPerSample.length; destBitsPerSample = new int[totalNumBands]; int dbps = image.getSampleModel().getSampleSize(0); for(int b = 0; b < totalNumBands; b++) { destBitsPerSample[b] = dbps; } } else { destBitsPerSample = image.getSampleModel().getSampleSize(); } // Make sure that the image is not CMYK (separated) or does not have // bits per sample of 1, 2, or 4 before trying adjust. if(photometricInterpretation != BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_CMYK || bitsPerSample[0] != 1 && bitsPerSample[0] != 2 && bitsPerSample[0] != 4) { for (int b = 0; b < numBands; b++) { if (destBitsPerSample[destinationBands[b]] != bitsPerSample[sourceBands[b]]) { adjustBitDepths = true; break; } } } // If the bit depths differ, create a lookup table // per band to perform the conversion if(adjustBitDepths) { // Compute the table only if this is the first time one is // being computed or if any of the variables on which the // table is based have changed. if(this.isFirstBitDepthTable || planar != planarCache || !areIntArraysEqual(destBitsPerSample, destBitsPerSampleCache) || !areIntArraysEqual(sourceBands, sourceBandsCache) || !areIntArraysEqual(bitsPerSample, bitsPerSampleCache) || !areIntArraysEqual(destinationBands, destinationBandsCache)) { this.isFirstBitDepthTable = false; // Cache some variables. this.planarCache = planar; this.destBitsPerSampleCache = (int[])destBitsPerSample.clone(); // never null ... this.sourceBandsCache = sourceBands == null ? null : (int[])sourceBands.clone(); this.bitsPerSampleCache = bitsPerSample == null ? null : (int[])bitsPerSample.clone(); this.destinationBandsCache = destinationBands == null ? null : (int[])destinationBands.clone(); // Allocate and fill the table. bitDepthScale = new int[numBands][]; for (int b = 0; b < numBands; b++) { int maxInSample = (1 << bitsPerSample[sourceBands[b]]) - 1; int halfMaxInSample = maxInSample/2; int maxOutSample = (1 << destBitsPerSample[destinationBands[b]]) - 1; bitDepthScale[b] = new int[maxInSample + 1]; for (int s = 0; s <= maxInSample; s++) { bitDepthScale[b][s] = (s*maxOutSample + halfMaxInSample)/ maxInSample; } } } } else { // !adjustBitDepths // Clear any prior table. this.bitDepthScale = null; } // Determine whether source and destination band lists are ramps. // Note that these conditions will be true for planar images if // and only if samplesPerPixel == 1, sourceBands[0] == 0, and // destinationBands[0] == 0. For the purposes of this method, the // only difference between such a planar image and a chunky image // is the setting of the PlanarConfiguration field. boolean sourceBandsNormal = false; boolean destinationBandsNormal = false; if (numBands == samplesPerPixel) { sourceBandsNormal = true; destinationBandsNormal = true; for (int i = 0; i < numBands; i++) { if (sourceBands[i] != i) { sourceBandsNormal = false; } if (destinationBands[i] != i) { destinationBandsNormal = false; } } } // Determine whether the image is bilevel and/or contiguous. // Note that a planar image could be bilevel but it will not // be contiguous unless it has a single component band stored // in a single bank. this.isBilevel = ImageUtil.isBinary(this.image.getRaster().getSampleModel()); this.isContiguous = this.isBilevel ? true : ImageUtil.imageIsContiguous(this.image); // Analyze destination image to see if we can copy into it // directly this.isImageSimple = (colorConverter == null) && (subsampleX == 1) && (subsampleY == 1) && (srcWidth == dstWidth) && (srcHeight == dstHeight) && ((dstMinX + dstWidth) <= image.getWidth()) && ((dstMinY + dstHeight) <= image.getHeight()) && sourceBandsNormal && destinationBandsNormal && !adjustBitDepths; } /** * Decodes the input bit stream (located in the * ImageInputStream stream, at offset * offset, and continuing for byteCount * bytes) into the output BufferedImage * image. * *

The default implementation analyzes the destination image * to determine if it is suitable as the destination for the * decodeRaw method. If not, a suitable image is * created. Next, decodeRaw is called to perform the * actual decoding, and the results are copied into the * destination image if necessary. Subsampling and offsetting are * performed automatically. * *

The precise responsibilities of this routine are as * follows. The input bit stream is defined by the instance * variables stream, offset, and * byteCount. These bits contain the data for the * region of the source image defined by srcMinX, * srcMinY, srcWidth, and * srcHeight. * *

The source data is required to be subsampling, starting at * the sourceXOffsetth column and including * every subsampleXth pixel thereafter (and similarly * for sourceYOffset and * subsampleY). * *

Pixels are copied into the destination with an addition shift of * (dstXOffset, dstYOffset). The complete * set of formulas relating the source and destination coordinate spaces * are: * *

     * dx = (sx - sourceXOffset)/subsampleX + dstXOffset;
     * dy = (sy - sourceYOffset)/subsampleY + dstYOffset; 
     * 
* * Only source pixels such that (sx - sourceXOffset) % * subsampleX == 0 and (sy - sourceYOffset) % * subsampleY == 0 are copied. * *

The inverse mapping, from destination to source coordinates, * is one-to-one: * *

     * sx = (dx - dstXOffset)*subsampleX + sourceXOffset;
     * sy = (dy - dstYOffset)*subsampleY + sourceYOffset;
     * 
* *

The region of the destination image to be updated is given * by the instance variables dstMinX, * dstMinY, dstWidth, and * dstHeight. * *

It is possible that not all of the source data being read * will contribute to the destination image. For example, the * destination offsets could be set such that some of the source * pixels land outside of the bounds of the image. As a * convenience, the bounds of the active source region (that is, * the region of the strip or tile being read that actually * contributes to the destination image, taking clipping into * account) are available as activeSrcMinX, * activeSrcMinY, activeSrcWidth and * activeSrcHeight. Thus, the source pixel at * (activeSrcMinX, activeSrcMinY) will * map to the destination pixel (dstMinX, * dstMinY). * *

The sequence of source bands given by * sourceBands are to be copied into the sequence of * bands in the destination given by * destinationBands. * *

Some standard tag information is provided the instance * variables photometricInterpretation, * compression, samplesPerPixel, * bitsPerSample, sampleFormat, * extraSamples, and colorMap. * *

In practice, unless there is a significant performance * advantage to be gained by overriding this routine, most users * will prefer to use the default implementation of this routine, * and instead override the decodeRaw and/or * getRawImageType methods. * * @exception IOException if an error occurs in * decodeRaw. */ public void decode() throws IOException { byte[] byteData = null; short[] shortData = null; int[] intData = null; float[] floatData = null; int dstOffset = 0; int pixelBitStride = 1; int scanlineStride = 0; // Analyze raw image this.rawImage = null; if(isImageSimple) { if(isBilevel) { rawImage = this.image; } else if (isContiguous) { rawImage = image.getSubimage(dstMinX, dstMinY, dstWidth, dstHeight); } } boolean isDirectCopy = rawImage != null; if(rawImage == null) { rawImage = createRawImage(); if (rawImage == null) { throw new IIOException("Couldn't create image buffer!"); } } WritableRaster ras = rawImage.getRaster(); if(isBilevel) { Rectangle rect = isImageSimple ? new Rectangle(dstMinX, dstMinY, dstWidth, dstHeight) : ras.getBounds(); byteData = ImageUtil.getPackedBinaryData(ras, rect); dstOffset = 0; pixelBitStride = 1; scanlineStride = (rect.width + 7)/8; } else { SampleModel sm = ras.getSampleModel(); DataBuffer db = ras.getDataBuffer(); boolean isSupportedType = false; if (sm instanceof ComponentSampleModel) { ComponentSampleModel csm = (ComponentSampleModel)sm; dstOffset = csm.getOffset(-ras.getSampleModelTranslateX(), -ras.getSampleModelTranslateY()); scanlineStride = csm.getScanlineStride(); if(db instanceof DataBufferByte) { DataBufferByte dbb = (DataBufferByte)db; byteData = dbb.getData(); pixelBitStride = csm.getPixelStride()*8; isSupportedType = true; } else if(db instanceof DataBufferUShort) { DataBufferUShort dbus = (DataBufferUShort)db; shortData = dbus.getData(); pixelBitStride = csm.getPixelStride()*16; isSupportedType = true; } else if(db instanceof DataBufferShort) { DataBufferShort dbs = (DataBufferShort)db; shortData = dbs.getData(); pixelBitStride = csm.getPixelStride()*16; isSupportedType = true; } else if(db instanceof DataBufferInt) { DataBufferInt dbi = (DataBufferInt)db; intData = dbi.getData(); pixelBitStride = csm.getPixelStride()*32; isSupportedType = true; } else if(db instanceof DataBufferFloat) { DataBufferFloat dbf = (DataBufferFloat)db; floatData = dbf.getData(); pixelBitStride = csm.getPixelStride()*32; isSupportedType = true; } } else if (sm instanceof MultiPixelPackedSampleModel) { MultiPixelPackedSampleModel mppsm = (MultiPixelPackedSampleModel)sm; dstOffset = mppsm.getOffset(-ras.getSampleModelTranslateX(), -ras.getSampleModelTranslateY()); pixelBitStride = mppsm.getPixelBitStride(); scanlineStride = mppsm.getScanlineStride(); if(db instanceof DataBufferByte) { DataBufferByte dbb = (DataBufferByte)db; byteData = dbb.getData(); isSupportedType = true; } else if(db instanceof DataBufferUShort) { DataBufferUShort dbus = (DataBufferUShort)db; shortData = dbus.getData(); isSupportedType = true; } else if(db instanceof DataBufferInt) { DataBufferInt dbi = (DataBufferInt)db; intData = dbi.getData(); isSupportedType = true; } } else if (sm instanceof SinglePixelPackedSampleModel) { SinglePixelPackedSampleModel sppsm = (SinglePixelPackedSampleModel)sm; dstOffset = sppsm.getOffset(-ras.getSampleModelTranslateX(), -ras.getSampleModelTranslateY()); scanlineStride = sppsm.getScanlineStride(); if(db instanceof DataBufferByte) { DataBufferByte dbb = (DataBufferByte)db; byteData = dbb.getData(); pixelBitStride = 8; isSupportedType = true; } else if(db instanceof DataBufferUShort) { DataBufferUShort dbus = (DataBufferUShort)db; shortData = dbus.getData(); pixelBitStride = 16; isSupportedType = true; } else if(db instanceof DataBufferInt) { DataBufferInt dbi = (DataBufferInt)db; intData = dbi.getData(); pixelBitStride = 32; isSupportedType = true; } } if(!isSupportedType) { throw new IIOException ("Unsupported raw image type: SampleModel = "+sm+ "; DataBuffer = "+db); } } if(isBilevel) { // Bilevel data are always in a contiguous byte buffer. decodeRaw(byteData, dstOffset, pixelBitStride, scanlineStride); } else { SampleModel sm = ras.getSampleModel(); // Branch based on whether data are bit-contiguous, i.e., // data are packaed as tightly as possible leaving no unused // bits except at the end of a row. if(isDataBufferBitContiguous(sm)) { // Use byte or float data directly. if (byteData != null) { if(DEBUG) { System.out.println("Decoding bytes directly"); } decodeRaw(byteData, dstOffset, pixelBitStride, scanlineStride); } else if (floatData != null) { if(DEBUG) { System.out.println("Decoding floats directly"); } decodeRaw(floatData, dstOffset, pixelBitStride, scanlineStride); } else { if (shortData != null) { if(areSampleSizesEqual(sm) && sm.getSampleSize(0) == 16) { if(DEBUG) { System.out.println("Decoding shorts directly"); } // Decode directly into short data. decodeRaw(shortData, dstOffset, pixelBitStride, scanlineStride); } else { if(DEBUG) { System.out.println("Decoding bytes->shorts"); } // Decode into bytes and reformat into shorts. int bpp = getBitsPerPixel(sm); int bytesPerRow = (bpp*srcWidth + 7)/8; byte[] buf = new byte[bytesPerRow*srcHeight]; decodeRaw(buf, 0, bpp, bytesPerRow); reformatData(buf, bytesPerRow, srcHeight, shortData, null, dstOffset, scanlineStride); } } else if (intData != null) { if(areSampleSizesEqual(sm) && sm.getSampleSize(0) == 32) { if(DEBUG) { System.out.println("Decoding ints directly"); } // Decode directly into int data. decodeRaw(intData, dstOffset, pixelBitStride, scanlineStride); } else { if(DEBUG) { System.out.println("Decoding bytes->ints"); } // Decode into bytes and reformat into ints. int bpp = getBitsPerPixel(sm); int bytesPerRow = (bpp*srcWidth + 7)/8; byte[] buf = new byte[bytesPerRow*srcHeight]; decodeRaw(buf, 0, bpp, bytesPerRow); reformatData(buf, bytesPerRow, srcHeight, null, intData, dstOffset, scanlineStride); } } } } else { if(DEBUG) { System.out.println("Decoding discontiguous data"); } // Read discontiguous data into bytes and set the samples // into the Raster. int bpp = getBitsPerPixel(sm); int bytesPerRow = (bpp*srcWidth + 7)/8; byte[] buf = new byte[bytesPerRow*srcHeight]; decodeRaw(buf, 0, bpp, bytesPerRow); reformatDiscontiguousData(buf, bytesPerRow, srcWidth, srcHeight, ras); } } // System.out.println("colorConverter = " + colorConverter); if (colorConverter != null) { float[] rgb = new float[3]; if(byteData != null) { for (int j = 0; j < dstHeight; j++) { int idx = dstOffset; for (int i = 0; i < dstWidth; i++) { float x0 = (float)(byteData[idx] & 0xff); float x1 = (float)(byteData[idx + 1] & 0xff); float x2 = (float)(byteData[idx + 2] & 0xff); colorConverter.toRGB(x0, x1, x2, rgb); byteData[idx] = (byte)(rgb[0]); byteData[idx + 1] = (byte)(rgb[1]); byteData[idx + 2] = (byte)(rgb[2]); idx += 3; } dstOffset += scanlineStride; } } else if(shortData != null) { if(sampleFormat[0] == BaselineTIFFTagSet.SAMPLE_FORMAT_SIGNED_INTEGER) { for (int j = 0; j < dstHeight; j++) { int idx = dstOffset; for (int i = 0; i < dstWidth; i++) { float x0 = (float)shortData[idx]; float x1 = (float)shortData[idx + 1]; float x2 = (float)shortData[idx + 2]; colorConverter.toRGB(x0, x1, x2, rgb); shortData[idx] = (short)(rgb[0]); shortData[idx + 1] = (short)(rgb[1]); shortData[idx + 2] = (short)(rgb[2]); idx += 3; } dstOffset += scanlineStride; } } else { for (int j = 0; j < dstHeight; j++) { int idx = dstOffset; for (int i = 0; i < dstWidth; i++) { float x0 = (float)(shortData[idx] & 0xffff); float x1 = (float)(shortData[idx + 1] & 0xffff); float x2 = (float)(shortData[idx + 2] & 0xffff); colorConverter.toRGB(x0, x1, x2, rgb); shortData[idx] = (short)(rgb[0]); shortData[idx + 1] = (short)(rgb[1]); shortData[idx + 2] = (short)(rgb[2]); idx += 3; } dstOffset += scanlineStride; } } } else if(intData != null) { for (int j = 0; j < dstHeight; j++) { int idx = dstOffset; for (int i = 0; i < dstWidth; i++) { float x0 = (float)intData[idx]; float x1 = (float)intData[idx + 1]; float x2 = (float)intData[idx + 2]; colorConverter.toRGB(x0, x1, x2, rgb); intData[idx] = (int)(rgb[0]); intData[idx + 1] = (int)(rgb[1]); intData[idx + 2] = (int)(rgb[2]); idx += 3; } dstOffset += scanlineStride; } } else if(floatData != null) { for (int j = 0; j < dstHeight; j++) { int idx = dstOffset; for (int i = 0; i < dstWidth; i++) { float x0 = floatData[idx]; float x1 = floatData[idx + 1]; float x2 = floatData[idx + 2]; colorConverter.toRGB(x0, x1, x2, rgb); floatData[idx] = rgb[0]; floatData[idx + 1] = rgb[1]; floatData[idx + 2] = rgb[2]; idx += 3; } dstOffset += scanlineStride; } } // int[] p = new int[3]; // ras.getPixel(0, 0, p); // System.out.println("p00 = " + // p[0] + " " + p[1] + " " + p[2]); // ras.getPixel(1, 0, p); // System.out.println("p10 = " + // p[0] + " " + p[1] + " " + p[2]); // ras.getPixel(2, 0, p); // System.out.println("p20 = " + // p[0] + " " + p[1] + " " + p[2]); // ras.getPixel(3, 0, p); // System.out.println("p30 = " + // p[0] + " " + p[1] + " " + p[2]); // ColorSpace rgb = ColorSpace.getInstance(ColorSpace.CS_sRGB); // ColorConvertOp op = new ColorConvertOp(colorSpace, rgb, null); // WritableRaster dest = op.createCompatibleDestRaster(ras); // op.filter(ras, dest); // ras = dest; } if (photometricInterpretation == BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_WHITE_IS_ZERO) { if(byteData != null) { int bytesPerRow = (srcWidth*pixelBitStride + 7)/8; for (int y = 0; y < srcHeight; y++) { int offset = dstOffset + y*scanlineStride; for (int i = 0; i < bytesPerRow; i++) { byteData[offset + i] ^= 0xff; } } } else if(shortData != null) { int shortsPerRow = (srcWidth*pixelBitStride + 15)/16; if(sampleFormat[0] == BaselineTIFFTagSet.SAMPLE_FORMAT_SIGNED_INTEGER) { for (int y = 0; y < srcHeight; y++) { int offset = dstOffset + y*scanlineStride; for (int i = 0; i < shortsPerRow; i++) { int shortOffset = offset + i; // XXX Does this make any sense? shortData[shortOffset] = (short)(Short.MAX_VALUE - shortData[shortOffset]); } } } else { for (int y = 0; y < srcHeight; y++) { int offset = dstOffset + y*scanlineStride; for (int i = 0; i < shortsPerRow; i++) { shortData[offset + i] ^= 0xffff; } } } } else if(intData != null) { int intsPerRow = (srcWidth*pixelBitStride + 15)/16; for (int y = 0; y < srcHeight; y++) { int offset = dstOffset + y*scanlineStride; for (int i = 0; i < intsPerRow; i++) { int intOffset = offset + i; // XXX Does this make any sense? intData[intOffset] = Integer.MAX_VALUE - intData[intOffset]; } } } else if(floatData != null) { int floatsPerRow = (srcWidth*pixelBitStride + 15)/16; for (int y = 0; y < srcHeight; y++) { int offset = dstOffset + y*scanlineStride; for (int i = 0; i < floatsPerRow; i++) { int floatOffset = offset + i; // XXX Does this make any sense? floatData[floatOffset] = 1.0F - floatData[floatOffset]; } } } } if(isBilevel) { Rectangle rect = isImageSimple ? new Rectangle(dstMinX, dstMinY, dstWidth, dstHeight) : ras.getBounds(); ImageUtil.setPackedBinaryData(byteData, ras, rect); } // XXX A better test might be if the rawImage raster either // equals the raster of 'image' or is a child thereof. if (isDirectCopy) { // rawImage == image) { return; } // Copy the raw image data into the true destination image Raster src = rawImage.getRaster(); // Create band child of source Raster srcChild = src.createChild(0, 0, srcWidth, srcHeight, srcMinX, srcMinY, planar ? null : sourceBands); WritableRaster dst = image.getRaster(); // Create dst child covering area and bands to be written WritableRaster dstChild = dst.createWritableChild(dstMinX, dstMinY, dstWidth, dstHeight, dstMinX, dstMinY, destinationBands); if (subsampleX == 1 && subsampleY == 1 && !adjustBitDepths) { srcChild = srcChild.createChild(activeSrcMinX, activeSrcMinY, activeSrcWidth, activeSrcHeight, dstMinX, dstMinY, null); dstChild.setRect(srcChild); } else if (subsampleX == 1 && !adjustBitDepths) { int sy = activeSrcMinY; int dy = dstMinY; while (sy < srcMinY + srcHeight) { Raster srcRow = srcChild.createChild(activeSrcMinX, sy, activeSrcWidth, 1, dstMinX, dy, null); dstChild.setRect(srcRow); sy += subsampleY; ++dy; } } else { int[] p = srcChild.getPixel(srcMinX, srcMinY, (int[])null); int numBands = p.length; int sy = activeSrcMinY; int dy = dstMinY; while (sy < activeSrcMinY + activeSrcHeight) { int sx = activeSrcMinX; int dx = dstMinX; while (sx < activeSrcMinX + activeSrcWidth) { srcChild.getPixel(sx, sy, p); if (adjustBitDepths) { for (int band = 0; band < numBands; band++) { p[band] = bitDepthScale[band][p[band]]; } } dstChild.setPixel(dx, dy, p); sx += subsampleX; ++dx; } sy += subsampleY; ++dy; } } } } jai-imageio-core-1.2/src/share/classes/com/sun/media/imageio/plugins/tiff/TIFFField.java0000664000175100017510000011622510424267721030053 0ustar tilletille/* * $RCSfile: TIFFField.java,v $ * * * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.4 $ * $Date: 2006-04-28 01:28:49 $ * $State: Exp $ */ package com.sun.media.imageio.plugins.tiff; import java.io.IOException; import java.io.Serializable; import java.util.StringTokenizer; import javax.imageio.metadata.IIOMetadataNode; import javax.imageio.stream.ImageOutputStream; import org.w3c.dom.NamedNodeMap; import org.w3c.dom.Node; import com.sun.media.imageio.plugins.tiff.TIFFTag; import com.sun.media.imageio.plugins.tiff.TIFFTagSet; import com.sun.media.imageioimpl.plugins.tiff.TIFFFieldNode; /** * A class representing a field in a TIFF 6.0 Image File Directory. * *

A field in a TIFF Image File Directory (IFD) is defined as a * tag number accompanied by a sequence of values of identical data type. * TIFF 6.0 defines 12 data types; a 13th type IFD is * defined in TIFF Tech Note 1 of TIFF Specification Supplement 1. These * TIFF data types are referred to by Java constants and mapped internally * onto Java language data types and type names as follows: * *
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* TIFF Data Type * * Java Constant * * Java Data Type * * Java Type Name *
* BYTE * * {@link TIFFTag#TIFF_BYTE} * * byte * * "Byte" *
* ASCII * * {@link TIFFTag#TIFF_ASCII} * * String * * "Ascii" *
* SHORT * * {@link TIFFTag#TIFF_SHORT} * * char * * "Short" *
* LONG * * {@link TIFFTag#TIFF_LONG} * * long * * "Long" *
* RATIONAL * * {@link TIFFTag#TIFF_RATIONAL} * * long[2] {numerator, denominator} * * "Rational" *
* SBYTE * * {@link TIFFTag#TIFF_SBYTE} * * byte * * "SByte" *
* UNDEFINED * * {@link TIFFTag#TIFF_UNDEFINED} * * byte * * "Undefined" *
* SSHORT * * {@link TIFFTag#TIFF_SSHORT} * * short * * "SShort" *
* SLONG * * {@link TIFFTag#TIFF_SLONG} * * int * * "SLong" *
* SRATIONAL * * {@link TIFFTag#TIFF_SRATIONAL} * * int[2] {numerator, denominator} * * "SRational" *
* FLOAT * * {@link TIFFTag#TIFF_FLOAT} * * float * * "Float" *
* DOUBLE * * {@link TIFFTag#TIFF_DOUBLE} * * double * * "Double" *
* IFD * * {@link TIFFTag#TIFF_IFD_POINTER} * * long * * "IFDPointer" *
* * @see TIFFDirectory * @see TIFFTag */ public class TIFFField implements Comparable { private static final String[] typeNames = { null, "Byte", "Ascii", "Short", "Long", "Rational", "SByte", "Undefined", "SShort", "SLong", "SRational", "Float", "Double", "IFDPointer" }; private static final boolean[] isIntegral = { false, true, false, true, true, false, true, true, true, true, false, false, false, false }; /** The tag. */ private TIFFTag tag; /** The tag number. */ private int tagNumber; /** The tag type. */ private int type; /** The number of data items present in the field. */ private int count; /** The field data. */ private Object data; /** The default constructor. */ private TIFFField() {} private static String getAttribute(Node node, String attrName) { NamedNodeMap attrs = node.getAttributes(); return attrs.getNamedItem(attrName).getNodeValue(); } private static void initData(Node node, int[] otype, int[] ocount, Object[] odata) { int type; int count; Object data = null; String typeName = node.getNodeName(); typeName = typeName.substring(4); typeName = typeName.substring(0, typeName.length() - 1); type = TIFFField.getTypeByName(typeName); if (type == -1) { throw new IllegalArgumentException("typeName = " + typeName); } Node child = node.getFirstChild(); count = 0; while (child != null) { String childTypeName = child.getNodeName().substring(4); if (!typeName.equals(childTypeName)) { // warning } ++count; child = child.getNextSibling(); } if (count > 0) { data = createArrayForType(type, count); child = node.getFirstChild(); int idx = 0; while (child != null) { String value = getAttribute(child, "value"); String numerator, denominator; int slashPos; switch (type) { case TIFFTag.TIFF_ASCII: ((String[])data)[idx] = value; break; case TIFFTag.TIFF_BYTE: case TIFFTag.TIFF_SBYTE: ((byte[])data)[idx] = (byte)Integer.parseInt(value); break; case TIFFTag.TIFF_SHORT: ((char[])data)[idx] = (char)Integer.parseInt(value); break; case TIFFTag.TIFF_SSHORT: ((short[])data)[idx] = (short)Integer.parseInt(value); break; case TIFFTag.TIFF_SLONG: ((int[])data)[idx] = (int)Integer.parseInt(value); break; case TIFFTag.TIFF_LONG: case TIFFTag.TIFF_IFD_POINTER: ((long[])data)[idx] = (long)Long.parseLong(value); break; case TIFFTag.TIFF_FLOAT: ((float[])data)[idx] = (float)Float.parseFloat(value); break; case TIFFTag.TIFF_DOUBLE: ((double[])data)[idx] = (double)Double.parseDouble(value); break; case TIFFTag.TIFF_SRATIONAL: slashPos = value.indexOf("/"); numerator = value.substring(0, slashPos); denominator = value.substring(slashPos + 1); ((int[][])data)[idx] = new int[2]; ((int[][])data)[idx][0] = Integer.parseInt(numerator); ((int[][])data)[idx][1] = Integer.parseInt(denominator); break; case TIFFTag.TIFF_RATIONAL: slashPos = value.indexOf("/"); numerator = value.substring(0, slashPos); denominator = value.substring(slashPos + 1); ((long[][])data)[idx] = new long[2]; ((long[][])data)[idx][0] = Long.parseLong(numerator); ((long[][])data)[idx][1] = Long.parseLong(denominator); break; default: // error } idx++; child = child.getNextSibling(); } } otype[0] = type; ocount[0] = count; odata[0] = data; } /** * Creates a TIFFField from a TIFF native image * metadata node. If the value of the "tagNumber" attribute * of the node is not found in tagSet then a new * TIFFTag with name "unknown" will be * created and assigned to the field. * * @param tagSet The TIFFTagSet to which the * TIFFTag of the field belongs. * @param node A native TIFF image metadata TIFFField node. * @throws IllegalArgumentException if node is * null. * @throws IllegalArgumentException if the name of the node is not * "TIFFField". */ public static TIFFField createFromMetadataNode(TIFFTagSet tagSet, Node node) { if (node == null) { throw new IllegalArgumentException("node == null!"); } String name = node.getNodeName(); if (!name.equals("TIFFField")) { throw new IllegalArgumentException("!name.equals(\"TIFFField\")"); } int tagNumber = Integer.parseInt(getAttribute(node, "number")); TIFFTag tag; if (tagSet != null) { tag = tagSet.getTag(tagNumber); } else { tag = new TIFFTag("unknown", tagNumber, 0, null); } int type = TIFFTag.TIFF_UNDEFINED; int count = 0; Object data = null; Node child = node.getFirstChild(); if (child != null) { String typeName = child.getNodeName(); if (typeName.equals("TIFFUndefined")) { String values = getAttribute(child, "value"); StringTokenizer st = new StringTokenizer(values, ","); count = st.countTokens(); byte[] bdata = new byte[count]; for (int i = 0; i < count; i++) { bdata[i] = (byte)Integer.parseInt(st.nextToken()); } type = TIFFTag.TIFF_UNDEFINED; data = bdata; } else { int[] otype = new int[1]; int[] ocount = new int[1]; Object[] odata = new Object[1]; initData(node.getFirstChild(), otype, ocount, odata); type = otype[0]; count = ocount[0]; data = odata[0]; } } else { int t = TIFFTag.MAX_DATATYPE; while(t >= TIFFTag.MIN_DATATYPE && !tag.isDataTypeOK(t)) { t--; } type = t; } return new TIFFField(tag, type, count, data); } /** * Constructs a TIFFField with arbitrary data. The * type parameter must be a value for which * {@link TIFFTag#isDataTypeOK tag.isDataTypeOK()} * returns true. The data parameter must * be an array of a Java type appropriate for the type of the TIFF * field unless {@link TIFFTag#isIFDPointer * tag.isIFDPointer()} returns true in * which case it must be a TIFFDirectory instance. * *

Neither the legality of type with respect to * tag nor that or data with respect to * type is verified by this constructor. The methods * {@link TIFFTag#isDataTypeOK TIFFTag.isDataTypeOK()} * and {@link #createArrayForType createArrayForType()} * should be used programmatically to ensure that subsequent errors * such as ClassCastExceptions do not occur as a result * of providing inconsitent parameters to this constructor.

* *

Note that the value (data) of the TIFFField * will always be the actual field value regardless of the number of * bytes required for that value. This is the case despite the fact * that the TIFF IFD Entry corresponding to the field may * actually contain the offset to the field's value rather than * the value itself (the latter occurring if and only if the * value fits into 4 bytes). In other words, the value of the * field will already have been read from the TIFF stream. This * subsumes the case where tag.isIFDPointer() returns * true and the value will be a TIFFDirectory * rather than an array.

* * @param tag The tag to associated with this field. * @param type One of the TIFFTag.TIFF_* constants * indicating the data type of the field as written to the TIFF stream. * @param count The number of data values. * @param data The actual data content of the field. * * @throws IllegalArgumentException if tag == null. * @throws IllegalArgumentException if dataType is not * one of the TIFFTag.TIFF_* data type constants. * @throws IllegalArgumentException if count < 0. */ public TIFFField(TIFFTag tag, int type, int count, Object data) { if(tag == null) { throw new IllegalArgumentException("tag == null!"); } else if(type < TIFFTag.MIN_DATATYPE || type > TIFFTag.MAX_DATATYPE) { throw new IllegalArgumentException("Unknown data type "+type); } else if(count < 0) { throw new IllegalArgumentException("count < 0!"); } this.tag = tag; this.tagNumber = tag.getNumber(); this.type = type; this.count = count; this.data = data; } /** * Constructs a data array using {@link #createArrayForType * createArrayForType()} and invokes * {@link #TIFFField(TIFFTag,int,int,Object)} with the supplied * parameters and the created array. * * @see #TIFFField(TIFFTag,int,int,Object) */ public TIFFField(TIFFTag tag, int type, int count) { this(tag, type, count, createArrayForType(type, count)); } /** * Constructs a TIFFField with a single integral value. * The field will have type * {@link TIFFTag#TIFF_SHORT TIFF_SHORT} if * val < 65536 and type * {@link TIFFTag#TIFF_LONG TIFF_LONG} otherwise. * It is not verified whether the resulting type is * legal for tag. * * @param tag The tag to associate with this field. * @param value The value to associate with this field. * @throws IllegalArgumentException if tag == null. * @throws IllegalArgumentException if value < 0. */ public TIFFField(TIFFTag tag, int value) { if(tag == null) { throw new IllegalArgumentException("tag == null!"); } if (value < 0) { throw new IllegalArgumentException("value < 0!"); } this.tag = tag; this.tagNumber = tag.getNumber(); this.count = 1; if (value < 65536) { this.type = TIFFTag.TIFF_SHORT; char[] cdata = new char[1]; cdata[0] = (char)value; this.data = cdata; } else { this.type = TIFFTag.TIFF_LONG; long[] ldata = new long[1]; ldata[0] = value; this.data = ldata; } } /** * Retrieves the tag associated with this field. * * @return The associated TIFFTag. */ public TIFFTag getTag() { return tag; } /** * Retrieves the tag number in the range [0, 65535]. * * @return The tag number. */ public int getTagNumber() { return tagNumber; } /** * Returns the type of the data stored in the field. For a TIFF 6.0 * stream, the value will equal one of the TIFFTag.TIFF_* * constants. For future revisions of TIFF, higher values are possible. * * @return The data type of the field value. */ public int getType() { return type; } /** * Returns the name of the supplied data type constant. * * @param dataType One of the TIFFTag.TIFF_* constants * indicating the data type of the field as written to the TIFF stream. * @return The type name corresponding to the supplied type constant. * @throws IllegalArgumentException if dataType is not * one of the TIFFTag.TIFF_* data type constants. */ public static String getTypeName(int dataType) { if (dataType < TIFFTag.MIN_DATATYPE || dataType > TIFFTag.MAX_DATATYPE) { throw new IllegalArgumentException("Unknown data type "+dataType); } return typeNames[dataType]; } /** * Returns the data type constant corresponding to the supplied data * type name. If the name is unknown -1 will be returned. * * @return One of the TIFFTag.TIFF_* constants or * -1 if the name is not recognized. */ public static int getTypeByName(String typeName) { for (int i = TIFFTag.MIN_DATATYPE; i <= TIFFTag.MAX_DATATYPE; i++) { if (typeName.equals(typeNames[i])) { return i; } } return -1; } /** * Creates an array appropriate for the indicated data type. * * @param dataType One of the TIFFTag.TIFF_* data type * constants. * @param count The number of values in the array. * * @throws IllegalArgumentException if dataType is not * one of the TIFFTag.TIFF_* data type constants. * @throws IllegalArgumentException if count < 0. */ public static Object createArrayForType(int dataType, int count) { if(count < 0) { throw new IllegalArgumentException("count < 0!"); } switch (dataType) { case TIFFTag.TIFF_BYTE: case TIFFTag.TIFF_SBYTE: case TIFFTag.TIFF_UNDEFINED: return new byte[count]; case TIFFTag.TIFF_ASCII: return new String[count]; case TIFFTag.TIFF_SHORT: return new char[count]; case TIFFTag.TIFF_LONG: case TIFFTag.TIFF_IFD_POINTER: return new long[count]; case TIFFTag.TIFF_RATIONAL: return new long[count][2]; case TIFFTag.TIFF_SSHORT: return new short[count]; case TIFFTag.TIFF_SLONG: return new int[count]; case TIFFTag.TIFF_SRATIONAL: return new int[count][2]; case TIFFTag.TIFF_FLOAT: return new float[count]; case TIFFTag.TIFF_DOUBLE: return new double[count]; default: throw new IllegalArgumentException("Unknown data type "+dataType); } } /** * Returns the TIFFField as a node named either * "TIFFField" or "TIFFIFD" as described in the * TIFF native image metadata specification. The node will be named * "TIFFIFD" if and only if the field's data object is an * instance of {@link TIFFDirectory} or equivalently * {@link TIFFTag#isIFDPointer getTag.isIFDPointer()} returns * true. * * @return a Node named "TIFFField" or * "TIFFIFD". */ public Node getAsNativeNode() { return new TIFFFieldNode(this); } /** * Indicates whether the value associated with the field is of * integral data type. * * @return Whether the field type is integral. */ public boolean isIntegral() { return isIntegral[type]; } /** * Returns the number of data items present in the field. For * TIFFTag.TIFF_ASCII fields, the value returned is the * number of Strings, not the total length of the * data as in the file representation. */ public int getCount() { return count; } /** * Returns a reference to the data object associated with the field. * * @return The data object of the field. */ public Object getData() { return data; } /** * Returns the data as an uninterpreted array of * bytes. The type of the field must be one of * TIFFTag.TIFF_BYTE, TIFF_SBYTE, or * TIFF_UNDEFINED. * *

For data in TIFFTag.TIFF_BYTE format, the application * must take care when promoting the data to longer integral types * to avoid sign extension. * * @throws ClassCastException if the field is not of type * TIFF_BYTE, TIFF_SBYTE, or * TIFF_UNDEFINED. */ public byte[] getAsBytes() { return (byte[])data; } /** * Returns TIFFTag.TIFF_SHORT data as an array of * chars (unsigned 16-bit integers). * * @throws ClassCastException if the field is not of type * TIFF_SHORT. */ public char[] getAsChars() { return (char[])data; } /** * Returns TIFFTag.TIFF_SSHORT data as an array of * shorts (signed 16-bit integers). * * @throws ClassCastException if the field is not of type * TIFF_SSHORT. */ public short[] getAsShorts() { return (short[])data; } /** * Returns TIFFTag.TIFF_SLONG data as an array of * ints (signed 32-bit integers). * * @throws ClassCastException if the field is not of type * TIFF_SHORT, TIFF_SSHORT, or * TIFF_SLONG. */ public int[] getAsInts() { if (data instanceof int[]) { return (int[])data; } else if (data instanceof char[]){ char[] cdata = (char[])data; int[] idata = new int[cdata.length]; for (int i = 0; i < cdata.length; i++) { idata[i] = (int)(cdata[i] & 0xffff); } return idata; } else if (data instanceof short[]){ short[] sdata = (short[])data; int[] idata = new int[sdata.length]; for (int i = 0; i < sdata.length; i++) { idata[i] = (int)sdata[i]; } return idata; } else { throw new ClassCastException( "Data not char[], short[], or int[]!"); } } /** * Returns TIFFTag.TIFF_LONG or * TIFF_IFD_POINTER data as an array of * longs (signed 64-bit integers). * * @throws ClassCastException if the field is not of type * TIFF_LONG or TIFF_IFD_POINTER. */ public long[] getAsLongs() { return (long[])data; } /** * Returns TIFFTag.TIFF_FLOAT data as an array of * floats (32-bit floating-point values). * * @throws ClassCastException if the field is not of type * TIFF_FLOAT. */ public float[] getAsFloats() { return (float[])data; } /** * Returns TIFFTag.TIFF_DOUBLE data as an array of * doubles (64-bit floating-point values). * * @throws ClassCastException if the field is not of type * TIFF_DOUBLE. */ public double[] getAsDoubles() { return (double[])data; } /** * Returns TIFFTag.TIFF_SRATIONAL data as an array of * 2-element arrays of ints. * * @throws ClassCastException if the field is not of type * TIFF_SRATIONAL. */ public int[][] getAsSRationals() { return (int[][])data; } /** * Returns TIFFTag.TIFF_RATIONAL data as an array of * 2-element arrays of longs. * * @throws ClassCastException if the field is not of type * TIFF_RATIONAL. */ public long[][] getAsRationals() { return (long[][])data; } /** * Returns data in any format as an int. * *

TIFFTag.TIFF_BYTE values are treated as unsigned; that * is, no sign extension will take place and the returned value * will be in the range [0, 255]. TIFF_SBYTE data * will be returned in the range [-128, 127]. * *

A TIFF_UNDEFINED value is treated as though * it were a TIFF_BYTE. * *

Data in TIFF_SLONG, TIFF_LONG, * TIFF_FLOAT, TIFF_DOUBLE or * TIFF_IFD_POINTER format are simply cast to * int and may suffer from truncation. * *

Data in TIFF_SRATIONAL or * TIFF_RATIONAL format are evaluated by dividing the * numerator into the denominator using double-precision * arithmetic and then casting to int. Loss of * precision and truncation may occur. * *

Data in TIFF_ASCII format will be parsed as by * the Double.parseDouble method, with the result * case to int. */ public int getAsInt(int index) { switch (type) { case TIFFTag.TIFF_BYTE: case TIFFTag.TIFF_UNDEFINED: return ((byte[])data)[index] & 0xff; case TIFFTag.TIFF_SBYTE: return ((byte[])data)[index]; case TIFFTag.TIFF_SHORT: return ((char[])data)[index] & 0xffff; case TIFFTag.TIFF_SSHORT: return ((short[])data)[index]; case TIFFTag.TIFF_SLONG: return ((int[])data)[index]; case TIFFTag.TIFF_LONG: case TIFFTag.TIFF_IFD_POINTER: return (int)((long[])data)[index]; case TIFFTag.TIFF_FLOAT: return (int)((float[])data)[index]; case TIFFTag.TIFF_DOUBLE: return (int)((double[])data)[index]; case TIFFTag.TIFF_SRATIONAL: int[] ivalue = getAsSRational(index); return (int)((double)ivalue[0]/ivalue[1]); case TIFFTag.TIFF_RATIONAL: long[] lvalue = getAsRational(index); return (int)((double)lvalue[0]/lvalue[1]); case TIFFTag.TIFF_ASCII: String s = ((String[])data)[index]; return (int)Double.parseDouble(s); default: throw new ClassCastException(); } } /** * Returns data in any format as a long. * *

TIFFTag.TIFF_BYTE and TIFF_UNDEFINED data * are treated as unsigned; that is, no sign extension will take * place and the returned value will be in the range [0, 255]. * TIFF_SBYTE data will be returned in the range * [-128, 127]. * *

Data in TIFF_ASCII format will be parsed as by * the Double.parseDouble method, with the result * cast to long. */ public long getAsLong(int index) { switch (type) { case TIFFTag.TIFF_BYTE: case TIFFTag.TIFF_UNDEFINED: return ((byte[])data)[index] & 0xff; case TIFFTag.TIFF_SBYTE: return ((byte[])data)[index]; case TIFFTag.TIFF_SHORT: return ((char[])data)[index] & 0xffff; case TIFFTag.TIFF_SSHORT: return ((short[])data)[index]; case TIFFTag.TIFF_SLONG: return ((int[])data)[index]; case TIFFTag.TIFF_LONG: case TIFFTag.TIFF_IFD_POINTER: return ((long[])data)[index]; case TIFFTag.TIFF_SRATIONAL: int[] ivalue = getAsSRational(index); return (long)((double)ivalue[0]/ivalue[1]); case TIFFTag.TIFF_RATIONAL: long[] lvalue = getAsRational(index); return (long)((double)lvalue[0]/lvalue[1]); case TIFFTag.TIFF_ASCII: String s = ((String[])data)[index]; return (long)Double.parseDouble(s); default: throw new ClassCastException(); } } /** * Returns data in any format as a float. * *

TIFFTag.TIFF_BYTE and TIFF_UNDEFINED data * are treated as unsigned; that is, no sign extension will take * place and the returned value will be in the range [0, 255]. * TIFF_SBYTE data will be returned in the range * [-128, 127]. * *

Data in TIFF_SLONG, TIFF_LONG, * TIFF_DOUBLE, or TIFF_IFD_POINTER format are * simply cast to float and may suffer from * truncation. * *

Data in TIFF_SRATIONAL or * TIFF_RATIONAL format are evaluated by dividing the * numerator into the denominator using double-precision * arithmetic and then casting to float. * *

Data in TIFF_ASCII format will be parsed as by * the Double.parseDouble method, with the result * cast to float. */ public float getAsFloat(int index) { switch (type) { case TIFFTag.TIFF_BYTE: case TIFFTag.TIFF_UNDEFINED: return ((byte[])data)[index] & 0xff; case TIFFTag.TIFF_SBYTE: return ((byte[])data)[index]; case TIFFTag.TIFF_SHORT: return ((char[])data)[index] & 0xffff; case TIFFTag.TIFF_SSHORT: return ((short[])data)[index]; case TIFFTag.TIFF_SLONG: return ((int[])data)[index]; case TIFFTag.TIFF_LONG: case TIFFTag.TIFF_IFD_POINTER: return ((long[])data)[index]; case TIFFTag.TIFF_FLOAT: return ((float[])data)[index]; case TIFFTag.TIFF_DOUBLE: return (float)((double[])data)[index]; case TIFFTag.TIFF_SRATIONAL: int[] ivalue = getAsSRational(index); return (float)((double)ivalue[0]/ivalue[1]); case TIFFTag.TIFF_RATIONAL: long[] lvalue = getAsRational(index); return (float)((double)lvalue[0]/lvalue[1]); case TIFFTag.TIFF_ASCII: String s = ((String[])data)[index]; return (float)Double.parseDouble(s); default: throw new ClassCastException(); } } /** * Returns data in any format as a double. * *

TIFFTag.TIFF_BYTE and TIFF_UNDEFINED data * are treated as unsigned; that is, no sign extension will take * place and the returned value will be in the range [0, 255]. * TIFF_SBYTE data will be returned in the range * [-128, 127]. * *

Data in TIFF_SRATIONAL or * TIFF_RATIONAL format are evaluated by dividing the * numerator into the denominator using double-precision * arithmetic. * *

Data in TIFF_ASCII format will be parsed as by * the Double.parseDouble method. */ public double getAsDouble(int index) { switch (type) { case TIFFTag.TIFF_BYTE: case TIFFTag.TIFF_UNDEFINED: return ((byte[])data)[index] & 0xff; case TIFFTag.TIFF_SBYTE: return ((byte[])data)[index]; case TIFFTag.TIFF_SHORT: return ((char[])data)[index] & 0xffff; case TIFFTag.TIFF_SSHORT: return ((short[])data)[index]; case TIFFTag.TIFF_SLONG: return ((int[])data)[index]; case TIFFTag.TIFF_LONG: case TIFFTag.TIFF_IFD_POINTER: return ((long[])data)[index]; case TIFFTag.TIFF_FLOAT: return ((float[])data)[index]; case TIFFTag.TIFF_DOUBLE: return ((double[])data)[index]; case TIFFTag.TIFF_SRATIONAL: int[] ivalue = getAsSRational(index); return (double)ivalue[0]/ivalue[1]; case TIFFTag.TIFF_RATIONAL: long[] lvalue = getAsRational(index); return (double)lvalue[0]/lvalue[1]; case TIFFTag.TIFF_ASCII: String s = ((String[])data)[index]; return Double.parseDouble(s); default: throw new ClassCastException(); } } /** * Returns a TIFFTag.TIFF_ASCII value as a * String. * * @throws ClassCastException if the field is not of type * TIFF_ASCII. */ public String getAsString(int index) { return ((String[])data)[index]; } /** * Returns a TIFFTag.TIFF_SRATIONAL data item as a * two-element array of ints. * * @throws ClassCastException if the field is not of type * TIFF_SRATIONAL. */ public int[] getAsSRational(int index) { return ((int[][])data)[index]; } /** * Returns a TIFFTag.TIFF_RATIONAL data item as a two-element array * of ints. * * @throws ClassCastException if the field is not of type * TIFF_RATIONAL. */ public long[] getAsRational(int index) { return ((long[][])data)[index]; } /** * Returns a String containing a human-readable * version of the data item. Data of type * TIFFTag.TIFF_RATIONAL or TIFF_SRATIONAL are * represented as a pair of integers separated by a * '/' character. * * @throws ClassCastException if the field is not of one of the * legal field types. */ public String getValueAsString(int index) { switch (type) { case TIFFTag.TIFF_ASCII: return ((String[])data)[index]; case TIFFTag.TIFF_BYTE: case TIFFTag.TIFF_UNDEFINED: return Integer.toString(((byte[])data)[index] & 0xff); case TIFFTag.TIFF_SBYTE: return Integer.toString(((byte[])data)[index]); case TIFFTag.TIFF_SHORT: return Integer.toString(((char[])data)[index] & 0xffff); case TIFFTag.TIFF_SSHORT: return Integer.toString(((short[])data)[index]); case TIFFTag.TIFF_SLONG: return Integer.toString(((int[])data)[index]); case TIFFTag.TIFF_LONG: case TIFFTag.TIFF_IFD_POINTER: return Long.toString(((long[])data)[index]); case TIFFTag.TIFF_FLOAT: return Float.toString(((float[])data)[index]); case TIFFTag.TIFF_DOUBLE: return Double.toString(((double[])data)[index]); case TIFFTag.TIFF_SRATIONAL: int[] ivalue = getAsSRational(index); String srationalString; if(ivalue[1] != 0 && ivalue[0] % ivalue[1] == 0) { // If the denominator is a non-zero integral divisor // of the numerator then convert the fraction to be // with respect to a unity denominator. srationalString = Integer.toString(ivalue[0] / ivalue[1]) + "/1"; } else { // Use the values directly. srationalString = Integer.toString(ivalue[0]) + "/" + Integer.toString(ivalue[1]); } return srationalString; case TIFFTag.TIFF_RATIONAL: long[] lvalue = getAsRational(index); String rationalString; if(lvalue[1] != 0L && lvalue[0] % lvalue[1] == 0) { // If the denominator is a non-zero integral divisor // of the numerator then convert the fraction to be // with respect to a unity denominator. rationalString = Long.toString(lvalue[0] / lvalue[1]) + "/1"; } else { // Use the values directly. rationalString = Long.toString(lvalue[0]) + "/" + Long.toString(lvalue[1]); } return rationalString; default: throw new ClassCastException(); } } /** * Compares this TIFFField with another * TIFFField by comparing the tags. * *

Note: this class has a natural ordering that is inconsistent * with equals(). * * @throws IllegalArgumentException if the parameter is null. * @throws ClassCastException if the parameter is not a * TIFFField. */ public int compareTo(Object o) { if (o == null) { throw new IllegalArgumentException(); } int oTagNumber = ((TIFFField)o).getTagNumber(); if (tagNumber < oTagNumber) { return -1; } else if (tagNumber > oTagNumber) { return 1; } else { return 0; } } } jai-imageio-core-1.2/src/share/classes/com/sun/media/imageio/plugins/tiff/TIFFImageReadParam.java0000664000175100017510000001723510203036165031617 0ustar tilletille/* * $RCSfile: TIFFImageReadParam.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.1 $ * $Date: 2005-02-11 05:01:18 $ * $State: Exp $ */ package com.sun.media.imageio.plugins.tiff; import java.util.ArrayList; import java.util.List; import javax.imageio.ImageReadParam; /** * A subclass of {@link ImageReadParam} allowing control over * the TIFF reading process. * *

Because TIFF is an extensible format, the reader requires * information about any tags used by TIFF extensions in order to emit * meaningful metadata. Also, TIFF extensions may define new * compression types. Both types of information about extensions may * be provided by this interface. * *

Additional TIFF tags must be organized into * TIFFTagSets. A TIFFTagSet may be * provided to the reader by means of the * addAllowedTagSet method. By default, the tag sets * BaselineTIFFTagSet, FaxTIFFTagSet, * EXIFParentTIFFTagSet, and GeoTIFFTagSet * are included. * *

New TIFF decompressors are handled in a simple fashion. If a * non-null TIFFDecompressor is provided by * means of the setTIFFDecompressor method, it will override the * reader's usual choice of decompressor. Thus, to read an image with * a non-standard compression type, the application should first * attempt to read the image's metadata and extract the compression * type. The application may then use its own logic to choose a * suitable TIFFDecompressor, instantiate it, and pass it * to the ImageReadParam being used. The reader's * read method may be called with the * ImageReadParam set. */ public class TIFFImageReadParam extends ImageReadParam { List allowedTagSets = new ArrayList(4); TIFFDecompressor decompressor = null; TIFFColorConverter colorConverter = null; /** * Constructs a TIFFImageReadParam. Tags defined by * the TIFFTagSets BaselineTIFFTagSet, * FaxTIFFTagSet, EXIFParentTIFFTagSet, and * GeoTIFFTagSet will be supported. * * @see BaselineTIFFTagSet * @see FaxTIFFTagSet * @see EXIFParentTIFFTagSet * @see GeoTIFFTagSet */ public TIFFImageReadParam() { addAllowedTagSet(BaselineTIFFTagSet.getInstance()); addAllowedTagSet(FaxTIFFTagSet.getInstance()); addAllowedTagSet(EXIFParentTIFFTagSet.getInstance()); addAllowedTagSet(GeoTIFFTagSet.getInstance()); } /** * Adds a TIFFTagSet object to the list of allowed * tag sets. * * @param tagSet a TIFFTagSet. * * @throws IllegalArgumentException if tagSet is * null. */ public void addAllowedTagSet(TIFFTagSet tagSet) { if (tagSet == null) { throw new IllegalArgumentException("tagSet == null!"); } allowedTagSets.add(tagSet); } /** * Removes a TIFFTagSet object from the list of * allowed tag sets. Removal is based on the equals * method of the TIFFTagSet, which is normally * defined as reference equality. * * @param tagSet a TIFFTagSet. * * @throws IllegalArgumentException if tagSet is * null. */ public void removeAllowedTagSet(TIFFTagSet tagSet) { if (tagSet == null) { throw new IllegalArgumentException("tagSet == null!"); } allowedTagSets.remove(tagSet); } /** * Returns a List containing the allowed * TIFFTagSet objects. * * @return a List of TIFFTagSets. */ public List getAllowedTagSets() { return allowedTagSets; } /** * Sets the TIFFDecompressor object to be used by the * ImageReader to decode each image strip or tile. * A value of null allows the reader to choose its * own TIFFDecompressor. * * @param decompressor the TIFFDecompressor to be * used for decoding, or null to allow the reader to * choose its own. * * @see #getTIFFDecompressor */ public void setTIFFDecompressor(TIFFDecompressor decompressor) { this.decompressor = decompressor; } /** * Returns the TIFFDecompressor that is currently set * to be used by the ImageReader to decode each image * strip or tile, or null if none has been set. * * @return decompressor the TIFFDecompressor to be * used for decoding, or null if none has been set * (allowing the reader to choose its own). * * @see #setTIFFDecompressor(TIFFDecompressor) */ public TIFFDecompressor getTIFFDecompressor() { return this.decompressor; } /** * Sets the TIFFColorConverter object for the pixel data * being read. The data will be converted from the given color * space to a standard RGB space as it is being read. A value of * null disables conversion. * * @param colorConverter a TIFFColorConverter object * to be used for final color conversion, or null. * * @see #getColorConverter */ public void setColorConverter(TIFFColorConverter colorConverter) { this.colorConverter = colorConverter; } /** * Returns the currently set TIFFColorConverter object, * or null if none is set. * * @return the current TIFFColorConverter object. * * @see #setColorConverter(TIFFColorConverter) */ public TIFFColorConverter getColorConverter() { return this.colorConverter; } } jai-imageio-core-1.2/src/share/classes/com/sun/media/imageio/plugins/tiff/EXIFParentTIFFTagSet.java0000664000175100017510000001003010424264607032030 0ustar tilletille/* * $RCSfile: EXIFParentTIFFTagSet.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.4 $ * $Date: 2006-04-28 01:01:59 $ * $State: Exp $ */ package com.sun.media.imageio.plugins.tiff; import java.util.ArrayList; import java.util.List; /** * A class containing the TIFF tags used to reference the EXIF and GPS IFDs. * This tag set should be added to the root tag set by means of the * {@link TIFFImageReadParam#addAllowedTagSet(TIFFTagSet) * TIFFImageReadParam.addAllowedTagSet} method if EXIF * support is desired. */ public class EXIFParentTIFFTagSet extends TIFFTagSet { private static EXIFParentTIFFTagSet theInstance = null; // 34665 - EXIF IFD Pointer (LONG/1) /** Tag pointing to the EXIF IFD (type LONG). */ public static final int TAG_EXIF_IFD_POINTER = 34665; /** Tag pointing to a GPS info IFD (type LONG). */ public static final int TAG_GPS_INFO_IFD_POINTER = 34853; // To be inserted into parent (root) TIFFTagSet static class EXIFIFDPointer extends TIFFTag { public EXIFIFDPointer() { super("EXIFIFDPointer", TAG_EXIF_IFD_POINTER, 1 << TIFFTag.TIFF_LONG, EXIFTIFFTagSet.getInstance()); } } // To be inserted into parent (root) TIFFTagSet static class GPSInfoIFDPointer extends TIFFTag { public GPSInfoIFDPointer() { super("GPSInfoIFDPointer", TAG_GPS_INFO_IFD_POINTER, 1 << TIFFTag.TIFF_LONG, EXIFGPSTagSet.getInstance()); } } private static List tags; private static void initTags() { tags = new ArrayList(1); tags.add(new EXIFParentTIFFTagSet.EXIFIFDPointer()); tags.add(new EXIFParentTIFFTagSet.GPSInfoIFDPointer()); } private EXIFParentTIFFTagSet() { super(tags); } /** * Returns a shared instance of an EXIFParentTIFFTagSet. * * @return an EXIFParentTIFFTagSet instance. */ public synchronized static EXIFParentTIFFTagSet getInstance() { if (theInstance == null) { initTags(); theInstance = new EXIFParentTIFFTagSet(); tags = null; } return theInstance; } } jai-imageio-core-1.2/src/share/classes/com/sun/media/imageio/plugins/tiff/TIFFCompressor.java0000664000175100017510000002263410203036165031153 0ustar tilletille/* * $RCSfile: TIFFCompressor.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.1 $ * $Date: 2005-02-11 05:01:18 $ * $State: Exp $ */ package com.sun.media.imageio.plugins.tiff; import java.io.IOException; import javax.imageio.ImageWriter; import javax.imageio.metadata.IIOMetadata; import javax.imageio.stream.ImageOutputStream; import com.sun.media.imageioimpl.plugins.tiff.TIFFImageWriter; /** * An abstract superclass for pluggable TIFF compressors. */ public abstract class TIFFCompressor { /** * The ImageWriter calling this * TIFFCompressor. */ protected ImageWriter writer; /** * The IIOMetadata object containing metadata for the * current image. */ protected IIOMetadata metadata; /** * The name of the compression type supported by this compressor. */ protected String compressionType; /** * The value to be assigned to the TIFF Compression tag in the * TIFF image metadata. */ protected int compressionTagValue; /** * Whether the compression is lossless. */ protected boolean isCompressionLossless; /** * The ImageOutputStream to be written. */ protected ImageOutputStream stream; /** * Creates a compressor object for use in compressing TIFF data. This * object may be passed to the * {@link TIFFImageWriteParam#setTIFFCompressor(TIFFCompressor)} * method to override the compressor of a supported compression type or * to provide the implementation of the compression algorithm of an * unsupported compression type. * *

The parameters compressionTagValue and * isCompressionLossless are provided to accomodate * compression types which are unknown. A compression type is * "known" if it is either among those already supported by the * TIFF writer (see {@link TIFFImageWriteParam}), or is listed in * the TIFF 6.0 specification but not supported. If the compression * type is unknown, the compressionTagValue and * isCompressionLossless parameters are ignored.

* * @param compressionType The name of the compression type. * @param compressionTagValue The value to be assigned to the TIFF * Compression tag in the TIFF image metadata; ignored if * compressionType is a known type. * @param isCompressionLossless Whether the compression is lossless; * ignored if compressionType is a known type. * * @throws IllegalArgumentException if compressionType is * null or compressionTagValue is less than * 1. */ public TIFFCompressor(String compressionType, int compressionTagValue, boolean isCompressionLossless) { if(compressionType == null) { throw new IllegalArgumentException("compressionType == null"); } else if(compressionTagValue < 1) { throw new IllegalArgumentException("compressionTagValue < 1"); } // Set the compression type. this.compressionType = compressionType; // Determine whether this type is either defined in the TIFF 6.0 // specification or is already supported. int compressionIndex = -1; String[] compressionTypes = TIFFImageWriter.compressionTypes; int len = compressionTypes.length; for(int i = 0; i < len; i++) { if(compressionTypes[i].equals(compressionType)) { // Save the index of the supported type. compressionIndex = i; break; } } if(compressionIndex != -1) { // Known compression type. this.compressionTagValue = TIFFImageWriter.compressionNumbers[compressionIndex]; this.isCompressionLossless = TIFFImageWriter.isCompressionLossless[compressionIndex]; } else { // Unknown compression type. this.compressionTagValue = compressionTagValue; this.isCompressionLossless = isCompressionLossless; } } /** * Retrieve the name of the compression type supported by this compressor. * * @return The compression type name. */ public String getCompressionType() { return compressionType; } /** * Retrieve the value to be assigned to the TIFF Compression tag * in the TIFF image metadata. * * @return The Compression tag value. */ public int getCompressionTagValue() { return compressionTagValue; } /** * Retrieves a value indicating whether the compression is lossless. * * @return Whether the compression is lossless. */ public boolean isCompressionLossless() { return isCompressionLossless; } /** * Sets the ImageOutputStream to be written. * * @param stream an ImageOutputStream to be written. * * @see #getStream */ public void setStream(ImageOutputStream stream) { this.stream = stream; } /** * Returns the ImageOutputStream that will be written. * * @return an ImageOutputStream. * * @see #setStream(ImageOutputStream) */ public ImageOutputStream getStream() { return stream; } /** * Sets the value of the writer field. * * @param writer the current ImageWriter. * * @see #getWriter() */ public void setWriter(ImageWriter writer) { this.writer = writer; } /** * Returns the current ImageWriter. * * @return an ImageWriter. * * @see #setWriter(ImageWriter) */ public ImageWriter getWriter() { return this.writer; } /** * Sets the value of the metadata field. * * @param metadata the IIOMetadata object for the * image being written. * * @see #getMetadata() */ public void setMetadata(IIOMetadata metadata) { this.metadata = metadata; } /** * Returns the current IIOMetadata object. * * @return the IIOMetadata object for the image being * written. * * @see #setMetadata(IIOMetadata) */ public IIOMetadata getMetadata() { return this.metadata; } /** * Encodes the supplied image data, writing to the currently set * ImageOutputStream. * * @param b an array of bytes containing the packed * but uncompressed image data. * @param off the starting offset of the data to be written in the * array b. * @param width the width of the rectangle of pixels to be written. * @param height the height of the rectangle of pixels to be written. * @param bitsPerSample an array of ints indicting * the number of bits used to represent each image sample within * a pixel. * @param scanlineStride the number of bytes separating each * row of the input data. * * @return the number of bytes written. * * @throws IOException if the supplied data cannot be encoded by * this TIFFCompressor, or if any I/O error occurs * during writing. */ public abstract int encode(byte[] b, int off, int width, int height, int[] bitsPerSample, int scanlineStride) throws IOException; } jai-imageio-core-1.2/src/share/classes/com/sun/media/imageio/plugins/tiff/package.html0000664000175100017510000012450210425510766027773 0ustar tilletille Package containing the public classes used by the TIFF plug-in for the Image I/O Framework.

Reading Images

Writing Images
Native Stream Metadata Format
Native Image Metadata Format

Reading Images

TIFF images are read by an {@link javax.imageio.ImageReader} which may be controlled by its public interface as well as via a supplied {@link com.sun.media.imageio.plugins.tiff.TIFFImageReadParam}.

Decompression

A {@link com.sun.media.imageio.plugins.tiff.TIFFDecompressor} object may be supplied via {@link com.sun.media.imageio.plugins.tiff.TIFFImageReadParam#setTIFFDecompressor TIFFImageReadParam.setTIFFDecompressor()}. If a {@link com.sun.media.imageio.plugins.tiff.TIFFDecompressor} is specified in this manner it will be used and will supersede any internal decompressor which might otherwise have been used for a known compression type. This mechanism allows for compression types to be handled by user-defined decompressors whether or not that compression type is known to the plug-in.

Color Conversion

A {@link com.sun.media.imageio.plugins.tiff.TIFFColorConverter} object may be supplied via {@link com.sun.media.imageio.plugins.tiff.TIFFImageReadParam#setColorConverter TIFFImageReadParam.setColorConverter()}. If a {@link com.sun.media.imageio.plugins.tiff.TIFFColorConverter} is specified in this manner it will be used and will supersede any internal color converter which might otherwise have been used. This color converter will be used to convert the source image data to an RGB color space.

If no user-supplied color converter is available, the source image data have photometric type CIE L*a*b* or YCbCr, and the destination color space type is RGB, then the source image data will be automatically converted to RGB using an internal color converter.

Color Spaces

The raw color space assigned by default, i.e., in the absence of a user-supplied {@link javax.imageio.ImageTypeSpecifier}, will be the first among the following which applies:

The normalized color coordinate transformations used for the default CMYK color space are defined as follows:

The generic color space used when no other color space can be inferred is provided merely to enable the data to be loaded. It is not intended to provide accurate conversions of any kind.

If the data are known to be in a color space not correctly handled by the foregoing, then an {@link javax.imageio.ImageTypeSpecifier} should be supplied to the reader and should be derived from a color space which is correct for the data in question.

ICC Profiles

If an ICC profile is contained in the image metadata ({@link com.sun.media.imageio.plugins.tiff.BaselineTIFFTagSet#TAG_ICC_PROFILE}, tag number 34675), an attempt will be made to use it to create the color space of the loaded image. It will be used if the data layout is of component type and the number of samples per pixel equals or is one greater than the number of components described by the ICC profile. If the ICC profile is not used then the color space will be inferred in one of the subsequent steps described above.

If for some reason the embedded ICC profile is not used automatically, then it may be used manually by following this procedure:

  1. Obtain the image metadata from {@link javax.imageio.ImageReader#getImageMetadata}
  2. Extract the ICC profile field and its value.
  3. Create an {@link java.awt.color.ICC_ColorSpace} from an {@link java.awt.color.ICC_Profile} created from the ICC profile field data using {@link java.awt.color.ICC_Profile#getInstance(byte[])}.
  4. Create an {@link javax.imageio.ImageTypeSpecifier} from the new color space using one of its factory methods which accepts an {@link java.awt.color.ICC_ColorSpace}.
  5. Create a compatible {@link javax.imageio.ImageReadParam} and set the {@link javax.imageio.ImageTypeSpecifier} using {@link javax.imageio.ImageReadParam#setDestinationType}.
  6. Pass the parameter object to the appropriate read method.

If the inferred color space not based on the ICC Profile field is compatible with the ICC profile-based color space, then a second {@link javax.imageio.ImageTypeSpecifier} derived from this inferred color space will be included in the {@link java.util.Iterator} returned by {@link javax.imageio.ImageReader#getImageTypes}. If the iterator contains more than one type, the first one will be based on the ICC profile and the second on the inferred color space.

Metadata Issues

By default all fields in the TIFF image file directory (IFD) are loaded into the native image metadata object. In cases where the IFD includes fields which contain large amounts of data this could be very inefficient. Which fields are loaded may be controlled by setting which TIFF tags the reader is allowed to recognize and whether it is ignoring metadata. The reader is informed to disregard metadata as usual via the ignoreMetadata parameter of {@link javax.imageio.ImageReader#setInput(Object,boolean,boolean) javax.imageio.ImageReader.setInput()}. It is informed of which {@link com.sun.media.imageio.plugins.tiff.TIFFTag}s to recognize or not to recognize via {@link com.sun.media.imageio.plugins.tiff.TIFFImageReadParam#addAllowedTagSet(TIFFTagSet) TIFFImageReadParam.addAllowedTagSet()} and {@link com.sun.media.imageio.plugins.tiff.TIFFImageReadParam#removeAllowedTagSet(TIFFTagSet) TIFFImageReadParam.removeAllowedTagSet()}. If ignoreMetadata is true, then the reader will load into the native image metadata object only those fields which have a TIFFTag contained in the one of the allowed TIFFTagSets.

Use of a {@link com.sun.media.imageio.plugins.tiff.TIFFDirectory} object may simplify gaining access to metadata values. An instance of TIFFDirectory may be created from the IIOMetadata object returned by the TIFF reader using the {@link com.sun.media.imageio.plugins.tiff.TIFFDirectory#createFromMetadata TIFFDirectory.createFromMetadata()} method.

Mapping of TIFF Native Image Metadata to the Standard Metadata Format
The derivation of standard metadata format javax_imageio_1.0 elements from TIFF native image metadata is given in the following table.

Standard Metadata Element Derivation from TIFF Fields
/Chroma/ColorSpaceType@name PhotometricInterpretation: WhiteIsZero, BlackIsZero, TransparencyMask = "GRAY"; RGB, PaletteColor => "RGB"; CMYK => "CMYK"; YCbCr => "YCbCr"; CIELab, ICCLab => "Lab".
/Chroma/NumChannels@value SamplesPerPixel
/Chroma/BlackIsZero@value "TRUE" <=> PhotometricInterpretation => WhiteIsZero
/Chroma/Palette ColorMap
/Compression/CompressionTypeName@value Compression: Uncompressed => "none"; CCITT 1D => "CCITT RLE"; Group 3 Fax => "CCITT T.4"; Group 4 Fax => "CCITT T.6"; LZW => "LZW"; JPEG => "Old JPEG"; New JPEG => "JPEG"; Zlib =>> "ZLib"; PackBits => "PackBits"; Deflate => "Deflate"; EXIF JPEG => "JPEG".
/Compression/Lossless@value Compression: JPEG or New JPEG => "FALSE"; otherwise "TRUE".
/Data/PlanarConfiguration@value Chunky => "PixelInterleaved"; Planar => "PlaneInterleaved".
/Data/SampleFormat@value PhotometricInterpretation PaletteColor => "Index"; SampleFormat unsigned integer data => "UnsignedIntegral"; SampleFormat two's complement signed integer data => "SignedIntegral"; SampleFormat IEEE floating point data => "Real"; otherwise element not emitted.
/Data/BitsPerSample@value BitsPerSample as a space-separated list.
/Data/SampleMSB@value FillOrder: left-to-right => space-separated list of BitsPerSample-1; right-to-left => space-separated list of 0s.
/Dimension/PixelAspectRatio@value (1/XResolution)/(1/YResolution)
/Dimension/ImageOrientation@value Orientation
/Dimension/HorizontalPixelSize@value 1/XResolution in millimeters if ResolutionUnit is not None.
/Dimension/VerticalPixelSize@value 1/YResolution in millimeters if ResolutionUnit is not None.
/Dimension/HorizontalPosition@value XPosition in millimeters if ResolutionUnit is not None.
/Dimension/VerticalPosition@value YPosition in millimeters if ResolutionUnit is not None.
/Document/FormatVersion@value 6.0
/Document/SubimageInterpretation@value NewSubFileType: transparency => "TransparencyMask"; reduced-resolution => "ReducedResolution"; single page => "SinglePage".
/Document/ImageCreationTime@value DateTime
/Text/TextEntry DocumentName, ImageDescription, Make, Model, PageName, Software, Artist, HostComputer, InkNames, Copyright: /Text/TextEntry@keyword = field name, /Text/TextEntry@value = field value.
Example: TIFF Software field => /Text/TextEntry@keyword = "Software", /Text/TextEntry@value = Name and version number of the software package(s) used to create the image.
/Transparency/Alpha@value ExtraSamples: associated alpha => "premultiplied"; unassociated alpha => "nonpremultiplied".

Reading EXIF Images

The TIFF reader may be used to read an uncompressed EXIF image or the contents of the APP1 marker segment of a compressed EXIF image.
Reading Uncompressed EXIF Images
An uncompressed EXIF image is a one- or two-page uncompressed TIFF image with a specific ordering of its IFD and image data content. Each pixel has three 8-bit samples with photometric interpretation RGB or YCbCr. The image stream must contain a single primary image and may contain a single thumbnail which if present must also be uncompressed. The usual {@link javax.imageio.ImageReader} methods may be used to read the image data and metadata:

ImageReader tiffReader;
ImageInputStream input;
ImageReadParam readParam;

tiffReader.setInput(input);

// Read primary image and IFD.
BufferedImage image = tiffReader.read(0, readParam);
IIOMetadata primaryIFD = tiffReader.getImageMetadata(0);

// Read thumbnail and IFD if present.
BufferedImage thumbnail = null;
IIOMetadata thumbnailIFD = null;
if(tiffReader.getNumImages(true) > 1) {
    thumbnail = tiffReader.read(1, readParam);
    thumbnailIFD = tiffReader.getImageMetadata(1);
}
Note that the EXIF thumbnail is treated as a separate page in the TIFF stream and not as a thumbnail, i.e., tiffReader.hasThumbnails(0) will return false.
Reading Compressed EXIF Images
A compressed EXIF image is a 3-band ISO/IEC 10918-1 baseline DCT JPEG stream with an inserted APP1 marker segment. The parameters of the marker segment after the length are the 6-byte sequence {'E', 'x', 'i', 'f', 0x00, 0x00} followed by a complete TIFF stream. The embedded TIFF stream contains a primary IFD describing the JPEG image optionally followed by a thumbnail IFD and compressed or uncompressed thumbnail image data. Note that the embedded TIFF stream does not contain any image data associated with the primary IFD nor any descriptive fields which duplicate information found in the JPEG stream itself.

The parameter content of the APP1 marker segment may be obtained from the user object of the associated Node in a javax_imageio_jpeg_image_1.0 native image metadata tree extracted from the image metadata object returned by the JPEG reader. This node will have name unknown and an attribute named MarkerTag with integral value 0xE1 (String value "225"). The primary IFD and the thumbnail IFD and image may be read from the user object by the usual {@link javax.imageio.ImageReader} methods:


ImageReader tiffReader;
ImageReadParam readParam;
IIOMetadataNode app1EXIFNode;

// Set up input skipping EXIF ID 6-byte sequence.
byte[] app1Params = (byte[])app1EXIFNode.getUserObject();
MemoryCacheImageInputStream app1EXIFInput =
    new MemoryCacheImageInputStream(new ByteArrayInputStream(app1Params, 6,
                                                             app1Params.length - 6));
tiffReader.setInput(app1EXIFInput);

// Read primary IFD.
IIOMetadata primaryIFD = tiffReader.getImageMetadata(0);

// Read thumbnail and IFD if present.
BufferedImage thumbnail = null;
IIOMetadata thumbnailIFD = null;
if(tiffReader.getNumImages(true) > 1) {
    thumbnail = tiffReader.read(1, readParam);
    thumbnailIFD = tiffReader.getImageMetadata(1);
}
Note that tiffReader.getNumImages(true) returns the number of IFDs in the embedded TIFF stream including those corresponding to empty images. Calling tiffReader.read(0, readParam) will throw an exception as the primary image in the embedded TIFF stream is always empty; the primary image should be obtained using the JPEG reader itself.

Writing Images

TIFF images are written by an {@link javax.imageio.ImageWriter} which may be controlled by its public interface as well as via a supplied {@link com.sun.media.imageio.plugins.tiff.TIFFImageWriteParam}. The TIFF writer supports many optional capabilities including writing tiled images, inserting images, writing or inserting empty images, and replacing image data. Pixels may be replaced in either empty or non-empty images but if and only if the data are not compressed.

Compression

A {@link com.sun.media.imageio.plugins.tiff.TIFFCompressor} object may be supplied via {@link com.sun.media.imageio.plugins.tiff.TIFFImageWriteParam#setTIFFCompressor TIFFImageWriteParam.setTIFFCompressor()}. If a {@link com.sun.media.imageio.plugins.tiff.TIFFCompressor} is specified in this manner it will be used and will supersede any internal compressor which might otherwise have been used for a known compression type. This mechanism allows for compression types to be handled by user-defined compressors whether or not that compression type is known to the plug-in.

Color Conversion

A {@link com.sun.media.imageio.plugins.tiff.TIFFColorConverter} object may be supplied via {@link com.sun.media.imageio.plugins.tiff.TIFFImageWriteParam#setColorConverter TIFFImageWriteParam.setColorConverter()}. If a {@link com.sun.media.imageio.plugins.tiff.TIFFColorConverter} is specified in this manner it will be used and will supersede any internal color converter which might otherwise have been used. This color converter will be used to convert from RGB to the color space of the output image.

If no user-supplied color converter is available, the source image data color space type is RGB, and the destination photometric type is CIE L*a*b* or YCbCr, then the source image data will be automatically converted from RGB using an internal color converter.

ICC Profiles

An ICC Profile field will be written if either:
  • one is present in the native image metadata {@link javax.imageio.metadata.IIOMetadata} instance supplied to the writer, or
  • the {@link java.awt.color.ColorSpace} of the destination ImageTypeSpecifier is an instance of {@link java.awt.color.ICC_ColorSpace} which is not one of the standard color spaces defined by the CS_* constants in the ColorSpace class. The destination type is set via {@link javax.imageio.ImageWriteParam#setDestinationType(ImageTypeSpecifier) ImageWriteParam.setDestinationType()} and defaults to the ImageTypeSpecifier of the image being written.

Metadata Issues

Some behavior of the writer is affected by or may affect the contents of the image metadata which may be supplied by the user.

For bilevel images, the FillOrder, and T4Options fields affect the output data. The data will be filled right-to-left if FillOrder is present with a value of 2 ({@link com.sun.media.imageio.plugins.tiff.BaselineTIFFTagSet#FILL_ORDER_RIGHT_TO_LEFT}) and will be filled left-to-right otherwise. The value of T4Options specifies whether the data should be 1D- or 2D-encoded and whether EOL padding should be used.

For all images the value of the RowsPerStrip field is used to the set the number of rows per strip if the image is not tiled. The default number of rows per strip is either 8 or the number of rows which would fill no more than 8 kilobytes, whichever is larger.

For all images the tile dimensions may be set using the TileWidth and TileLength field values if the tiling mode is {@link javax.imageio.ImageWriteParam#MODE_COPY_FROM_METADATA}. If this mode is set but the fields are not, their respective default values are the image width and height.

When using JPEG-in-TIFF compression, a JPEGTables field will be written to the IFD and abbreviated JPEG streams to each strip or tile if and only if a JPEGTables field is contained in the metadata object provided to the writer. If the contents of the JPEGTables field is a valid tables-only JPEG stream, then it will be used; otherwise the contents of the field will be replaced with default visually lossless tables. If no such JPEGTables field is present in the metadata, then no JPEGTables field will be written to the output and each strip or tile will be written as a separate, self-contained JPEG stream.

When using Deflate/ZLib or LZW compression, if the image has 8 bits per sample, a horizontal differencing predictor will be used if the Predictor field is present with a value of 2 ({@link com.sun.media.imageio.plugins.tiff.BaselineTIFFTagSet#PREDICTOR_HORIZONTAL_DIFFERENCING}). If prediction is so requested but the image does not have 8 bits per sample the field will be reset to have the value 1 ({@link com.sun.media.imageio.plugins.tiff.BaselineTIFFTagSet#PREDICTOR_NONE}).

Some fields may be added or modified:

  • PhotometricInterpretation if not present or if derived from a TIFFColorConverter.
  • PlanarConfiguration if this field is present with value Planar is is reset to Chunky.
  • Compression always.
  • BitsPerSample if the image is not bilevel.
  • SamplesPerPixel always.
  • ExtraSamples if an alpha channel is present.
  • SampleFormat if not present and the data are 16- or 32-bit integers or floating point.
  • ColorMap if the PhotometricInterpretation is RGBPalette.
  • ImageWidth and ImageLength always.
  • TileWidth, TileLength, TileOffsets, and TileByteCounts if a tiled image is being written.
  • RowsPerStrip, StripOffsets, and StripByteCounts if a tiled image is not being written.
  • XResolution, YResolution, and ResolutionUnit if none of these is present.
  • YCbCrSubsampling and YCbCrPositioning if the photometric interpretation is YCbCr and the compression type is not JPEG (only [1, 1] subsampling and cosited positioning are supported for non-JPEG YCbCr output).
  • YCbCrSubsampling, YCbCrPositioning, and ReferenceBlackWhite: if the compression type is JPEG and the color space is RGB these will be reset to [2, 2] centered subsampling with no headroom/footroom (0:255,128:255,128:255).

Some fields may be removed:

  • BitsPerSample if the image is bilevel.
  • ExtraSamples if the image does not have an alpha channel.
  • ColorMap if the photometric interpretation is not RGBPalette.
  • TileWidth, TileLength, TileOffsets, and TileByteCounts if tiling is not being used.
  • RowsPerStrip, StripOffsets, and StripByteCounts if tiling is being used.
  • YCbCrSubsampling, YCbCrPositioning, and ReferenceBlackWhite if the compression type is JPEG and the color space is grayscale.

Other fields present in the supplied metadata are uninterpreted and will be written as supplied.

If an EXIF image is being written, the set of fields present and their values will be modified such that the result is in accord with the EXIF 2.2 specification.

Setting up the image metadata to write to a TIFF stream may be simplified by using the {@link com.sun.media.imageio.plugins.tiff.TIFFDirectory} class which represents a TIFF IFD. A field in a TIFF IFD is represented by an instance of {@link com.sun.media.imageio.plugins.tiff.TIFFField}. For each field to be written a TIFFField may be added to the TIFFDirectory and the latter converted to an IIOMetadata object by invoking {@link com.sun.media.imageio.plugins.tiff.TIFFDirectory#getAsMetadata}. The IIOMetadata object so obtained may then be passed to the TIFF writer.

Mapping of the Standard Metadata Format to TIFF Native Image Metadata
The derivation of TIFF native image metadata elements from the standard metadata format javax_imageio_1.0 is given in the following table.

TIFF Field Derivation from Standard Metadata Elements
PhotometricInterpretation /Chroma/ColorSpaceType@name: "GRAY" and /Chroma/BlackIsZero@value = "FALSE" => WhiteIsZero; "GRAY" and /Document/SubimageInterpretation@value = "TransparencyMask" => TransparencyMask; "RGB" and /Chroma/Palette present => PaletteColor; "GRAY" => BlackIsZero; "RGB" => RGB; "YCbCr" => YCbCr; "CMYK" => CMYK; "Lab" => CIELab.
SamplesPerPixel /Chroma/NumChannels@value
ColorMap /Chroma/Palette
Compression /Compression/CompressionTypeName@value: "none" => Uncompressed; "CCITT RLE" => CCITT 1D; "CCITT T.4" => Group 3 Fax; "CCITT T.6" => Group 4 Fax; "LZW" => LZW; "Old JPEG" => JPEG; "JPEG" => New JPEG; "ZLib" => ZLib; "PackBits" => PackBits; "Deflate" => Deflate.
PlanarConfiguration /Data/PlanarConfiguration@value: "PixelInterleaved" => Chunky; "PlaneInterleaved" => Planar.
SampleFormat /Data/SampleFormat@value: "SignedIntegral" => two's complement signed integer data; "UnsignedIntegral" => unsigned integer data; "Real" => IEEE floating point data; "Index" => unsigned integer data.
BitsPerSample /Data/BitsPerSample@value: space-separated list parsed to char array.
FillOrder /Data/SampleMSB@value: if all values in space-separated list are 0s => right-to-left; otherwise => left-to-right.
XResolution (10 / /Dimension/HorizontalPixelSize@value) or (10 / (/Dimension/VerticalPixelSize@value * /Dimension/PixelAspectRatio@value))
YResolution (10 / /Dimension/VerticalPixelSize@value) or (10 / (/Dimension/HorizontalPixelSize@value / /Dimension/PixelAspectRatio@value))
ResolutionUnit Centimeter if XResolution or YResolution set; otherwise None.
Orientation /Dimension/ImageOrientation@value
XPosition /Dimension/HorizontalPosition@value / 10
YPosition /Dimension/VerticalPosition@value / 10
NewSubFileType /Document/SubimageInterpretation@value: "TransparencyMask" => transparency mask; "ReducedResolution" => reduced-resolution; "SinglePage" => single page.
DateTime /Document/ImageCreationTime@value
DocumentName, ImageDescription, Make, Model, PageName, Software, Artist, HostComputer, InkNames, Copyright /Text/TextEntry: if /Text/TextEntry@keyword is the name of any of the TIFF Fields, e.g., "Software", then the field is added with content /Text/TextEntry@value and count 1.
ExtraSamples /Transparency/Alpha@value: "premultiplied" => associated alpha, count 1; "nonpremultiplied" => unassociated alpha, count 1.

Writing EXIF Images

The TIFF writer may be used to write an uncompressed EXIF image or the contents of the APP1 marker segment of a compressed EXIF image.
Writing Uncompressed EXIF Images
When writing a sequence of images each image is normally recorded as {IFD, IFD Value, Image Data}. The EXIF specification requires that an uncompressed EXIF image be structured as follows:
  1. Image File Header
  2. Primary IFD
  3. Primary IFD Value
  4. Thumbnail IFD
  5. Thumbnail IFD Value
  6. Thumbnail Image Data
  7. Primary Image Data
To meet the requirement of the primary image data being recorded last, the primary image must be written initially as an empty image and have its data added via pixel replacement after the thumbnail IFD and image data have been written:

ImageWriter tiffWriter;
ImageOutputStream output;
ImageWriteParam writeParam;

IIOMetadata streamMetadata;
BufferedImage image;
BufferedImage thumbnail;
IIOMetadata primaryIFD;
IIOMetadata thumbnailIFD;

tiffWriter.setOutput(output);
if(thumbnail != null) {
    // Write the TIFF header.
    tiffWriter.prepareWriteSequence(streamMetadata);

    // Append the primary IFD.
    tiffWriter.prepareInsertEmpty(-1, // append
                                  new ImageTypeSpecifier(image),
                                  image.getWidth(),
                                  image.getHeight(),
                                  primaryIFD,
                                  null, // thumbnails
                                  writeParam);
    tiffWriter.endInsertEmpty();

    // Append the thumbnail IFD and image data.
    tiffWriter.writeToSequence(new IIOImage(thumbnail, null, null),
                               writeParam);

    // Append the primary image data.
    tiffWriter.prepareReplacePixels(0, new Rectangle(image.getWidth(),
                                                     image.getHeight()));
    tiffWriter.replacePixels(image, writeParam);
    tiffWriter.endReplacePixels();

    // End writing.
    tiffWriter.endWriteSequence();
} else {
    // Write only the primary IFD and image data.
    tiffWriter.write(streamMetadata,
                     new IIOImage(image, null, primaryIFD),
                     writeParam);
}
Writing Compressed EXIF Images
The structure of the embedded TIFF stream in the APP1 segment of a compressed EXIF image is identical to the uncompressed EXIF image structure except that there are no primary image data, i.e., the primary IFD does not refer to any image data.

ImageWriter tiffWriter;
ImageWriteParam writeParam;
boolean isThumbnailCompressed;

IIOMetadata streamMetadata;
BufferedImage image;
BufferedImage thumbnail;
IIOMetadata primaryIFD;
IIOMetadata thumbnailIFD;

// Set up the output.
ByteArrayOutputStream baos = new ByteArrayOutputStream();
MemoryCacheImageOutputStream app1EXIFOutput = new MemoryCacheImageOutputStream(baos);
tiffWriter.setOutput(app1EXIFOutput);

// Set compression.
writeParam.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
writeParam.setCompressionType("EXIF JPEG");

if(thumbnail != null) {
    // Write the TIFF header.
    tiffWriter.prepareWriteSequence(streamMetadata);

    // Append the primary IFD.
    tiffWriter.prepareInsertEmpty(-1,  // append
                                  new ImageTypeSpecifier(image),
                                  image.getWidth(),
                                  image.getHeight(),
                                  primaryIFD,
                                  null, // thumbnails
                                  writeParam);
    tiffWriter.endInsertEmpty();

    // Change compression type if uncompressed.
    if(!isThumbnailCompressed) {
        writeParam.setCompressionMode(ImageWriteParam.MODE_DISABLED);
    }

    // Append the thumbnail IFD and image data.
    tiffWriter.writeToSequence(new IIOImage(thumbnail, null,
                                            thumbnailIFD),
                               writeParam);

    // End writing.
    tiffWriter.endWriteSequence();
} else {
    // Write only the primary IFD.
    tiffWriter.prepareWriteEmpty(streamMetadata,
                                 new ImageTypeSpecifier(image),
                                 image.getWidth(),
                                 image.getHeight(),
                                 primaryIFD,
                                 null, // thumbnails
                                 writeParam);
    tiffWriter.endWriteEmpty();
}

// Flush data into byte stream.
app1EXIFOutput.flush();

// Create APP1 parameter array.
byte[] app1Parameters = new byte[6 + baos.size()];

// Add EXIF APP1 ID bytes.
app1Parameters[0] = (byte)'E';
app1Parameters[1] = (byte)'x';
app1Parameters[2] = (byte)'i';
app1Parameters[3] = (byte)'f';
app1Parameters[4] = app1Parameters[5] = (byte)0;

// Append TIFF stream to APP1 parameters.
System.arraycopy(baos.toByteArray(), 0, app1Parameters, 6, baos.size());

// Create the APP1 EXIF node to be added to native JPEG image metadata.
IIOMetadataNode app1Node = new IIOMetadataNode("unknown");
app1Node.setAttribute("MarkerTag", (new Integer(0xE1)).toString());
app1Node.setUserObject(app1Parameters);
The "unknown" node created above would be appended to the "markerSequence" node of the native JPEG image metadata and written to the JPEG stream when the primary image is written using the JPEG writer.

Stream Metadata

The DTD for the stream metadata format is as follows:
<!DOCTYPE "com_sun_media_imageio_plugins_tiff_stream_1.0" [

  <!ELEMENT "com_sun_media_imageio_plugins_tiff_stream_1.0" (ByteOrder)>

    <!ELEMENT "ByteOrder" EMPTY>
      <!-- The stream byte order --> 
      <!ATTLIST "ByteOrder" "value" #CDATA #REQUIRED>
        <!-- One of "BIG_ENDIAN" or "LITTLE_ENDIAN" --> 
        <!-- Data type: String -->
]>

Image Metadata

The DTD for the native image metadata format is as follows:
<!DOCTYPE "com_sun_media_imageio_plugins_tiff_image_1.0" [

  <!ELEMENT "com_sun_media_imageio_plugins_tiff_image_1.0" (TIFFIFD)*>

    <!ELEMENT "TIFFIFD" (TIFFField | TIFFIFD)*>
      <!-- An IFD (directory) containing fields --> 
      <!ATTLIST "TIFFIFD" "tagSets" #CDATA #REQUIRED>
        <!-- Data type: String -->
      <!ATTLIST "TIFFIFD" "parentTagNumber" #CDATA #IMPLIED>
        <!-- The tag number of the field pointing to this IFD --> 
        <!-- Data type: Integer -->
      <!ATTLIST "TIFFIFD" "parentTagName" #CDATA #IMPLIED>
        <!-- A mnemonic name for the field pointing to this IFD, if known 
             --> 
        <!-- Data type: String -->

      <!ELEMENT "TIFFField" (TIFFBytes | TIFFAsciis |
        TIFFShorts | TIFFSShorts | TIFFLongs | TIFFSLongs |
        TIFFRationals | TIFFSRationals |
        TIFFFloats | TIFFDoubles | TIFFUndefined)>
        <!-- A field containing data --> 
        <!ATTLIST "TIFFField" "number" #CDATA #REQUIRED>
          <!-- The tag number asociated with the field --> 
          <!-- Data type: String -->
        <!ATTLIST "TIFFField" "name" #CDATA #IMPLIED>
          <!-- A mnemonic name associated with the field, if known --> 
          <!-- Data type: String -->

        <!ELEMENT "TIFFBytes" (TIFFByte)*>
          <!-- A sequence of TIFFByte nodes --> 

          <!ELEMENT "TIFFByte" EMPTY>
            <!-- An integral value between 0 and 255 --> 
            <!ATTLIST "TIFFByte" "value" #CDATA #IMPLIED>
              <!-- The value --> 
              <!-- Data type: String -->
            <!ATTLIST "TIFFByte" "description" #CDATA #IMPLIED>
              <!-- A description, if available --> 
              <!-- Data type: String -->

        <!ELEMENT "TIFFAsciis" (TIFFAscii)*>
          <!-- A sequence of TIFFAscii nodes --> 

          <!ELEMENT "TIFFAscii" EMPTY>
            <!-- A String value --> 
            <!ATTLIST "TIFFAscii" "value" #CDATA #IMPLIED>
              <!-- The value --> 
              <!-- Data type: String -->

        <!ELEMENT "TIFFShorts" (TIFFShort)*>
          <!-- A sequence of TIFFShort nodes --> 

          <!ELEMENT "TIFFShort" EMPTY>
            <!-- An integral value between 0 and 65535 --> 
            <!ATTLIST "TIFFShort" "value" #CDATA #IMPLIED>
              <!-- The value --> 
              <!-- Data type: String -->
            <!ATTLIST "TIFFShort" "description" #CDATA #IMPLIED>
              <!-- A description, if available --> 
              <!-- Data type: String -->

        <!ELEMENT "TIFFSShorts" (TIFFSShort)*>
          <!-- A sequence of TIFFSShort nodes --> 

          <!ELEMENT "TIFFSShort" EMPTY>
            <!-- An integral value between -32768 and 32767 --> 
            <!ATTLIST "TIFFSShort" "value" #CDATA #IMPLIED>
              <!-- The value --> 
              <!-- Data type: String -->
            <!ATTLIST "TIFFSShort" "description" #CDATA #IMPLIED>
              <!-- A description, if available --> 
              <!-- Data type: String -->

        <!ELEMENT "TIFFLongs" (TIFFLong)*>
          <!-- A sequence of TIFFLong nodes --> 

          <!ELEMENT "TIFFLong" EMPTY>
            <!-- An integral value between 0 and 4294967295 --> 
            <!ATTLIST "TIFFLong" "value" #CDATA #IMPLIED>
              <!-- The value --> 
              <!-- Data type: String -->
            <!ATTLIST "TIFFLong" "description" #CDATA #IMPLIED>
              <!-- A description, if available --> 
              <!-- Data type: String -->

        <!ELEMENT "TIFFSLongs" (TIFFSLong)*>
          <!-- A sequence of TIFFSLong nodes --> 

          <!ELEMENT "TIFFSLong" EMPTY>
            <!-- An integral value between -2147483648 and 2147482647 --> 
            <!ATTLIST "TIFFSLong" "value" #CDATA #IMPLIED>
              <!-- The value --> 
              <!-- Data type: String -->
            <!ATTLIST "TIFFSLong" "description" #CDATA #IMPLIED>
              <!-- A description, if available --> 
              <!-- Data type: String -->

        <!ELEMENT "TIFFRationals" (TIFFRational)*>
          <!-- A sequence of TIFFRational nodes --> 

          <!ELEMENT "TIFFRational" EMPTY>
            <!-- A rational value consisting of an unsigned numerator and 
                 denominator --> 
            <!ATTLIST "TIFFRational" "value" #CDATA #IMPLIED>
              <!-- The numerator and denominator, separated by a slash --> 
              <!-- Data type: String -->

        <!ELEMENT "TIFFSRationals" (TIFFSRational)*>
          <!-- A sequence of TIFFSRational nodes --> 

          <!ELEMENT "TIFFSRational" EMPTY>
            <!-- A rational value consisting of a signed numerator and 
                 denominator --> 
            <!ATTLIST "TIFFSRational" "value" #CDATA #IMPLIED>
              <!-- The numerator and denominator, separated by a slash --> 
              <!-- Data type: String -->

        <!ELEMENT "TIFFFloats" (TIFFFloat)*>
          <!-- A sequence of TIFFFloat nodes --> 

          <!ELEMENT "TIFFFloat" EMPTY>
            <!-- A single-precision floating-point value --> 
            <!ATTLIST "TIFFFloat" "value" #CDATA #IMPLIED>
              <!-- The value --> 
              <!-- Data type: String -->

        <!ELEMENT "TIFFDoubles" (TIFFDouble)*>
          <!-- A sequence of TIFFDouble nodes --> 

          <!ELEMENT "TIFFDouble" EMPTY>
            <!-- A double-precision floating-point value --> 
            <!ATTLIST "TIFFDouble" "value" #CDATA #IMPLIED>
              <!-- The value --> 
              <!-- Data type: String -->

        <!ELEMENT "TIFFUndefined" EMPTY>
          <!-- Uninterpreted byte data --> 
          <!ATTLIST "TIFFUndefined" "value" #CDATA #IMPLIED>
            <!-- A list of comma-separated byte values --> 
            <!-- Data type: String -->
]>
@since 1.0 jai-imageio-core-1.2/src/share/classes/com/sun/media/imageio/plugins/tiff/TIFFImageWriteParam.java0000664000175100017510000003454110424264607032046 0ustar tilletille/* * $RCSfile: TIFFImageWriteParam.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.3 $ * $Date: 2006-04-28 01:01:59 $ * $State: Exp $ */ package com.sun.media.imageio.plugins.tiff; import java.util.Arrays; import java.util.List; import java.util.Locale; import javax.imageio.ImageWriteParam; import com.sun.media.imageioimpl.plugins.tiff.TIFFImageWriter; /** * A subclass of {@link ImageWriteParam ImageWriteParam} * allowing control over the TIFF writing process. The set of innately * supported compression types is listed in the following table: * *

* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
Supported Compression Types
Compression Type Description Reference
CCITT RLEModified Huffman compressionTIFF 6.0 Specification, Section 10
CCITT T.4CCITT T.4 bilevel encoding/Group 3 facsimile compressionTIFF 6.0 Specification, Section 11
CCITT T.6CCITT T.6 bilevel encoding/Group 4 facsimile compressionTIFF 6.0 Specification, Section 11
LZWLZW compressionTIFF 6.0 Specification, Section 13
JPEG"New" JPEG-in-TIFF compressionTIFF * Technical Note #2
ZLib"Deflate/Inflate" compression (see note following this table) * Adobe Photoshop® TIFF Technical Notes (PDF)
PackBitsByte-oriented, run length compressionTIFF 6.0 Specification, Section 9
Deflate"Zip-in-TIFF" compression (see note following this table) * ZLIB Compressed Data Format Specification, * * DEFLATE Compressed Data Format Specification
EXIF JPEGEXIF-specific JPEG compression (see note following this table)EXIF 2.2 Specification * (PDF), section 4.5.5, "Basic Structure of Thumbnail Data"
*

*

* Old-style JPEG compression as described in section 22 of the TIFF 6.0 * Specification is not supported. *

* *

The CCITT compression types are applicable to bilevel (1-bit) * images only. The JPEG compression type is applicable to byte * grayscale (1-band) and RGB (3-band) images only.

* *

* ZLib and Deflate compression are identical except for the value of the * TIFF Compression field: for ZLib the Compression field has value 8 * whereas for Deflate it has value 32946 (0x80b2). In both cases each * image segment (strip or tile) is written as a single complete zlib data * stream. *

* *

* "EXIF JPEG" is a compression type used when writing the contents of an * APP1 EXIF marker segment for inclusion in a JPEG native image metadata * tree. The contents appended to the output when this compression type is * used are a function of whether an empty or non-empty image is written. * If the image is empty, then a TIFF IFD adhering to the specification of * a compressed EXIF primary IFD is appended. If the image is non-empty, * then a complete IFD and image adhering to the specification of a * compressed EXIF thumbnail IFD and image are appended. Note that the * data of the empty image may not later be appended using the pixel * replacement capability of the TIFF writer. *

* *

If ZLib/Deflate or JPEG compression is used, the compression quality * may be set. For ZLib/Deflate the supplied floating point quality value is * rescaled to the range [1, 9] and truncated to an integer * to derive the Deflate compression level. For JPEG the floating point * quality value is passed directly to the JPEG writer plug-in which * interprets it in the usual way.

* *

The canWriteTiles and * canWriteCompressed methods will return * true; the canOffsetTiles and * canWriteProgressive methods will return * false.

* *

If tiles are being written, then each of their dimensions will be * rounded to the nearest multiple of 16 per the TIFF specification. If * JPEG-in-TIFF compression is being used, and tiles are being written * each tile dimension will be rounded to the nearest multiple of 8 times * the JPEG minimum coded unit (MCU) in that dimension. If JPEG-in-TIFF * compression is being used and strips are being written, the number of * rows per strip is rounded to a multiple of 8 times the maximum MCU over * both dimensions.

*/ public class TIFFImageWriteParam extends ImageWriteParam { TIFFCompressor compressor = null; TIFFColorConverter colorConverter = null; int photometricInterpretation; private boolean appendedCompressionType = false; /** * Constructs a TIFFImageWriteParam instance * for a given Locale. * * @param locale the Locale for which messages * should be localized. */ public TIFFImageWriteParam(Locale locale) { super(locale); this.canWriteCompressed = true; this.canWriteTiles = true; this.compressionTypes = TIFFImageWriter.TIFFCompressionTypes; }; public boolean isCompressionLossless() { if (getCompressionMode() != MODE_EXPLICIT) { throw new IllegalStateException ("Compression mode not MODE_EXPLICIT!"); } if (compressionType == null) { throw new IllegalStateException("No compression type set!"); } if(compressor != null && compressionType.equals(compressor.getCompressionType())) { return compressor.isCompressionLossless(); } for (int i = 0; i < compressionTypes.length; i++) { if (compressionType.equals(compressionTypes[i])) { return TIFFImageWriter.isCompressionLossless[i]; } } return false; } /** * Sets the TIFFCompressor object to be used by the * ImageWriter to encode each image strip or tile. * A value of null allows the writer to choose its * own TIFFCompressor. * *

Note that invoking this method is not sufficient to set * the compression type: * {@link ImageWriteParam#setCompressionType(String) setCompressionType()} * must be invoked explicitly for this purpose. The following * code illustrates the correct procedure: *

     * TIFFImageWriteParam writeParam;
     * TIFFCompressor compressor;
     * writeParam.setCompressionMode(writeParam.MODE_EXPLICIT);
     * writeParam.setTIFFCompressor(compressor);
     * writeParam.setCompressionType(compressor.getCompressionType());
     * 
* If compressionType is set to a value different from * that supported by the TIFFCompressor then the * compressor object will not be used. *

* *

If the compression type supported by the supplied * TIFFCompressor is not among those in * {@link ImageWriteParam#compressionTypes compressionTypes}, * then it will be appended to this array after removing any previously * appended compression type. If compressor is * null this will also cause any previously appended * type to be removed from the array.

* * @param compressor the TIFFCompressor to be * used for encoding, or null to allow the writer to * choose its own. * * @throws IllegalStateException if the compression mode is not * MODE_EXPLICIT. * * @see #getTIFFCompressor */ public void setTIFFCompressor(TIFFCompressor compressor) { if (getCompressionMode() != MODE_EXPLICIT) { throw new IllegalStateException ("Compression mode not MODE_EXPLICIT!"); } this.compressor = compressor; if(appendedCompressionType) { // Remove previously appended compression type. int len = compressionTypes.length - 1; String[] types = new String[len]; System.arraycopy(compressionTypes, 0, types, 0, len); compressionTypes = types; appendedCompressionType = false; } if(compressor != null) { // Check whether compressor's type is already in the list. String compressorType = compressor.getCompressionType(); int len = compressionTypes.length; boolean appendCompressionType = true; for(int i = 0; i < len; i++) { if(compressorType.equals(compressionTypes[i])) { appendCompressionType = false; break; } } if(appendCompressionType) { // Compressor's compression type not in the list; append it. String[] types = new String[len + 1]; System.arraycopy(compressionTypes, 0, types, 0, len); types[len] = compressorType; compressionTypes = types; appendedCompressionType = true; } } } /** * Returns the TIFFCompressor that is currently set * to be used by the ImageWriter to encode each image * strip or tile, or null if none has been set. * * @return compressor the TIFFCompressor to be * used for encoding, or null if none has been set * (allowing the writer to choose its own). * * @throws IllegalStateException if the compression mode is not * MODE_EXPLICIT. * * @see #setTIFFCompressor(TIFFCompressor) */ public TIFFCompressor getTIFFCompressor() { if (getCompressionMode() != MODE_EXPLICIT) { throw new IllegalStateException ("Compression mode not MODE_EXPLICIT!"); } return this.compressor; } /** * Sets the TIFFColorConverter object describing the * color space to which the input data should be converted for * storage in the input stream. In addition, the value to be * written to the PhotometricInterpretation tag is * supplied. * * @param colorConverter a TIFFColorConverter object, * or null. * @param photometricInterpretation the value to be written to the * PhotometricInterpretation tag in the root IFD. * * @see #getColorConverter * @see #getPhotometricInterpretation */ public void setColorConverter(TIFFColorConverter colorConverter, int photometricInterpretation) { this.colorConverter = colorConverter; this.photometricInterpretation = photometricInterpretation; } /** * Returns the current TIFFColorConverter object that * will be used to perform color conversion when writing the * image, or null if none is set. * * @return a TIFFColorConverter object, or * null. * * @see #setColorConverter(TIFFColorConverter, int) */ public TIFFColorConverter getColorConverter() { return colorConverter; } /** * Returns the current value that will be written to the * Photometricinterpretation tag. This method should * only be called if a value has been set using the * setColorConverter method. * * @return an int to be used as the value of the * PhotometricInterpretation tag. * * @see #setColorConverter(TIFFColorConverter, int) * * @throws IllegalStateException if no value is set. */ public int getPhotometricInterpretation() { if (colorConverter == null) { throw new IllegalStateException("Color converter not set!"); } return photometricInterpretation; } /** * Removes any currently set ColorConverter object and * PhotometricInterpretation tag value. * * @see #setColorConverter(TIFFColorConverter, int) */ public void unsetColorConverter() { this.colorConverter = null; } } jai-imageio-core-1.2/src/share/classes/com/sun/media/imageio/plugins/tiff/GeoTIFFTagSet.java0000664000175100017510000001337710203036165030645 0ustar tilletille/* * $RCSfile: GeoTIFFTagSet.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.1 $ * $Date: 2005-02-11 05:01:17 $ * $State: Exp $ */ package com.sun.media.imageio.plugins.tiff; import java.util.ArrayList; import java.util.List; /** * A class representing the tags found in a GeoTIFF IFD. GeoTIFF is a * standard for annotating georeferenced or geocoded raster imagery. * The GeoTIFF specification may be found at
* http://www.remotesensing.org/geotiff/spec/geotiffhome.html * . This class does not handle the GeoKeys referenced * from a GeoKeyDirectoryTag as those are not TIFF tags per se. * *

The definitions of the data types referenced by the field * definitions may be found in the {@link TIFFTag * TIFFTag} class.

*/ public class GeoTIFFTagSet extends TIFFTagSet { private static GeoTIFFTagSet theInstance = null; /** * A tag used to specify the size of raster pixel spacing in * model space units. */ public static final int TAG_MODEL_PIXEL_SCALE = 33550; /** * A tag used to specify the transformation matrix between the raster * space and the model space. */ public static final int TAG_MODEL_TRANSFORMATION = 34264; /** A tag used to store raster->model tiepoint pairs. */ public static final int TAG_MODEL_TIE_POINT = 33922; /** A tag used to store the GeoKey directory. */ public static final int TAG_GEO_KEY_DIRECTORY = 34735; /** A tag used to store all double-values GeoKeys. */ public static final int TAG_GEO_DOUBLE_PARAMS = 34736; /** A tag used to store all ASCII-values GeoKeys. */ public static final int TAG_GEO_ASCII_PARAMS = 34737; // GeoTIFF tags static class ModelPixelScale extends TIFFTag { public ModelPixelScale() { super("ModelPixelScaleTag", TAG_MODEL_PIXEL_SCALE, 1 << TIFFTag.TIFF_DOUBLE); } } static class ModelTransformation extends TIFFTag { public ModelTransformation() { super("ModelTransformationTag", TAG_MODEL_TRANSFORMATION, 1 << TIFFTag.TIFF_DOUBLE); } } static class ModelTiePoint extends TIFFTag { public ModelTiePoint() { super("ModelTiePointTag", TAG_MODEL_TIE_POINT, 1 << TIFFTag.TIFF_DOUBLE); } } static class GeoKeyDirectory extends TIFFTag { public GeoKeyDirectory() { super("GeoKeyDirectory", TAG_GEO_KEY_DIRECTORY, 1 << TIFFTag.TIFF_SHORT); } } static class GeoDoubleParams extends TIFFTag { public GeoDoubleParams() { super("GeoDoubleParams", TAG_GEO_DOUBLE_PARAMS, 1 << TIFFTag.TIFF_DOUBLE); } } static class GeoAsciiParams extends TIFFTag { public GeoAsciiParams() { super("GeoAsciiParams", TAG_GEO_ASCII_PARAMS, 1 << TIFFTag.TIFF_ASCII); } } private static List tags; private static void initTags() { tags = new ArrayList(42); tags.add(new GeoTIFFTagSet.ModelPixelScale()); tags.add(new GeoTIFFTagSet.ModelTransformation()); tags.add(new GeoTIFFTagSet.ModelTiePoint()); tags.add(new GeoTIFFTagSet.GeoKeyDirectory()); tags.add(new GeoTIFFTagSet.GeoDoubleParams()); tags.add(new GeoTIFFTagSet.GeoAsciiParams()); } private GeoTIFFTagSet() { super(tags); } /** * Returns a shared instance of a GeoTIFFTagSet. * * @return a GeoTIFFTagSet instance. */ public synchronized static GeoTIFFTagSet getInstance() { if (theInstance == null) { initTags(); theInstance = new GeoTIFFTagSet(); tags = null; } return theInstance; } } jai-imageio-core-1.2/src/share/classes/com/sun/media/imageio/plugins/tiff/EXIFTIFFTagSet.java0000664000175100017510000016354210330454115030666 0ustar tilletille/* * $RCSfile: EXIFTIFFTagSet.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.4 $ * $Date: 2005-10-28 16:56:45 $ * $State: Exp $ */ package com.sun.media.imageio.plugins.tiff; import java.util.ArrayList; import java.util.List; /** * A class representing the tags found in an EXIF IFD. EXIF is a * standard for annotating images used by most digital camera * manufacturers. The EXIF specification may be found at * * http://www.exif.org/Exif2-2.PDF * . * *

The definitions of the data types referenced by the field * definitions may be found in the {@link TIFFTag * TIFFTag} class. */ public class EXIFTIFFTagSet extends TIFFTagSet { private static EXIFTIFFTagSet theInstance = null; /** * A tag pointing to a GPS info IFD (type LONG). * * @deprecated Superseded by * {@link EXIFParentTIFFTagSet#TAG_GPS_INFO_IFD_POINTER} */ public static final int TAG_GPS_INFO_IFD_POINTER = 34853; /** A tag pointing to an interoperability IFD (type LONG). */ public static final int TAG_INTEROPERABILITY_IFD_POINTER = 40965; /** * A tag containing the EXIF version number (type UNDEFINED, count = * 4). Conformance to the EXIF 2.1 standard is indicated using * the ASCII value "0210" (with no terminating NUL). * * @see #EXIF_VERSION_2_1 * @see #EXIF_VERSION_2_2 */ public static final int TAG_EXIF_VERSION = 36864; /** * An array of bytes containing the values {'0', '2', '1', * '0'} to be used with the "EXIFVersion" tag to indicate * EXIF version 2.1. * * @see #TAG_EXIF_VERSION */ public static byte[] EXIF_VERSION_2_1 = { '0', '2', '1', '0' }; /** * An array of bytes containing the values {'0', '2', '2', * '0'} to be used with the "EXIFVersion" tag to indicate * EXIF version 2.2. * * @see #TAG_EXIF_VERSION */ public static byte[] EXIF_VERSION_2_2 = { '0', '2', '2', '0' }; /** * A tag indicating the FlashPix version number (type UNDEFINED, * count = 4). */ public static final int TAG_FLASHPIX_VERSION = 40960; /** * A tag indicating the color space information (type SHORT). The * legal values are given by the COLOR_SPACE_* * constants. * * @see #COLOR_SPACE_SRGB * @see #COLOR_SPACE_UNCALIBRATED */ public static final int TAG_COLOR_SPACE = 40961; /** * A value to be used with the "ColorSpace" tag. * * @see #TAG_COLOR_SPACE */ public static final int COLOR_SPACE_SRGB = 1; /** * A value to be used with the "ColorSpace" tag. * * @see #TAG_COLOR_SPACE */ public static final int COLOR_SPACE_UNCALIBRATED = 0xFFFF; /** * A tag containing the components configuration information (type * UNDEFINED, count = 4). * * @see #COMPONENTS_CONFIGURATION_DOES_NOT_EXIST * @see #COMPONENTS_CONFIGURATION_Y * @see #COMPONENTS_CONFIGURATION_CB * @see #COMPONENTS_CONFIGURATION_CR * @see #COMPONENTS_CONFIGURATION_R * @see #COMPONENTS_CONFIGURATION_G * @see #COMPONENTS_CONFIGURATION_B */ public static final int TAG_COMPONENTS_CONFIGURATION = 37121; /** * A value to be used with the "ComponentsConfiguration" tag. * * @see #TAG_COMPONENTS_CONFIGURATION */ public static final int COMPONENTS_CONFIGURATION_DOES_NOT_EXIST = 0; /** * A value to be used with the "ComponentsConfiguration" tag. * * @see #TAG_COMPONENTS_CONFIGURATION */ public static final int COMPONENTS_CONFIGURATION_Y = 1; /** * A value to be used with the "ComponentsConfiguration" tag. * * @see #TAG_COMPONENTS_CONFIGURATION */ public static final int COMPONENTS_CONFIGURATION_CB = 2; /** * A value to be used with the "ComponentsConfiguration" tag. * * @see #TAG_COMPONENTS_CONFIGURATION */ public static final int COMPONENTS_CONFIGURATION_CR = 3; /** * A value to be used with the "ComponentsConfiguration" tag. * * @see #TAG_COMPONENTS_CONFIGURATION */ public static final int COMPONENTS_CONFIGURATION_R = 4; /** * A value to be used with the "ComponentsConfiguration" tag. * * @see #TAG_COMPONENTS_CONFIGURATION */ public static final int COMPONENTS_CONFIGURATION_G = 5; /** * A value to be used with the "ComponentsConfiguration" tag. * * @see #TAG_COMPONENTS_CONFIGURATION */ public static final int COMPONENTS_CONFIGURATION_B = 6; /** * A tag indicating the number of compressed bits per pixel * (type RATIONAL). */ public static final int TAG_COMPRESSED_BITS_PER_PIXEL = 37122; /** * A tag indicating the pixel X dimension (type SHORT or LONG). * This value records the valid width of the meaningful image for * a compressed file, whether or not there is padding or a restart * marker. */ public static final int TAG_PIXEL_X_DIMENSION = 40962; /** * A tag indicating the pixel Y dimension (type SHORT or LONG). * This value records the valid height of the meaningful image for * a compressed file, whether or not there is padding or a restart * marker. */ public static final int TAG_PIXEL_Y_DIMENSION = 40963; /** * A tag indicating a manufacturer-defined maker note (type * UNDEFINED). */ public static final int TAG_MAKER_NOTE = 37500; /** * A tag indicating a manufacturer-defined marker note (type * UNDEFINED). * * @deprecated Superseded by {@link #TAG_MAKER_NOTE}. */ public static final int TAG_MARKER_NOTE = TAG_MAKER_NOTE; /** * A tag indicating a user comment (type UNDEFINED). The first 8 * bytes are used to specify the character encoding. */ public static final int TAG_USER_COMMENT = 37510; /** * A tag indicating the name of a related sound file (type ASCII). */ public static final int TAG_RELATED_SOUND_FILE = 40964; /** * A tag indicating the date and time when the original image was * generated (type ASCII). */ public static final int TAG_DATE_TIME_ORIGINAL = 36867; /** * A tag indicating the date and time when the image was stored as * digital data (type ASCII). */ public static final int TAG_DATE_TIME_DIGITIZED = 36868; /** * A tag used to record fractions of seconds for the "DateTime" tag * (type ASCII). */ public static final int TAG_SUB_SEC_TIME = 37520; /** * A tag used to record fractions of seconds for the * "DateTimeOriginal" tag (type ASCII). */ public static final int TAG_SUB_SEC_TIME_ORIGINAL = 37521; /** * A tag used to record fractions of seconds for the * "DateTimeDigitized" tag (type ASCII). */ public static final int TAG_SUB_SEC_TIME_DIGITIZED = 37522; /** * A tag indicating the exposure time, in seconds (type RATIONAL). */ public static final int TAG_EXPOSURE_TIME = 33434; /** * A tag indicating the F number (type RATIONAL). */ public static final int TAG_F_NUMBER = 33437; /** * A tag indicating the class of the programs used to set exposure * when the picture was taken (type SHORT). * * @see #EXPOSURE_PROGRAM_NOT_DEFINED * @see #EXPOSURE_PROGRAM_MANUAL * @see #EXPOSURE_PROGRAM_NORMAL_PROGRAM * @see #EXPOSURE_PROGRAM_APERTURE_PRIORITY * @see #EXPOSURE_PROGRAM_SHUTTER_PRIORITY * @see #EXPOSURE_PROGRAM_CREATIVE_PROGRAM * @see #EXPOSURE_PROGRAM_ACTION_PROGRAM * @see #EXPOSURE_PROGRAM_PORTRAIT_MODE * @see #EXPOSURE_PROGRAM_LANDSCAPE_MODE * @see #EXPOSURE_PROGRAM_MAX_RESERVED */ public static final int TAG_EXPOSURE_PROGRAM = 34850; /** * A value to be used with the "ExposureProgram" tag. * * @see #TAG_EXPOSURE_PROGRAM */ public static final int EXPOSURE_PROGRAM_NOT_DEFINED = 0; /** * A value to be used with the "ExposureProgram" tag. * * @see #TAG_EXPOSURE_PROGRAM */ public static final int EXPOSURE_PROGRAM_MANUAL = 1; /** * A value to be used with the "ExposureProgram" tag. * * @see #TAG_EXPOSURE_PROGRAM */ public static final int EXPOSURE_PROGRAM_NORMAL_PROGRAM = 2; /** * A value to be used with the "ExposureProgram" tag. * * @see #TAG_EXPOSURE_PROGRAM */ public static final int EXPOSURE_PROGRAM_APERTURE_PRIORITY = 3; /** * A value to be used with the "ExposureProgram" tag. * * @see #TAG_EXPOSURE_PROGRAM */ public static final int EXPOSURE_PROGRAM_SHUTTER_PRIORITY = 4; /** * A value to be used with the "ExposureProgram" tag. * * @see #TAG_EXPOSURE_PROGRAM */ public static final int EXPOSURE_PROGRAM_CREATIVE_PROGRAM = 5; /** * A value to be used with the "ExposureProgram" tag. * * @see #TAG_EXPOSURE_PROGRAM */ public static final int EXPOSURE_PROGRAM_ACTION_PROGRAM = 6; /** * A value to be used with the "ExposureProgram" tag. * * @see #TAG_EXPOSURE_PROGRAM */ public static final int EXPOSURE_PROGRAM_PORTRAIT_MODE = 7; /** * A value to be used with the "ExposureProgram" tag. * * @see #TAG_EXPOSURE_PROGRAM */ public static final int EXPOSURE_PROGRAM_LANDSCAPE_MODE = 8; /** * A value to be used with the "ExposureProgram" tag. * * @see #TAG_EXPOSURE_PROGRAM */ public static final int EXPOSURE_PROGRAM_MAX_RESERVED = 255; /** * A tag indicating the spectral sensitivity of each channel of * the camera used (type ASCII). The tag value is an ASCII string * compatible with the ASTM standard. */ public static final int TAG_SPECTRAL_SENSITIVITY = 34852; /** * A tag indicating the ISO speed and ISO latitude of the camera * or input device, as specified in ISO 12232xiv (type * SHORT). */ public static final int TAG_ISO_SPEED_RATINGS= 34855; /** * A tag indicating the optoelectric conversion function, * specified in ISO 14254xv (type UNDEFINED). OECF is * the relationship between the camera optical input and the image * values. */ public static final int TAG_OECF = 34856; /** * A tag indicating the shutter speed (type SRATIONAL). */ public static final int TAG_SHUTTER_SPEED_VALUE = 37377; /** * A tag indicating the lens aperture (type RATIONAL). */ public static final int TAG_APERTURE_VALUE = 37378; /** * A tag indicating the value of brightness (type SRATIONAL). */ public static final int TAG_BRIGHTNESS_VALUE = 37379; /** * A tag indicating the exposure bias (type SRATIONAL). */ public static final int TAG_EXPOSURE_BIAS_VALUE = 37380; /** * A tag indicating the smallest F number of the lens (type * RATIONAL). */ public static final int TAG_MAX_APERTURE_VALUE = 37381; /** * A tag indicating the distance to the subject, in meters (type * RATIONAL). */ public static final int TAG_SUBJECT_DISTANCE = 37382; /** * A tag indicating the metering mode (type SHORT). * * @see #METERING_MODE_UNKNOWN * @see #METERING_MODE_AVERAGE * @see #METERING_MODE_CENTER_WEIGHTED_AVERAGE * @see #METERING_MODE_SPOT * @see #METERING_MODE_MULTI_SPOT * @see #METERING_MODE_PATTERN * @see #METERING_MODE_PARTIAL * @see #METERING_MODE_MIN_RESERVED * @see #METERING_MODE_MAX_RESERVED * @see #METERING_MODE_OTHER */ public static final int TAG_METERING_MODE = 37383; /** * A value to be used with the "MeteringMode" tag. * * @see #TAG_METERING_MODE */ public static final int METERING_MODE_UNKNOWN = 0; /** * A value to be used with the "MeteringMode" tag. * * @see #TAG_METERING_MODE */ public static final int METERING_MODE_AVERAGE = 1; /** * A value to be used with the "MeteringMode" tag. * * @see #TAG_METERING_MODE */ public static final int METERING_MODE_CENTER_WEIGHTED_AVERAGE = 2; /** * A value to be used with the "MeteringMode" tag. * * @see #TAG_METERING_MODE */ public static final int METERING_MODE_SPOT = 3; /** * A value to be used with the "MeteringMode" tag. * * @see #TAG_METERING_MODE */ public static final int METERING_MODE_MULTI_SPOT = 4; /** * A value to be used with the "MeteringMode" tag. * * @see #TAG_METERING_MODE */ public static final int METERING_MODE_PATTERN = 5; /** * A value to be used with the "MeteringMode" tag. * * @see #TAG_METERING_MODE */ public static final int METERING_MODE_PARTIAL = 6; /** * A value to be used with the "MeteringMode" tag. * * @see #TAG_METERING_MODE */ public static final int METERING_MODE_MIN_RESERVED = 7; /** * A value to be used with the "MeteringMode" tag. * * @see #TAG_METERING_MODE */ public static final int METERING_MODE_MAX_RESERVED = 254; /** * A value to be used with the "MeteringMode" tag. * * @see #TAG_METERING_MODE */ public static final int METERING_MODE_OTHER = 255; /** * A tag indicatingthe kind of light source (type SHORT). * * @see #LIGHT_SOURCE_UNKNOWN * @see #LIGHT_SOURCE_DAYLIGHT * @see #LIGHT_SOURCE_FLUORESCENT * @see #LIGHT_SOURCE_TUNGSTEN * @see #LIGHT_SOURCE_STANDARD_LIGHT_A * @see #LIGHT_SOURCE_STANDARD_LIGHT_B * @see #LIGHT_SOURCE_STANDARD_LIGHT_C * @see #LIGHT_SOURCE_D55 * @see #LIGHT_SOURCE_D65 * @see #LIGHT_SOURCE_D75 * @see #LIGHT_SOURCE_OTHER */ public static final int TAG_LIGHT_SOURCE = 37384; /** * A value to be used with the "LightSource" tag. * * @see #TAG_LIGHT_SOURCE */ public static final int LIGHT_SOURCE_UNKNOWN = 0; /** * A value to be used with the "LightSource" tag. * * @see #TAG_LIGHT_SOURCE */ public static final int LIGHT_SOURCE_DAYLIGHT = 1; /** * A value to be used with the "LightSource" tag. * * @see #TAG_LIGHT_SOURCE */ public static final int LIGHT_SOURCE_FLUORESCENT = 2; /** * A value to be used with the "LightSource" tag. * * @see #TAG_LIGHT_SOURCE */ public static final int LIGHT_SOURCE_TUNGSTEN = 3; /** * A value to be used with the "LightSource" tag. * * @see #TAG_LIGHT_SOURCE */ public static final int LIGHT_SOURCE_FLASH = 4; /** * A value to be used with the "LightSource" tag. * * @see #TAG_LIGHT_SOURCE */ public static final int LIGHT_SOURCE_FINE_WEATHER = 9; /** * A value to be used with the "LightSource" tag. * * @see #TAG_LIGHT_SOURCE */ public static final int LIGHT_SOURCE_CLOUDY_WEATHER = 10; /** * A value to be used with the "LightSource" tag. * * @see #TAG_LIGHT_SOURCE */ public static final int LIGHT_SOURCE_SHADE = 11; /** * A value to be used with the "LightSource" tag. * * @see #TAG_LIGHT_SOURCE */ public static final int LIGHT_SOURCE_DAYLIGHT_FLUORESCENT = 12; /** * A value to be used with the "LightSource" tag. * * @see #TAG_LIGHT_SOURCE */ public static final int LIGHT_SOURCE_DAY_WHITE_FLUORESCENT = 13; /** * A value to be used with the "LightSource" tag. * * @see #TAG_LIGHT_SOURCE */ public static final int LIGHT_SOURCE_COOL_WHITE_FLUORESCENT = 14; /** * A value to be used with the "LightSource" tag. * * @see #TAG_LIGHT_SOURCE */ public static final int LIGHT_SOURCE_WHITE_FLUORESCENT = 15; /** * A value to be used with the "LightSource" tag. * * @see #TAG_LIGHT_SOURCE */ public static final int LIGHT_SOURCE_STANDARD_LIGHT_A = 17; /** * A value to be used with the "LightSource" tag. * * @see #TAG_LIGHT_SOURCE */ public static final int LIGHT_SOURCE_STANDARD_LIGHT_B = 18; /** * A value to be used with the "LightSource" tag. * * @see #TAG_LIGHT_SOURCE */ public static final int LIGHT_SOURCE_STANDARD_LIGHT_C = 19; /** * A value to be used with the "LightSource" tag. * * @see #TAG_LIGHT_SOURCE */ public static final int LIGHT_SOURCE_D55 = 20; /** * A value to be used with the "LightSource" tag. * * @see #TAG_LIGHT_SOURCE */ public static final int LIGHT_SOURCE_D65 = 21; /** * A value to be used with the "LightSource" tag. * * @see #TAG_LIGHT_SOURCE */ public static final int LIGHT_SOURCE_D75 = 22; /** * A value to be used with the "LightSource" tag. * * @see #TAG_LIGHT_SOURCE */ public static final int LIGHT_SOURCE_D50 = 23; /** * A value to be used with the "LightSource" tag. * * @see #TAG_LIGHT_SOURCE */ public static final int LIGHT_SOURCE_ISO_STUDIO_TUNGSTEN = 24; /** * A value to be used with the "LightSource" tag. * * @see #TAG_LIGHT_SOURCE */ public static final int LIGHT_SOURCE_OTHER = 255; /** * A tag indicating the flash firing status and flash return * status (type SHORT). * * @see #FLASH_DID_NOT_FIRE * @see #FLASH_FIRED * @see #FLASH_STROBE_RETURN_LIGHT_NOT_DETECTED * @see #FLASH_STROBE_RETURN_LIGHT_DETECTED */ public static final int TAG_FLASH = 37385; /** * A value to be used with the "Flash" tag, indicating that the * flash did not fire. * * @see #TAG_FLASH */ public static final int FLASH_DID_NOT_FIRE = 0x0; /** * A value to be used with the "Flash" tag, indicating that the * flash fired, but the strobe return status is unknown. * * @see #TAG_FLASH */ public static final int FLASH_FIRED = 0x1; /** * A value to be used with the "Flash" tag, indicating that the * flash fired, but the strobe return light was not detected. * * @see #TAG_FLASH */ public static final int FLASH_STROBE_RETURN_LIGHT_NOT_DETECTED = 0x5; /** * A value to be used with the "Flash" tag, indicating that the * flash fired, and the strobe return light was detected. * * @see #TAG_FLASH */ public static final int FLASH_STROBE_RETURN_LIGHT_DETECTED = 0x7; /** * A mask to be used with the "Flash" tag, indicating that the * flash fired. * * @see #TAG_FLASH */ public static final int FLASH_MASK_FIRED = 0x1; /** * A mask to be used with the "Flash" tag, indicating strobe return * light not detected. * * @see #TAG_FLASH */ public static final int FLASH_MASK_RETURN_NOT_DETECTED = 0x4; /** * A mask to be used with the "Flash" tag, indicating strobe return * light detected. * * @see #TAG_FLASH */ public static final int FLASH_MASK_RETURN_DETECTED = 0x6; /** * A mask to be used with the "Flash" tag, indicating compulsory flash * firing mode. * * @see #TAG_FLASH */ public static final int FLASH_MASK_MODE_FLASH_FIRING = 0x8; /** * A mask to be used with the "Flash" tag, indicating compulsory flash * suppression mode. * * @see #TAG_FLASH */ public static final int FLASH_MASK_MODE_FLASH_SUPPRESSION = 0x10; /** * A mask to be used with the "Flash" tag, indicating auto mode. * * @see #TAG_FLASH */ public static final int FLASH_MASK_MODE_AUTO = 0x18; /** * A mask to be used with the "Flash" tag, indicating no flash function * present. * * @see #TAG_FLASH */ public static final int FLASH_MASK_FUNCTION_NOT_PRESENT = 0x20; /** * A mask to be used with the "Flash" tag, indicating red-eye reduction * supported. * * @see #TAG_FLASH */ public static final int FLASH_MASK_RED_EYE_REDUCTION = 0x40; /** * A tag indicating the actual focal length of the lens, in * millimeters (type RATIONAL). */ public static final int TAG_FOCAL_LENGTH = 37386; /** * A tag indicating the location and area of the main subject in * the overall scene. */ public static final int TAG_SUBJECT_AREA = 37396; /** * A tag indicating the strobe energy at the time the image was * captured, as measured in Beam Candle Power Seconds (BCPS) (type * RATIONAL). */ public static final int TAG_FLASH_ENERGY = 41483; /** * A tag indicating the camera or input device spatial frequency * table and SFR values in the direction of image width, image * height, and diagonal direction, as specified in ISO * 12233xvi (type UNDEFINED). */ public static final int TAG_SPATIAL_FREQUENCY_RESPONSE = 41484; /** * Indicates the number of pixels in the image width (X) direction * per FocalPlaneResolutionUnit on the camera focal plane (type * RATIONAL). */ public static final int TAG_FOCAL_PLANE_X_RESOLUTION = 41486; /** * Indicate the number of pixels in the image height (Y) direction * per FocalPlaneResolutionUnit on the camera focal plane (type * RATIONAL). */ public static final int TAG_FOCAL_PLANE_Y_RESOLUTION = 41487; /** * Indicates the unit for measuring FocalPlaneXResolution and * FocalPlaneYResolution (type SHORT). * * @see #FOCAL_PLANE_RESOLUTION_UNIT_NONE * @see #FOCAL_PLANE_RESOLUTION_UNIT_INCH * @see #FOCAL_PLANE_RESOLUTION_UNIT_CENTIMETER */ public static final int TAG_FOCAL_PLANE_RESOLUTION_UNIT = 41488; /** * A value to be used with the "FocalPlaneResolutionUnit" tag. * * @see #TAG_FOCAL_PLANE_RESOLUTION_UNIT */ public static final int FOCAL_PLANE_RESOLUTION_UNIT_NONE = 1; /** * A value to be used with the "FocalPlaneXResolution" tag. * * @see #TAG_FOCAL_PLANE_RESOLUTION_UNIT */ public static final int FOCAL_PLANE_RESOLUTION_UNIT_INCH = 2; /** * A value to be used with the "FocalPlaneXResolution" tag. * * @see #TAG_FOCAL_PLANE_RESOLUTION_UNIT */ public static final int FOCAL_PLANE_RESOLUTION_UNIT_CENTIMETER = 3; /** * A tag indicating the column and row of the center pixel of the * main subject in the scene (type SHORT, count = 2). */ public static final int TAG_SUBJECT_LOCATION = 41492; /** * A tag indicating the exposure index selected on the camera or * input device at the time the image was captured (type * RATIONAL). */ public static final int TAG_EXPOSURE_INDEX = 41493; /** * A tag indicating the sensor type on the camera or input device * (type SHORT). * * @see #SENSING_METHOD_NOT_DEFINED * @see #SENSING_METHOD_ONE_CHIP_COLOR_AREA_SENSOR * @see #SENSING_METHOD_TWO_CHIP_COLOR_AREA_SENSOR * @see #SENSING_METHOD_THREE_CHIP_COLOR_AREA_SENSOR * @see #SENSING_METHOD_COLOR_SEQUENTIAL_AREA_SENSOR * @see #SENSING_METHOD_TRILINEAR_SENSOR * @see #SENSING_METHOD_COLOR_SEQUENTIAL_LINEAR_SENSOR */ public static final int TAG_SENSING_METHOD = 41495; /** * A value to be used with the "SensingMethod" tag. * * @see #TAG_SENSING_METHOD */ public static final int SENSING_METHOD_NOT_DEFINED = 1; /** * A value to be used with the "SensingMethod" tag. * * @see #TAG_SENSING_METHOD */ public static final int SENSING_METHOD_ONE_CHIP_COLOR_AREA_SENSOR = 2; /** * A value to be used with the "SensingMethod" tag. * * @see #TAG_SENSING_METHOD */ public static final int SENSING_METHOD_TWO_CHIP_COLOR_AREA_SENSOR = 3; /** * A value to be used with the "SensingMethod" tag. * * @see #TAG_SENSING_METHOD */ public static final int SENSING_METHOD_THREE_CHIP_COLOR_AREA_SENSOR = 4; /** * A value to be used with the "SensingMethod" tag. * * @see #TAG_SENSING_METHOD */ public static final int SENSING_METHOD_COLOR_SEQUENTIAL_AREA_SENSOR = 5; /** * A value to be used with the "SensingMethod" tag. * * @see #TAG_SENSING_METHOD */ public static final int SENSING_METHOD_TRILINEAR_SENSOR = 7; /** * A value to be used with the "SensingMethod" tag. * * @see #TAG_SENSING_METHOD */ public static final int SENSING_METHOD_COLOR_SEQUENTIAL_LINEAR_SENSOR = 8; /** * A tag indicating the image source (type UNDEFINED). * * @see #FILE_SOURCE_DSC */ public static final int TAG_FILE_SOURCE = 41728; /** * A value to be used with the "FileSource" tag. * * @see #TAG_FILE_SOURCE */ public static final int FILE_SOURCE_DSC = 3; /** * A tag indicating the type of scene (type UNDEFINED). * * @see #SCENE_TYPE_DSC */ public static final int TAG_SCENE_TYPE = 41729; /** * A value to be used with the "SceneType" tag. * * @see #TAG_SCENE_TYPE */ public static final int SCENE_TYPE_DSC = 1; /** * A tag indicating the color filter array geometric pattern of * the image sensor when a one-chip color area sensor if used * (type UNDEFINED). */ public static final int TAG_CFA_PATTERN = 41730; /** * A tag indicating the use of special processing on image data, * such as rendering geared to output. */ public static final int TAG_CUSTOM_RENDERED = 41985; /** * A value to be used with the "CustomRendered" tag. * * @see #TAG_CUSTOM_RENDERED */ public static final int CUSTOM_RENDERED_NORMAL = 0; /** * A value to be used with the "CustomRendered" tag. * * @see #TAG_CUSTOM_RENDERED */ public static final int CUSTOM_RENDERED_CUSTOM = 1; /** * A tag indicating the exposure mode set when the image was shot. */ public static final int TAG_EXPOSURE_MODE = 41986; /** * A value to be used with the "ExposureMode" tag. * * @see #TAG_EXPOSURE_MODE */ public static final int EXPOSURE_MODE_AUTO_EXPOSURE = 0; /** * A value to be used with the "ExposureMode" tag. * * @see #TAG_EXPOSURE_MODE */ public static final int EXPOSURE_MODE_MANUAL_EXPOSURE = 1; /** * A value to be used with the "ExposureMode" tag. * * @see #TAG_EXPOSURE_MODE */ public static final int EXPOSURE_MODE_AUTO_BRACKET = 2; /** * A tag indicating the white balance mode set when the image was shot. */ public static final int TAG_WHITE_BALANCE = 41987; /** * A value to be used with the "WhiteBalance" tag. * * @see #TAG_WHITE_BALANCE */ public static final int WHITE_BALANCE_AUTO = 0; /** * A value to be used with the "WhiteBalance" tag. * * @see #TAG_WHITE_BALANCE */ public static final int WHITE_BALANCE_MANUAL = 1; /** * A tag indicating the digital zoom ratio when the image was shot. */ public static final int TAG_DIGITAL_ZOOM_RATIO = 41988; /** * A tag indicating the equivalent focal length assuming a 35mm film * camera, in millimeters. */ public static final int TAG_FOCAL_LENGTH_IN_35MM_FILM = 41989; /** * A tag indicating the type of scene that was shot. */ public static final int TAG_SCENE_CAPTURE_TYPE = 41990; /** * A value to be used with the "SceneCaptureType" tag. * * @see #TAG_SCENE_CAPTURE_TYPE */ public static final int SCENE_CAPTURE_TYPE_STANDARD = 0; /** * A value to be used with the "SceneCaptureType" tag. * * @see #TAG_SCENE_CAPTURE_TYPE */ public static final int SCENE_CAPTURE_TYPE_LANDSCAPE = 1; /** * A value to be used with the "SceneCaptureType" tag. * * @see #TAG_SCENE_CAPTURE_TYPE */ public static final int SCENE_CAPTURE_TYPE_PORTRAIT = 2; /** * A value to be used with the "SceneCaptureType" tag. * * @see #TAG_SCENE_CAPTURE_TYPE */ public static final int SCENE_CAPTURE_TYPE_NIGHT_SCENE = 3; /** * A tag indicating the degree of overall image gain adjustment. */ public static final int TAG_GAIN_CONTROL = 41991; /** * A value to be used with the "GainControl" tag. * * @see #TAG_GAIN_CONTROL */ public static final int GAIN_CONTROL_NONE = 0; /** * A value to be used with the "GainControl" tag. * * @see #TAG_GAIN_CONTROL */ public static final int GAIN_CONTROL_LOW_GAIN_UP = 1; /** * A value to be used with the "GainControl" tag. * * @see #TAG_GAIN_CONTROL */ public static final int GAIN_CONTROL_HIGH_GAIN_UP = 2; /** * A value to be used with the "GainControl" tag. * * @see #TAG_GAIN_CONTROL */ public static final int GAIN_CONTROL_LOW_GAIN_DOWN = 3; /** * A value to be used with the "GainControl" tag. * * @see #TAG_GAIN_CONTROL */ public static final int GAIN_CONTROL_HIGH_GAIN_DOWN = 4; /** * A tag indicating the direction of contrast processing applied * by the camera when the image was shot. */ public static final int TAG_CONTRAST = 41992; /** * A value to be used with the "Contrast" tag. * * @see #TAG_CONTRAST */ public static final int CONTRAST_NORMAL = 0; /** * A value to be used with the "Contrast" tag. * * @see #TAG_CONTRAST */ public static final int CONTRAST_SOFT = 1; /** * A value to be used with the "Contrast" tag. * * @see #TAG_CONTRAST */ public static final int CONTRAST_HARD = 2; /** * A tag indicating the direction of saturation processing * applied by the camera when the image was shot. */ public static final int TAG_SATURATION = 41993; /** * A value to be used with the "Saturation" tag. * * @see #TAG_SATURATION */ public static final int SATURATION_NORMAL = 0; /** * A value to be used with the "Saturation" tag. * * @see #TAG_SATURATION */ public static final int SATURATION_LOW = 1; /** * A value to be used with the "Saturation" tag. * * @see #TAG_SATURATION */ public static final int SATURATION_HIGH = 2; /** * A tag indicating the direction of sharpness processing * applied by the camera when the image was shot. */ public static final int TAG_SHARPNESS = 41994; /** * A value to be used with the "Sharpness" tag. * * @see #TAG_SHARPNESS */ public static final int SHARPNESS_NORMAL = 0; /** * A value to be used with the "Sharpness" tag. * * @see #TAG_SHARPNESS */ public static final int SHARPNESS_SOFT = 1; /** * A value to be used with the "Sharpness" tag. * * @see #TAG_SHARPNESS */ public static final int SHARPNESS_HARD = 2; /** * A tag indicating information on the picture-taking conditions * of a particular camera model. */ public static final int TAG_DEVICE_SETTING_DESCRIPTION = 41995; /** * A tag indicating the distance to the subject. */ public static final int TAG_SUBJECT_DISTANCE_RANGE = 41996; /** * A value to be used with the "SubjectDistanceRange" tag. * * @see #TAG_SUBJECT_DISTANCE_RANGE */ public static final int SUBJECT_DISTANCE_RANGE_UNKNOWN = 0; /** * A value to be used with the "SubjectDistanceRange" tag. * * @see #TAG_SUBJECT_DISTANCE_RANGE */ public static final int SUBJECT_DISTANCE_RANGE_MACRO = 1; /** * A value to be used with the "SubjectDistanceRange" tag. * * @see #TAG_SUBJECT_DISTANCE_RANGE */ public static final int SUBJECT_DISTANCE_RANGE_CLOSE_VIEW = 2; /** * A value to be used with the "SubjectDistanceRange" tag. * * @see #TAG_SUBJECT_DISTANCE_RANGE */ public static final int SUBJECT_DISTANCE_RANGE_DISTANT_VIEW = 3; /** * A tag indicating an identifier assigned uniquely to each image. */ public static final int TAG_IMAGE_UNIQUE_ID = 42016; // EXIF 2.1 private // GPS Attribute Information // 0 - GPSVersionID (BYTE/4) // 1 - GPSLatitudeRef (ASCII/2) // 2 - GPSLatitude (RATIONAL/3) // 3 - GPSLongitudeRef (ASCII/2) // 4 - GPSLongitude (RATIONAL/3) // 5 - GPSAltitudeRef (BYTE/1) // 6 - GPSAltitude (RATIONAL/1) // 7 - GPSTimeStamp (RATIONAL/3) // 8 - GPSSatellites (ASCII/any) // 9 - GPSStatus (ASCII/2) // 10 - GPSMeasureMode (ASCII/2) // 11 - GPSDOP (RATIONAL/1) // 12 - GPSSpeedRef (ASCII/2) // 13 - GPSSpeed (RATIONAL/1) // 14 - GPSTrackRef (ASCII/2) // 15 - GPSTrack (RATIONAL/1) // 16 - GPSImgDirectionRef (ASCII/2) // 17 - GPSImgDirection (RATIONAL/1) // 18 - GPSMapDatum (ASCII/any) // 19 - GPSDestLatitudeRef (ASCII/2) // 20 - GPSDestLatitude (RATIONAL/3) // 21 - GPSDestLongitudeRef (ASCII/2) // 22 - GPSDestLongitude (RATIONAL/3) // 23 - GPSDestBearingRef (ASCII/2) // 24 - GPSDestBearing (RATIONAL/1) // 25 - GPSDestDistanceRef (ASCII/2) // 26 - GPSDestDistance (RATIONAL/1) // EXIF Interoperability Information ??? // 0 - Interoperability Index (ASCII/any) // EXIF tags static class EXIFVersion extends TIFFTag { public EXIFVersion() { super("EXIFversion", TAG_EXIF_VERSION, 1 << TIFFTag.TIFF_UNDEFINED); } } static class FlashPixVersion extends TIFFTag { public FlashPixVersion() { super("FlashPixVersion", TAG_FLASHPIX_VERSION, 1 << TIFFTag.TIFF_UNDEFINED); } } static class ColorSpace extends TIFFTag { public ColorSpace() { super("ColorSpace", TAG_COLOR_SPACE, 1 << TIFFTag.TIFF_SHORT); addValueName(COLOR_SPACE_SRGB, "sRGB"); addValueName(COLOR_SPACE_UNCALIBRATED, "Uncalibrated"); } } static class ComponentsConfiguration extends TIFFTag { public ComponentsConfiguration() { super("ComponentsConfiguration", TAG_COMPONENTS_CONFIGURATION, 1 << TIFFTag.TIFF_UNDEFINED); addValueName(COMPONENTS_CONFIGURATION_DOES_NOT_EXIST, "DoesNotExist"); addValueName(COMPONENTS_CONFIGURATION_Y, "Y"); addValueName(COMPONENTS_CONFIGURATION_CB, "Cb"); addValueName(COMPONENTS_CONFIGURATION_CR, "Cr"); addValueName(COMPONENTS_CONFIGURATION_R, "R"); addValueName(COMPONENTS_CONFIGURATION_G, "G"); addValueName(COMPONENTS_CONFIGURATION_B, "B"); } } static class CompressedBitsPerPixel extends TIFFTag { public CompressedBitsPerPixel() { super("CompressedBitsPerPixel", TAG_COMPRESSED_BITS_PER_PIXEL, 1 << TIFFTag.TIFF_RATIONAL); } } static class PixelXDimension extends TIFFTag { public PixelXDimension() { super("PixelXDimension", TAG_PIXEL_X_DIMENSION, (1 << TIFFTag.TIFF_SHORT) | (1 << TIFFTag.TIFF_LONG)); } } static class PixelYDimension extends TIFFTag { public PixelYDimension() { super("PixelYDimension", TAG_PIXEL_Y_DIMENSION, (1 << TIFFTag.TIFF_SHORT) | (1 << TIFFTag.TIFF_LONG)); } } static class MakerNote extends TIFFTag { public MakerNote() { super("MakerNote", TAG_MAKER_NOTE, 1 << TIFFTag.TIFF_UNDEFINED); } } static class UserComment extends TIFFTag { public UserComment() { super("UserComment", TAG_USER_COMMENT, 1 << TIFFTag.TIFF_UNDEFINED); } } static class RelatedSoundFile extends TIFFTag { public RelatedSoundFile() { super("RelatedSoundFile", TAG_RELATED_SOUND_FILE, 1 << TIFFTag.TIFF_ASCII); } } static class DateTimeOriginal extends TIFFTag { public DateTimeOriginal() { super("DateTimeOriginal", TAG_DATE_TIME_ORIGINAL, 1 << TIFFTag.TIFF_ASCII); } } static class DateTimeDigitized extends TIFFTag { public DateTimeDigitized() { super("DateTimeDigitized", TAG_DATE_TIME_DIGITIZED, 1 << TIFFTag.TIFF_ASCII); } } static class SubSecTime extends TIFFTag { public SubSecTime() { super("SubSecTime", TAG_SUB_SEC_TIME, 1 << TIFFTag.TIFF_ASCII); } } static class SubSecTimeOriginal extends TIFFTag { public SubSecTimeOriginal() { super("SubSecTimeOriginal", TAG_SUB_SEC_TIME_ORIGINAL, 1 << TIFFTag.TIFF_ASCII); } } static class SubSecTimeDigitized extends TIFFTag { public SubSecTimeDigitized() { super("SubSecTimeDigitized", TAG_SUB_SEC_TIME_DIGITIZED, 1 << TIFFTag.TIFF_ASCII); } } static class ExposureTime extends TIFFTag { public ExposureTime() { super("ExposureTime", TAG_EXPOSURE_TIME, 1 << TIFFTag.TIFF_RATIONAL); } } static class FNumber extends TIFFTag { public FNumber() { super("FNumber", TAG_F_NUMBER, 1 << TIFFTag.TIFF_RATIONAL); } } static class ExposureProgram extends TIFFTag { public ExposureProgram() { super("ExposureProgram", TAG_EXPOSURE_PROGRAM, 1 << TIFFTag.TIFF_SHORT); addValueName(EXPOSURE_PROGRAM_NOT_DEFINED, "Not Defined"); addValueName(EXPOSURE_PROGRAM_MANUAL, "Manual"); addValueName(EXPOSURE_PROGRAM_NORMAL_PROGRAM, "Normal Program"); addValueName(EXPOSURE_PROGRAM_APERTURE_PRIORITY, "Aperture Priority"); addValueName(EXPOSURE_PROGRAM_SHUTTER_PRIORITY, "Shutter Priority"); addValueName(EXPOSURE_PROGRAM_CREATIVE_PROGRAM, "Creative Program"); addValueName(EXPOSURE_PROGRAM_ACTION_PROGRAM, "Action Program"); addValueName(EXPOSURE_PROGRAM_PORTRAIT_MODE, "Portrait Mode"); addValueName(EXPOSURE_PROGRAM_LANDSCAPE_MODE, "Landscape Mode"); } } static class SpectralSensitivity extends TIFFTag { public SpectralSensitivity() { super("SpectralSensitivity", TAG_SPECTRAL_SENSITIVITY, 1 << TIFFTag.TIFF_ASCII); } } static class ISOSpeedRatings extends TIFFTag { public ISOSpeedRatings() { super("ISOSpeedRatings", TAG_ISO_SPEED_RATINGS, 1 << TIFFTag.TIFF_SHORT); } } static class OECF extends TIFFTag { public OECF() { super("OECF", TAG_OECF, 1 << TIFFTag.TIFF_UNDEFINED); } } static class ShutterSpeedValue extends TIFFTag { public ShutterSpeedValue() { super("ShutterSpeedValue", TAG_SHUTTER_SPEED_VALUE, 1 << TIFFTag.TIFF_SRATIONAL); } } static class ApertureValue extends TIFFTag { public ApertureValue() { super("ApertureValue", TAG_APERTURE_VALUE, 1 << TIFFTag.TIFF_RATIONAL); } } static class BrightnessValue extends TIFFTag { public BrightnessValue() { super("BrightnessValue", TAG_BRIGHTNESS_VALUE, 1 << TIFFTag.TIFF_SRATIONAL); } } static class ExposureBiasValue extends TIFFTag { public ExposureBiasValue() { super("ExposureBiasValue", TAG_EXPOSURE_BIAS_VALUE, 1 << TIFFTag.TIFF_SRATIONAL); } } static class MaxApertureValue extends TIFFTag { public MaxApertureValue() { super("MaxApertureValue", TAG_MAX_APERTURE_VALUE, 1 << TIFFTag.TIFF_RATIONAL); } } static class SubjectDistance extends TIFFTag { public SubjectDistance() { super("SubjectDistance", TAG_SUBJECT_DISTANCE, 1 << TIFFTag.TIFF_RATIONAL); } } static class MeteringMode extends TIFFTag { public MeteringMode() { super("MeteringMode", TAG_METERING_MODE, 1 << TIFFTag.TIFF_SHORT); addValueName(METERING_MODE_UNKNOWN, "Unknown"); addValueName(METERING_MODE_AVERAGE, "Average"); addValueName(METERING_MODE_CENTER_WEIGHTED_AVERAGE, "CenterWeightedAverage"); addValueName(METERING_MODE_SPOT, "Spot"); addValueName(METERING_MODE_MULTI_SPOT, "MultiSpot"); addValueName(METERING_MODE_PATTERN, "Pattern"); addValueName(METERING_MODE_PARTIAL, "Partial"); addValueName(METERING_MODE_OTHER, "Other"); } } static class LightSource extends TIFFTag { public LightSource() { super("LightSource", TAG_LIGHT_SOURCE, 1 << TIFFTag.TIFF_SHORT); addValueName(LIGHT_SOURCE_UNKNOWN, "Unknown"); addValueName(LIGHT_SOURCE_DAYLIGHT, "Daylight"); addValueName(LIGHT_SOURCE_FLUORESCENT, "Fluorescent"); addValueName(LIGHT_SOURCE_TUNGSTEN, "Tungsten"); addValueName(LIGHT_SOURCE_STANDARD_LIGHT_A, "Standard Light A"); addValueName(LIGHT_SOURCE_STANDARD_LIGHT_B, "Standard Light B"); addValueName(LIGHT_SOURCE_STANDARD_LIGHT_C, "Standard Light C"); addValueName(LIGHT_SOURCE_D55, "D55"); addValueName(LIGHT_SOURCE_D65, "D65"); addValueName(LIGHT_SOURCE_D75, "D75"); addValueName(LIGHT_SOURCE_OTHER, "Other"); } } static class Flash extends TIFFTag { public Flash() { super("Flash", TAG_FLASH, 1 << TIFFTag.TIFF_SHORT); addValueName(FLASH_DID_NOT_FIRE, "Flash Did Not Fire"); addValueName(FLASH_FIRED, "Flash Fired"); addValueName(FLASH_STROBE_RETURN_LIGHT_NOT_DETECTED, "Strobe Return Light Not Detected"); addValueName(FLASH_STROBE_RETURN_LIGHT_DETECTED, "Strobe Return Light Detected"); } } static class FocalLength extends TIFFTag { public FocalLength() { super("FocalLength", TAG_FOCAL_LENGTH, 1 << TIFFTag.TIFF_RATIONAL); } } static class SubjectArea extends TIFFTag { public SubjectArea() { super("SubjectArea", TAG_SUBJECT_AREA, 1 << TIFFTag.TIFF_SHORT); } } static class FlashEnergy extends TIFFTag { public FlashEnergy() { super("FlashEnergy", TAG_FLASH_ENERGY, 1 << TIFFTag.TIFF_RATIONAL); } } static class SpatialFrequencyResponse extends TIFFTag { public SpatialFrequencyResponse() { super("SpatialFrequencyResponse", TAG_SPATIAL_FREQUENCY_RESPONSE, 1 << TIFFTag.TIFF_UNDEFINED); } } static class FocalPlaneXResolution extends TIFFTag { public FocalPlaneXResolution() { super("FocalPlaneXResolution", TAG_FOCAL_PLANE_X_RESOLUTION, 1 << TIFFTag.TIFF_RATIONAL); } } static class FocalPlaneYResolution extends TIFFTag { public FocalPlaneYResolution() { super("FocalPlaneYResolution", TAG_FOCAL_PLANE_Y_RESOLUTION, 1 << TIFFTag.TIFF_RATIONAL); } } static class FocalPlaneResolutionUnit extends TIFFTag { public FocalPlaneResolutionUnit() { super("FocalPlaneResolutionUnit", TAG_FOCAL_PLANE_RESOLUTION_UNIT, 1 << TIFFTag.TIFF_SHORT); addValueName(FOCAL_PLANE_RESOLUTION_UNIT_NONE, "None"); addValueName(FOCAL_PLANE_RESOLUTION_UNIT_INCH, "Inch"); addValueName(FOCAL_PLANE_RESOLUTION_UNIT_CENTIMETER, "Centimeter"); } } static class SubjectLocation extends TIFFTag { public SubjectLocation() { super("SubjectLocation", TAG_SUBJECT_LOCATION, 1 << TIFFTag.TIFF_SHORT); } } static class ExposureIndex extends TIFFTag { public ExposureIndex() { super("ExposureIndex", TAG_EXPOSURE_INDEX, 1 << TIFFTag.TIFF_RATIONAL); } } static class SensingMethod extends TIFFTag { public SensingMethod() { super("SensingMethod", TAG_SENSING_METHOD, 1 << TIFFTag.TIFF_SHORT); addValueName(SENSING_METHOD_NOT_DEFINED, "Not Defined"); addValueName(SENSING_METHOD_ONE_CHIP_COLOR_AREA_SENSOR, "One-chip color area sensor"); addValueName(SENSING_METHOD_TWO_CHIP_COLOR_AREA_SENSOR, "Two-chip color area sensor"); addValueName(SENSING_METHOD_THREE_CHIP_COLOR_AREA_SENSOR, "Three-chip color area sensor"); addValueName(SENSING_METHOD_COLOR_SEQUENTIAL_AREA_SENSOR, "Color sequential area sensor"); addValueName(SENSING_METHOD_TRILINEAR_SENSOR, "Trilinear sensor"); addValueName(SENSING_METHOD_COLOR_SEQUENTIAL_LINEAR_SENSOR, "Color sequential linear sensor"); } } static class FileSource extends TIFFTag { public FileSource() { super("FileSource", TAG_FILE_SOURCE, 1 << TIFFTag.TIFF_UNDEFINED); addValueName(FILE_SOURCE_DSC, "DSC"); } } static class SceneType extends TIFFTag { public SceneType() { super("SceneType", TAG_SCENE_TYPE, 1 << TIFFTag.TIFF_UNDEFINED); addValueName(SCENE_TYPE_DSC, "A directly photographed image"); } } static class CFAPattern extends TIFFTag { public CFAPattern() { super("CFAPattern", TAG_CFA_PATTERN, 1 << TIFFTag.TIFF_UNDEFINED); } } static class CustomRendered extends TIFFTag { public CustomRendered() { super("CustomRendered", TAG_CUSTOM_RENDERED, 1 << TIFFTag.TIFF_SHORT); addValueName(CUSTOM_RENDERED_NORMAL, "Normal process"); addValueName(CUSTOM_RENDERED_CUSTOM, "Custom process"); } } static class ExposureMode extends TIFFTag { public ExposureMode() { super("ExposureMode", TAG_EXPOSURE_MODE, 1 << TIFFTag.TIFF_SHORT); addValueName(EXPOSURE_MODE_AUTO_EXPOSURE, "Auto exposure"); addValueName(EXPOSURE_MODE_MANUAL_EXPOSURE, "Manual exposure"); addValueName(EXPOSURE_MODE_AUTO_BRACKET, "Auto bracket"); } } static class WhiteBalance extends TIFFTag { public WhiteBalance() { super("WhiteBalance", TAG_WHITE_BALANCE, 1 << TIFFTag.TIFF_SHORT); addValueName(WHITE_BALANCE_AUTO, "Auto white balance"); addValueName(WHITE_BALANCE_MANUAL, "Manual white balance"); } } static class DigitalZoomRatio extends TIFFTag { public DigitalZoomRatio() { super("DigitalZoomRatio", TAG_DIGITAL_ZOOM_RATIO, 1 << TIFFTag.TIFF_RATIONAL); } } static class FocalLengthIn35mmFilm extends TIFFTag { public FocalLengthIn35mmFilm() { super("FocalLengthIn35mmFilm", TAG_FOCAL_LENGTH_IN_35MM_FILM, 1 << TIFFTag.TIFF_SHORT); } } static class SceneCaptureType extends TIFFTag { public SceneCaptureType() { super("SceneCaptureType", TAG_SCENE_CAPTURE_TYPE, 1 << TIFFTag.TIFF_SHORT); addValueName(SCENE_CAPTURE_TYPE_STANDARD, "Standard"); addValueName(SCENE_CAPTURE_TYPE_LANDSCAPE, "Landscape"); addValueName(SCENE_CAPTURE_TYPE_PORTRAIT, "Portrait"); addValueName(SCENE_CAPTURE_TYPE_NIGHT_SCENE, "Night scene"); } } static class GainControl extends TIFFTag { public GainControl() { super("GainControl", TAG_GAIN_CONTROL, 1 << TIFFTag.TIFF_SHORT); addValueName(GAIN_CONTROL_NONE, "None"); addValueName(GAIN_CONTROL_LOW_GAIN_UP, "Low gain up"); addValueName(GAIN_CONTROL_HIGH_GAIN_UP, "High gain up"); addValueName(GAIN_CONTROL_LOW_GAIN_DOWN, "Low gain down"); addValueName(GAIN_CONTROL_HIGH_GAIN_DOWN, "High gain down"); } } static class Contrast extends TIFFTag { public Contrast() { super("Contrast", TAG_CONTRAST, 1 << TIFFTag.TIFF_SHORT); addValueName(CONTRAST_NORMAL, "Normal"); addValueName(CONTRAST_SOFT, "Soft"); addValueName(CONTRAST_HARD, "Hard"); } } static class Saturation extends TIFFTag { public Saturation() { super("Saturation", TAG_SATURATION, 1 << TIFFTag.TIFF_SHORT); addValueName(SATURATION_NORMAL, "Normal"); addValueName(SATURATION_LOW, "Low saturation"); addValueName(SATURATION_HIGH, "High saturation"); } } static class Sharpness extends TIFFTag { public Sharpness() { super("Sharpness", TAG_SHARPNESS, 1 << TIFFTag.TIFF_SHORT); addValueName(SHARPNESS_NORMAL, "Normal"); addValueName(SHARPNESS_SOFT, "Soft"); addValueName(SHARPNESS_HARD, "Hard"); } } static class DeviceSettingDescription extends TIFFTag { public DeviceSettingDescription() { super("DeviceSettingDescription", TAG_DEVICE_SETTING_DESCRIPTION, 1 << TIFFTag.TIFF_UNDEFINED); } } static class SubjectDistanceRange extends TIFFTag { public SubjectDistanceRange() { super("SubjectDistanceRange", TAG_SUBJECT_DISTANCE_RANGE, 1 << TIFFTag.TIFF_SHORT); addValueName(SUBJECT_DISTANCE_RANGE_UNKNOWN, "unknown"); addValueName(SUBJECT_DISTANCE_RANGE_MACRO, "Macro"); addValueName(SUBJECT_DISTANCE_RANGE_CLOSE_VIEW, "Close view"); addValueName(SUBJECT_DISTANCE_RANGE_DISTANT_VIEW, "Distant view"); } } static class ImageUniqueID extends TIFFTag { public ImageUniqueID() { super("ImageUniqueID", TAG_IMAGE_UNIQUE_ID, 1 << TIFFTag.TIFF_ASCII); } } static class InteroperabilityIFD extends TIFFTag { public InteroperabilityIFD() { super("InteroperabilityIFD", TAG_INTEROPERABILITY_IFD_POINTER, 1 << TIFFTag.TIFF_LONG, EXIFInteroperabilityTagSet.getInstance()); } } private static List tags; private static void initTags() { tags = new ArrayList(42); tags.add(new EXIFTIFFTagSet.EXIFVersion()); tags.add(new EXIFTIFFTagSet.FlashPixVersion()); tags.add(new EXIFTIFFTagSet.ColorSpace()); tags.add(new EXIFTIFFTagSet.ComponentsConfiguration()); tags.add(new EXIFTIFFTagSet.CompressedBitsPerPixel()); tags.add(new EXIFTIFFTagSet.PixelXDimension()); tags.add(new EXIFTIFFTagSet.PixelYDimension()); tags.add(new EXIFTIFFTagSet.MakerNote()); tags.add(new EXIFTIFFTagSet.UserComment()); tags.add(new EXIFTIFFTagSet.RelatedSoundFile()); tags.add(new EXIFTIFFTagSet.DateTimeOriginal()); tags.add(new EXIFTIFFTagSet.DateTimeDigitized()); tags.add(new EXIFTIFFTagSet.SubSecTime()); tags.add(new EXIFTIFFTagSet.SubSecTimeOriginal()); tags.add(new EXIFTIFFTagSet.SubSecTimeDigitized()); tags.add(new EXIFTIFFTagSet.ExposureTime()); tags.add(new EXIFTIFFTagSet.FNumber()); tags.add(new EXIFTIFFTagSet.ExposureProgram()); tags.add(new EXIFTIFFTagSet.SpectralSensitivity()); tags.add(new EXIFTIFFTagSet.ISOSpeedRatings()); tags.add(new EXIFTIFFTagSet.OECF()); tags.add(new EXIFTIFFTagSet.ShutterSpeedValue()); tags.add(new EXIFTIFFTagSet.ApertureValue()); tags.add(new EXIFTIFFTagSet.BrightnessValue()); tags.add(new EXIFTIFFTagSet.ExposureBiasValue()); tags.add(new EXIFTIFFTagSet.MaxApertureValue()); tags.add(new EXIFTIFFTagSet.SubjectDistance()); tags.add(new EXIFTIFFTagSet.MeteringMode()); tags.add(new EXIFTIFFTagSet.LightSource()); tags.add(new EXIFTIFFTagSet.Flash()); tags.add(new EXIFTIFFTagSet.FocalLength()); tags.add(new EXIFTIFFTagSet.SubjectArea()); tags.add(new EXIFTIFFTagSet.FlashEnergy()); tags.add(new EXIFTIFFTagSet.SpatialFrequencyResponse()); tags.add(new EXIFTIFFTagSet.FocalPlaneXResolution()); tags.add(new EXIFTIFFTagSet.FocalPlaneYResolution()); tags.add(new EXIFTIFFTagSet.FocalPlaneResolutionUnit()); tags.add(new EXIFTIFFTagSet.SubjectLocation()); tags.add(new EXIFTIFFTagSet.ExposureIndex()); tags.add(new EXIFTIFFTagSet.SensingMethod()); tags.add(new EXIFTIFFTagSet.FileSource()); tags.add(new EXIFTIFFTagSet.SceneType()); tags.add(new EXIFTIFFTagSet.CFAPattern()); tags.add(new EXIFTIFFTagSet.CustomRendered()); tags.add(new EXIFTIFFTagSet.ExposureMode()); tags.add(new EXIFTIFFTagSet.WhiteBalance()); tags.add(new EXIFTIFFTagSet.DigitalZoomRatio()); tags.add(new EXIFTIFFTagSet.FocalLengthIn35mmFilm()); tags.add(new EXIFTIFFTagSet.SceneCaptureType()); tags.add(new EXIFTIFFTagSet.GainControl()); tags.add(new EXIFTIFFTagSet.Contrast()); tags.add(new EXIFTIFFTagSet.Saturation()); tags.add(new EXIFTIFFTagSet.Sharpness()); tags.add(new EXIFTIFFTagSet.DeviceSettingDescription()); tags.add(new EXIFTIFFTagSet.SubjectDistanceRange()); tags.add(new EXIFTIFFTagSet.ImageUniqueID()); tags.add(new EXIFTIFFTagSet.InteroperabilityIFD()); } private EXIFTIFFTagSet() { super(tags); } /** * Returns a shared instance of an EXIFTIFFTagSet. * * @return an EXIFTIFFTagSet instance. */ public synchronized static EXIFTIFFTagSet getInstance() { if (theInstance == null) { initTags(); theInstance = new EXIFTIFFTagSet(); tags = null; } return theInstance; } } jai-imageio-core-1.2/src/share/classes/com/sun/media/imageio/plugins/tiff/BaselineTIFFTagSet.java0000664000175100017510000016463610423764242031672 0ustar tilletille/* * $RCSfile: BaselineTIFFTagSet.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.2 $ * $Date: 2006-04-26 21:39:46 $ * $State: Exp $ */ package com.sun.media.imageio.plugins.tiff; import java.util.ArrayList; import java.util.List; /** * A class representing the set of tags found in the baseline TIFF * specification as well as some common additional tags. * *

The non-baseline tags included in this class are: *

    *
  • {@link #TAG_JPEG_TABLES JPEGTables} *
  • {@link #TAG_ICC_PROFILE ICC Profile} *
*

* *

The non-baseline values of baseline tags included in this class are *

  • {@link #TAG_COMPRESSION Compression} tag values: *
      *
    • {@link #COMPRESSION_JPEG JPEG-in-TIFF compression}
    • *
    • {@link #COMPRESSION_ZLIB Zlib-in-TIFF compression}
    • *
    • {@link #COMPRESSION_DEFLATE Deflate compression}
    • *
    *
  • *
  • {@link #TAG_PHOTOMETRIC_INTERPRETATION PhotometricInterpretation} * tag values: *
      *
    • {@link #PHOTOMETRIC_INTERPRETATION_ICCLAB ICCLAB  * photometric interpretation}
    • *
    *
  • *

    * * @see TIFF 6.0 Specification */ public class BaselineTIFFTagSet extends TIFFTagSet { private static BaselineTIFFTagSet theInstance = null; // Tags from TIFF 6.0 specification /** * Constant specifying the "NewSubfileType" tag. * * @see #NEW_SUBFILE_TYPE_REDUCED_RESOLUTION * @see #NEW_SUBFILE_TYPE_SINGLE_PAGE * @see #NEW_SUBFILE_TYPE_TRANSPARENCY */ public static final int TAG_NEW_SUBFILE_TYPE = 254; /** * A mask to be used with the "NewSubfileType" tag. * * @see #TAG_NEW_SUBFILE_TYPE */ public static final int NEW_SUBFILE_TYPE_REDUCED_RESOLUTION = 1; /** * A mask to be used with the "NewSubfileType" tag. * * @see #TAG_NEW_SUBFILE_TYPE */ public static final int NEW_SUBFILE_TYPE_SINGLE_PAGE = 2; /** * A mask to be used with the "NewSubfileType" tag. * * @see #TAG_NEW_SUBFILE_TYPE */ public static final int NEW_SUBFILE_TYPE_TRANSPARENCY = 4; /** * Constant specifying the "SubfileType" tag. * * @see #SUBFILE_TYPE_FULL_RESOLUTION * @see #SUBFILE_TYPE_REDUCED_RESOLUTION * @see #SUBFILE_TYPE_SINGLE_PAGE */ public static final int TAG_SUBFILE_TYPE = 255; /** * A value to be used with the "SubfileType" tag. * * @see #TAG_SUBFILE_TYPE */ public static final int SUBFILE_TYPE_FULL_RESOLUTION = 1; /** * A value to be used with the "SubfileType" tag. * * @see #TAG_SUBFILE_TYPE */ public static final int SUBFILE_TYPE_REDUCED_RESOLUTION = 2; /** * A value to be used with the "SubfileType" tag. * * @see #TAG_SUBFILE_TYPE */ public static final int SUBFILE_TYPE_SINGLE_PAGE = 3; /** * Constant specifying the "ImageWidth" tag. */ public static final int TAG_IMAGE_WIDTH = 256; /** * Constant specifying the "ImageLength" tag. */ public static final int TAG_IMAGE_LENGTH = 257; /** * Constant specifying the "BitsPerSample" tag. */ public static final int TAG_BITS_PER_SAMPLE = 258; /** * Constant specifying the "Compression" tag. * * @see #COMPRESSION_NONE * @see #COMPRESSION_CCITT_RLE * @see #COMPRESSION_CCITT_T_4 * @see #COMPRESSION_CCITT_T_6 * @see #COMPRESSION_LZW * @see #COMPRESSION_OLD_JPEG * @see #COMPRESSION_JPEG * @see #COMPRESSION_ZLIB * @see #COMPRESSION_PACKBITS * @see #COMPRESSION_DEFLATE */ public static final int TAG_COMPRESSION = 259; /** * A value to be used with the "Compression" tag. * * @see #TAG_COMPRESSION */ public static final int COMPRESSION_NONE = 1; /** * A value to be used with the "Compression" tag. * * @see #TAG_COMPRESSION */ public static final int COMPRESSION_CCITT_RLE = 2; /** * A value to be used with the "Compression" tag. * * @see #TAG_COMPRESSION */ public static final int COMPRESSION_CCITT_T_4 = 3; /** * A value to be used with the "Compression" tag. * * @see #TAG_COMPRESSION */ public static final int COMPRESSION_CCITT_T_6 = 4; /** * A value to be used with the "Compression" tag. * * @see #TAG_COMPRESSION */ public static final int COMPRESSION_LZW = 5; /** * A value to be used with the "Compression" tag. * * @see #TAG_COMPRESSION */ public static final int COMPRESSION_OLD_JPEG = 6; /** * A value to be used with the "Compression" tag. * * @see #TAG_COMPRESSION * @see TIFF Specification Supplement 2 */ public static final int COMPRESSION_JPEG = 7; /** * A value to be used with the "Compression" tag. * * @see #TAG_COMPRESSION * @see TIFF Specification Supplement 2 */ public static final int COMPRESSION_ZLIB = 8; /** * A value to be used with the "Compression" tag. * * @see #TAG_COMPRESSION */ public static final int COMPRESSION_PACKBITS = 32773; /** * A value to be used with the "Compression" tag. * * @see #TAG_COMPRESSION * @see DEFLATE specification * @see TIFF Specification Supplement 2 */ public static final int COMPRESSION_DEFLATE = 32946; /** * Constant specifying the "PhotometricInterpretation" tag. * * @see #PHOTOMETRIC_INTERPRETATION_WHITE_IS_ZERO * @see #PHOTOMETRIC_INTERPRETATION_BLACK_IS_ZERO * @see #PHOTOMETRIC_INTERPRETATION_RGB * @see #PHOTOMETRIC_INTERPRETATION_PALETTE_COLOR * @see #PHOTOMETRIC_INTERPRETATION_TRANSPARENCY_MASK * @see #PHOTOMETRIC_INTERPRETATION_Y_CB_CR * @see #PHOTOMETRIC_INTERPRETATION_CIELAB * @see #PHOTOMETRIC_INTERPRETATION_ICCLAB */ public static final int TAG_PHOTOMETRIC_INTERPRETATION = 262; /** * A value to be used with the "PhotometricInterpretation" tag. * * @see #TAG_PHOTOMETRIC_INTERPRETATION */ public static final int PHOTOMETRIC_INTERPRETATION_WHITE_IS_ZERO = 0; /** * A value to be used with the "PhotometricInterpretation" tag. * * @see #TAG_PHOTOMETRIC_INTERPRETATION */ public static final int PHOTOMETRIC_INTERPRETATION_BLACK_IS_ZERO = 1; /** * A value to be used with the "PhotometricInterpretation" tag. * * @see #TAG_PHOTOMETRIC_INTERPRETATION */ public static final int PHOTOMETRIC_INTERPRETATION_RGB = 2; /** * A value to be used with the "PhotometricInterpretation" tag. * * @see #TAG_PHOTOMETRIC_INTERPRETATION */ public static final int PHOTOMETRIC_INTERPRETATION_PALETTE_COLOR = 3; /** * A value to be used with the "PhotometricInterpretation" tag. * * @see #TAG_PHOTOMETRIC_INTERPRETATION */ public static final int PHOTOMETRIC_INTERPRETATION_TRANSPARENCY_MASK = 4; /** * A value to be used with the "PhotometricInterpretation" tag. * * @see #TAG_PHOTOMETRIC_INTERPRETATION */ public static final int PHOTOMETRIC_INTERPRETATION_CMYK = 5; /** * A value to be used with the "PhotometricInterpretation" tag. * * @see #TAG_PHOTOMETRIC_INTERPRETATION */ public static final int PHOTOMETRIC_INTERPRETATION_Y_CB_CR = 6; /** * A value to be used with the "PhotometricInterpretation" tag. * * @see #TAG_PHOTOMETRIC_INTERPRETATION */ public static final int PHOTOMETRIC_INTERPRETATION_CIELAB = 8; /** * A value to be used with the "PhotometricInterpretation" tag. * * @see #TAG_PHOTOMETRIC_INTERPRETATION * @see TIFF Specification Supplement 1 */ public static final int PHOTOMETRIC_INTERPRETATION_ICCLAB = 9; /** * Constant specifying the "Threshholding" tag. * * @see #THRESHHOLDING_NONE * @see #THRESHHOLDING_ORDERED_DITHER * @see #THRESHHOLDING_RANDOMIZED_DITHER */ public static final int TAG_THRESHHOLDING = 263; /** * A value to be used with the "Thresholding" tag. * * @see #TAG_THRESHHOLDING */ public static final int THRESHHOLDING_NONE = 1; /** * A value to be used with the "Thresholding" tag. * * @see #TAG_THRESHHOLDING */ public static final int THRESHHOLDING_ORDERED_DITHER = 2; /** * A value to be used with the "Thresholding" tag. * * @see #TAG_THRESHHOLDING */ public static final int THRESHHOLDING_RANDOMIZED_DITHER = 3; /** * Constant specifying the "Cell_Width" tag. */ public static final int TAG_CELL_WIDTH = 264; /** * Constant specifying the "cell_length" tag. */ public static final int TAG_CELL_LENGTH = 265; /** * Constant specifying the "fill_order" tag. * * @see #FILL_ORDER_LEFT_TO_RIGHT * @see #FILL_ORDER_RIGHT_TO_LEFT */ public static final int TAG_FILL_ORDER = 266; /** * A value to be used with the "FillOrder" tag. * * @see #TAG_FILL_ORDER */ public static final int FILL_ORDER_LEFT_TO_RIGHT = 1; /** * A value to be used with the "FillOrder" tag. * * @see #TAG_FILL_ORDER */ public static final int FILL_ORDER_RIGHT_TO_LEFT = 2; /** * Constant specifying the "document_name" tag. */ public static final int TAG_DOCUMENT_NAME = 269; /** * Constant specifying the "Image_description" tag. */ public static final int TAG_IMAGE_DESCRIPTION = 270; /** * Constant specifying the "Make" tag. */ public static final int TAG_MAKE = 271; /** * Constant specifying the "Model" tag. */ public static final int TAG_MODEL = 272; /** * Constant specifying the "Strip_offsets" tag. */ public static final int TAG_STRIP_OFFSETS = 273; /** * Constant specifying the "Orientation" tag. * * @see #ORIENTATION_ROW_0_TOP_COLUMN_0_LEFT * @see #ORIENTATION_ROW_0_TOP_COLUMN_0_RIGHT * @see #ORIENTATION_ROW_0_BOTTOM_COLUMN_0_RIGHT * @see #ORIENTATION_ROW_0_BOTTOM_COLUMN_0_LEFT * @see #ORIENTATION_ROW_0_LEFT_COLUMN_0_TOP * @see #ORIENTATION_ROW_0_RIGHT_COLUMN_0_TOP * @see #ORIENTATION_ROW_0_RIGHT_COLUMN_0_BOTTOM * @see #ORIENTATION_ROW_0_LEFT_COLUMN_0_BOTTOM */ public static final int TAG_ORIENTATION = 274; /** * A value to be used with the "Orientation" tag. * * @see #TAG_ORIENTATION */ public static final int ORIENTATION_ROW_0_TOP_COLUMN_0_LEFT = 1; /** * A value to be used with the "Orientation" tag. * * @see #TAG_ORIENTATION */ public static final int ORIENTATION_ROW_0_TOP_COLUMN_0_RIGHT = 2; /** * A value to be used with the "Orientation" tag. * * @see #TAG_ORIENTATION */ public static final int ORIENTATION_ROW_0_BOTTOM_COLUMN_0_RIGHT = 3; /** * A value to be used with the "Orientation" tag. * * @see #TAG_ORIENTATION */ public static final int ORIENTATION_ROW_0_BOTTOM_COLUMN_0_LEFT = 4; /** * A value to be used with the "Orientation" tag. * * @see #TAG_ORIENTATION */ public static final int ORIENTATION_ROW_0_LEFT_COLUMN_0_TOP = 5; /** * A value to be used with the "Orientation" tag. * * @see #TAG_ORIENTATION */ public static final int ORIENTATION_ROW_0_RIGHT_COLUMN_0_TOP = 6; /** * A value to be used with the "Orientation" tag. * * @see #TAG_ORIENTATION */ public static final int ORIENTATION_ROW_0_RIGHT_COLUMN_0_BOTTOM = 7; /** * A value to be used with the "Orientation" tag. * * @see #TAG_ORIENTATION */ public static final int ORIENTATION_ROW_0_LEFT_COLUMN_0_BOTTOM = 8; /** * Constant specifying the "Samples_per_pixel" tag. */ public static final int TAG_SAMPLES_PER_PIXEL = 277; /** * Constant specifying the "Rows_per_strip" tag. */ public static final int TAG_ROWS_PER_STRIP = 278; /** * Constant specifying the "Strip_byte_counts" tag. */ public static final int TAG_STRIP_BYTE_COUNTS = 279; /** * Constant specifying the "Min_sample_value" tag. */ public static final int TAG_MIN_SAMPLE_VALUE = 280; /** * Constant specifying the "Max_sample_value" tag. */ public static final int TAG_MAX_SAMPLE_VALUE = 281; /** * Constant specifying the "XResolution" tag. */ public static final int TAG_X_RESOLUTION = 282; /** * Constant specifying the "YResolution" tag. */ public static final int TAG_Y_RESOLUTION = 283; /** * Constant specifying the "PlanarConfiguration" tag. * * @see #PLANAR_CONFIGURATION_CHUNKY * @see #PLANAR_CONFIGURATION_PLANAR */ public static final int TAG_PLANAR_CONFIGURATION = 284; /** * A value to be used with the "PlanarConfiguration" tag. * * @see #TAG_PLANAR_CONFIGURATION */ public static final int PLANAR_CONFIGURATION_CHUNKY = 1; /** * A value to be used with the "PlanarConfiguration" tag. * * @see #TAG_PLANAR_CONFIGURATION */ public static final int PLANAR_CONFIGURATION_PLANAR = 2; /** * Constant specifying the "PageName" tag. */ public static final int TAG_PAGE_NAME = 285; /** * Constant specifying the "XPosition" tag. */ public static final int TAG_X_POSITION = 286; /** * Constant specifying the "YPosition" tag. */ public static final int TAG_Y_POSITION = 287; /** * Constant specifying the "FreeOffsets" tag. */ public static final int TAG_FREE_OFFSETS = 288; /** * Constant specifying the "FreeByteCounts" tag. */ public static final int TAG_FREE_BYTE_COUNTS = 289; /** * Constant specifying the "GrayResponseUnit" tag. * * @see #GRAY_RESPONSE_UNIT_TENTHS * @see #GRAY_RESPONSE_UNIT_HUNDREDTHS * @see #GRAY_RESPONSE_UNIT_THOUSANDTHS * @see #GRAY_RESPONSE_UNIT_TEN_THOUSANDTHS * @see #GRAY_RESPONSE_UNIT_HUNDRED_THOUSANDTHS */ public static final int TAG_GRAY_RESPONSE_UNIT = 290; /** * A value to be used with the "GrayResponseUnit" tag. * * @see #TAG_GRAY_RESPONSE_UNIT */ public static final int GRAY_RESPONSE_UNIT_TENTHS = 1; /** * A value to be used with the "GrayResponseUnit" tag. * * @see #TAG_GRAY_RESPONSE_UNIT */ public static final int GRAY_RESPONSE_UNIT_HUNDREDTHS = 2; /** * A value to be used with the "GrayResponseUnit" tag. * * @see #TAG_GRAY_RESPONSE_UNIT */ public static final int GRAY_RESPONSE_UNIT_THOUSANDTHS = 3; /** * A value to be used with the "GrayResponseUnit" tag. * * @see #TAG_GRAY_RESPONSE_UNIT */ public static final int GRAY_RESPONSE_UNIT_TEN_THOUSANDTHS = 4; /** * A value to be used with the "GrayResponseUnit" tag. * * @see #TAG_GRAY_RESPONSE_UNIT */ public static final int GRAY_RESPONSE_UNIT_HUNDRED_THOUSANDTHS = 5; /** * Constant specifying the "GrayResponseCurve" tag. */ public static final int TAG_GRAY_RESPONSE_CURVE = 291; /** * Constant specifying the "T4Options" tag. * * @see #T4_OPTIONS_2D_CODING * @see #T4_OPTIONS_UNCOMPRESSED * @see #T4_OPTIONS_EOL_BYTE_ALIGNED */ public static final int TAG_T4_OPTIONS = 292; /** * A mask to be used with the "T4Options" tag. * * @see #TAG_T4_OPTIONS */ public static final int T4_OPTIONS_2D_CODING = 1; /** * A mask to be used with the "T4Options" tag. * * @see #TAG_T4_OPTIONS */ public static final int T4_OPTIONS_UNCOMPRESSED = 2; /** * A mask to be used with the "T4Options" tag. * * @see #TAG_T4_OPTIONS */ public static final int T4_OPTIONS_EOL_BYTE_ALIGNED = 4; /** * Constant specifying the "T6Options" tag. * * @see #T6_OPTIONS_UNCOMPRESSED */ public static final int TAG_T6_OPTIONS = 293; /** * A mask to be used with the "T6Options" tag. * * @see #TAG_T6_OPTIONS */ public static final int T6_OPTIONS_UNCOMPRESSED = 2; /** * Constant specifying the "ResolutionUnit" tag. * * @see #RESOLUTION_UNIT_NONE * @see #RESOLUTION_UNIT_INCH * @see #RESOLUTION_UNIT_CENTIMETER */ public static final int TAG_RESOLUTION_UNIT = 296; /** * A value to be used with the "ResolutionUnit" tag. * * @see #TAG_RESOLUTION_UNIT */ public static final int RESOLUTION_UNIT_NONE = 1; /** * A value to be used with the "ResolutionUnit" tag. * * @see #TAG_RESOLUTION_UNIT */ public static final int RESOLUTION_UNIT_INCH = 2; /** * A value to be used with the "ResolutionUnit" tag. * * @see #TAG_RESOLUTION_UNIT */ public static final int RESOLUTION_UNIT_CENTIMETER = 3; /** * Constant specifying the "PageNumber" tag. */ public static final int TAG_PAGE_NUMBER = 297; /** * Constant specifying the "TransferFunction" tag. */ public static final int TAG_TRANSFER_FUNCTION = 301; /** * Constant specifying the "Software" tag. */ public static final int TAG_SOFTWARE = 305; /** * Constant specifying the "DateTime" tag. */ public static final int TAG_DATE_TIME = 306; /** * Constant specifying the "Artist" tag. */ public static final int TAG_ARTIST = 315; /** * Constant specifying the "HostComputer" tag. */ public static final int TAG_HOST_COMPUTER = 316; /** * Constant specifying the "Predictor" tag. * * @see #TAG_WHITE_POINT * @see #TAG_PRIMARY_CHROMATICITES * @see #TAG_COLOR_MAP * @see #TAG_HALFTONE_HINTS * @see #TAG_TILE_WIDTH * @see #TAG_TILE_LENGTH * @see #TAG_TILE_OFFSETS * @see #TAG_TILE_BYTE_COUNTS */ public static final int TAG_PREDICTOR = 317; /** * A value to be used with the "Predictor" tag. * * @see #TAG_PREDICTOR */ public static final int PREDICTOR_NONE = 1; /** * A value to be used with the "Predictor" tag. * * @see #TAG_PREDICTOR */ public static final int PREDICTOR_HORIZONTAL_DIFFERENCING = 2; /** * Constant specifying the "WhitePoint" tag. */ public static final int TAG_WHITE_POINT = 318; /** * Constant specifying the "PrimaryChromaticites" tag. */ public static final int TAG_PRIMARY_CHROMATICITES = 319; /** * Constant specifying the "ColorMap" tag. */ public static final int TAG_COLOR_MAP = 320; /** * Constant specifying the "HalftoneHints" tag. */ public static final int TAG_HALFTONE_HINTS = 321; /** * Constant specifying the "TileWidth" tag. */ public static final int TAG_TILE_WIDTH = 322; /** * Constant specifying the "TileLength" tag. */ public static final int TAG_TILE_LENGTH = 323; /** * Constant specifying the "TileOffsets" tag. */ public static final int TAG_TILE_OFFSETS = 324; /** * Constant specifying the "TileByteCounts" tag. */ public static final int TAG_TILE_BYTE_COUNTS = 325; /** * Constant specifying the "InkSet" tag. * * @see #INK_SET_CMYK * @see #INK_SET_NOT_CMYK */ public static final int TAG_INK_SET = 332; /** * A value to be used with the "InkSet" tag. * * @see #TAG_INK_SET */ public static final int INK_SET_CMYK = 1; /** * A value to be used with the "InkSet" tag. * * @see #TAG_INK_SET */ public static final int INK_SET_NOT_CMYK = 2; /** * Constant specifying the "InkNames" tag. */ public static final int TAG_INK_NAMES = 333; /** * Constant specifying the "NumberOfInks" tag. */ public static final int TAG_NUMBER_OF_INKS = 334; /** * Constant specifying the "DotRange" tag. */ public static final int TAG_DOT_RANGE = 336; /** * Constant specifying the "TargetPrinter" tag. */ public static final int TAG_TARGET_PRINTER = 337; /** * Constant specifying the "ExtraSamples" tag. * * @see #EXTRA_SAMPLES_UNSPECIFIED * @see #EXTRA_SAMPLES_ASSOCIATED_ALPHA * @see #EXTRA_SAMPLES_UNASSOCIATED_ALPHA */ public static final int TAG_EXTRA_SAMPLES = 338; /** * A value to be used with the "ExtraSamples" tag. * * @see #TAG_EXTRA_SAMPLES */ public static final int EXTRA_SAMPLES_UNSPECIFIED = 0; /** * A value to be used with the "ExtraSamples" tag. * * @see #TAG_EXTRA_SAMPLES */ public static final int EXTRA_SAMPLES_ASSOCIATED_ALPHA = 1; /** * A value to be used with the "ExtraSamples" tag. * * @see #TAG_EXTRA_SAMPLES */ public static final int EXTRA_SAMPLES_UNASSOCIATED_ALPHA = 2; /** * Constant specifying the "SampleFormat" tag. * * @see #SAMPLE_FORMAT_UNSIGNED_INTEGER * @see #SAMPLE_FORMAT_SIGNED_INTEGER * @see #SAMPLE_FORMAT_FLOATING_POINT * @see #SAMPLE_FORMAT_UNDEFINED */ public static final int TAG_SAMPLE_FORMAT = 339; /** * A value to be used with the "SampleFormat" tag. * * @see #TAG_SAMPLE_FORMAT */ public static final int SAMPLE_FORMAT_UNSIGNED_INTEGER = 1; /** * A value to be used with the "SampleFormat" tag. * * @see #TAG_SAMPLE_FORMAT */ public static final int SAMPLE_FORMAT_SIGNED_INTEGER = 2; /** * A value to be used with the "SampleFormat" tag. * * @see #TAG_SAMPLE_FORMAT */ public static final int SAMPLE_FORMAT_FLOATING_POINT = 3; /** * A value to be used with the "SampleFormat" tag. * * @see #TAG_SAMPLE_FORMAT */ public static final int SAMPLE_FORMAT_UNDEFINED = 4; /** * Constant specifying the "SMinSampleValue" tag. */ public static final int TAG_S_MIN_SAMPLE_VALUE = 340; /** * Constant specifying the "SMaxSampleValue" tag. */ public static final int TAG_S_MAX_SAMPLE_VALUE = 341; /** * Constant specifying the "TransferRange" tag. */ public static final int TAG_TRANSFER_RANGE = 342; /** * Constant specifying the "JPEGTables" tag. * * @see TIFF Specification Supplement 2 * @see JPEG-in-TIFF compression */ public static final int TAG_JPEG_TABLES = 347; /** * Constant specifying the "JPEGProc" tag. */ public static final int TAG_JPEG_PROC = 512; /** * A value to be used with the "JPEGProc" tag. * * @see #TAG_JPEG_PROC */ public static final int JPEG_PROC_BASELINE = 1; /** * A value to be used with the "JPEGProc" tag. * * @see #TAG_JPEG_PROC */ public static final int JPEG_PROC_LOSSLESS = 14; /** * Constant specifying the "JPEGInterchangeFormat" tag. */ public static final int TAG_JPEG_INTERCHANGE_FORMAT = 513; /** * Constant specifying the "JPEGInterchangeFormatLength" tag. */ public static final int TAG_JPEG_INTERCHANGE_FORMAT_LENGTH = 514; /** * Constant specifying the "JPEGRestartInterval" tag. */ public static final int TAG_JPEG_RESTART_INTERVAL = 515; /** * Constant specifying the "JPEGLosslessPredictors" tag. */ public static final int TAG_JPEG_LOSSLESS_PREDICTORS = 517; /** * Constant specifying the "JPEGPointTransforms" tag. */ public static final int TAG_JPEG_POINT_TRANSFORMS = 518; /** * Constant specifying the "JPEGQTables" tag. */ public static final int TAG_JPEG_Q_TABLES = 519; /** * Constant specifying the "JPEGDCTables" tag. */ public static final int TAG_JPEG_DC_TABLES = 520; /** * Constant specifying the "JPEGACTables" tag. */ public static final int TAG_JPEG_AC_TABLES = 521; /** * Constant specifying the "YCbCrCoefficients" tag. */ public static final int TAG_Y_CB_CR_COEFFICIENTS = 529; /** * Constant specifying the "YCbCrSubsampling" tag. */ public static final int TAG_Y_CB_CR_SUBSAMPLING = 530; /** * Constant specifying the "YCbCrPositioning" tag. * * @see #Y_CB_CR_POSITIONING_CENTERED * @see #Y_CB_CR_POSITIONING_COSITED */ public static final int TAG_Y_CB_CR_POSITIONING = 531; /** * A value to be used with the "YCbCrPositioning" tag. * * @see #TAG_Y_CB_CR_POSITIONING */ public static final int Y_CB_CR_POSITIONING_CENTERED = 1; /** * A value to be used with the "YCbCrPositioning" tag. * * @see #TAG_Y_CB_CR_POSITIONING */ public static final int Y_CB_CR_POSITIONING_COSITED = 2; /** * Constant specifying the "ReferenceBlackWhite" tag. */ public static final int TAG_REFERENCE_BLACK_WHITE = 532; /** * Constant specifying the "Copyright" tag. */ public static final int TAG_COPYRIGHT = 33432; // Common non-baseline tags // ICC profiles (Spec ICC 1:2001-04, Appendix B) // 34675 - Embedded ICC Profile (UNDEFINED/any) /** * Constant specifying the "ICC Profile" tag. * * @see ICC Specification, section B.4: Embedding ICC profiles in TIFF files */ public static final int TAG_ICC_PROFILE = 34675; // Artist static class Artist extends TIFFTag { public Artist() { super("Artist", TAG_ARTIST, 1 << TIFF_ASCII); } } // BitsPerSample static class BitsPerSample extends TIFFTag { public BitsPerSample() { super("BitsPerSample", TAG_BITS_PER_SAMPLE, 1 << TIFF_SHORT); } } // CellLength static class CellLength extends TIFFTag { public CellLength() { super("CellLength", TAG_CELL_LENGTH, 1 << TIFF_SHORT); } } // CellWidth tag static class CellWidth extends TIFFTag { public CellWidth() { super("CellWidth", TAG_CELL_WIDTH, 1 << TIFF_SHORT); } } // ColorMap static class ColorMap extends TIFFTag { public ColorMap() { super("ColorMap", TAG_COLOR_MAP, 1 << TIFF_SHORT); } } // Compression static class Compression extends TIFFTag { public Compression() { super("Compression", TAG_COMPRESSION, 1 << TIFF_SHORT); addValueName(COMPRESSION_NONE, "Uncompressed"); addValueName(COMPRESSION_CCITT_RLE, "CCITT RLE"); addValueName(COMPRESSION_CCITT_T_4, "CCITT T.4"); addValueName(COMPRESSION_CCITT_T_6, "CCITT T.6"); addValueName(COMPRESSION_LZW, "LZW"); addValueName(COMPRESSION_OLD_JPEG, "Old JPEG"); addValueName(COMPRESSION_JPEG, "JPEG"); addValueName(COMPRESSION_ZLIB, "ZLib"); addValueName(COMPRESSION_PACKBITS, "PackBits"); addValueName(COMPRESSION_DEFLATE, "Deflate"); // Non-baseline // 32771 CCITT // 32809 ThunderScan // 32766 NeXT // 32909 Pixar // 34676 SGI // 34677 SGI } } // Copyright static class Copyright extends TIFFTag { public Copyright() { super("Copyright", TAG_COPYRIGHT, 1 << TIFF_ASCII); } } // DateTime static class DateTime extends TIFFTag { public DateTime() { super("DateTime", TAG_DATE_TIME, 1 << TIFF_ASCII); } } // DocumentName static class DocumentName extends TIFFTag { public DocumentName() { super("DocumentName", TAG_DOCUMENT_NAME, 1 << TIFF_ASCII); } } // DotRange static class DotRange extends TIFFTag { public DotRange() { super("DotRange", TAG_DOT_RANGE, (1 << TIFF_BYTE) | (1 << TIFF_SHORT)); } } // ExtraSamples static class ExtraSamples extends TIFFTag { public ExtraSamples() { super("ExtraSamples", TAG_EXTRA_SAMPLES, 1 << TIFF_SHORT); addValueName(EXTRA_SAMPLES_UNSPECIFIED, "Unspecified"); addValueName(EXTRA_SAMPLES_ASSOCIATED_ALPHA, "Associated Alpha"); addValueName(EXTRA_SAMPLES_UNASSOCIATED_ALPHA, "Unassociated Alpha"); } } // FillOrder static class FillOrder extends TIFFTag { public FillOrder() { super("FillOrder", TAG_FILL_ORDER, 1 << TIFF_SHORT); addValueName(FILL_ORDER_LEFT_TO_RIGHT, "LeftToRight"); addValueName(FILL_ORDER_RIGHT_TO_LEFT, "RightToLeft"); } } // FreeByteCounts static class FreeByteCounts extends TIFFTag { public FreeByteCounts() { super("FreeByteCounts", TAG_FREE_BYTE_COUNTS, 1 << TIFF_LONG); } } // FreeOffsets static class FreeOffsets extends TIFFTag { public FreeOffsets() { super("FreeOffsets", TAG_FREE_OFFSETS, 1 << TIFF_LONG); } } // GrayResponseCurve static class GrayResponseCurve extends TIFFTag { public GrayResponseCurve() { super("GrayResponseCurve", TAG_GRAY_RESPONSE_CURVE, 1 << TIFF_SHORT); } } // GrayResponseUnit static class GrayResponseUnit extends TIFFTag { public GrayResponseUnit() { super("GrayResponseUnit", TAG_GRAY_RESPONSE_UNIT, 1 << TIFF_SHORT); addValueName(GRAY_RESPONSE_UNIT_TENTHS, "Tenths"); addValueName(GRAY_RESPONSE_UNIT_HUNDREDTHS, "Hundredths"); addValueName(GRAY_RESPONSE_UNIT_THOUSANDTHS, "Thousandths"); addValueName(GRAY_RESPONSE_UNIT_TEN_THOUSANDTHS, "Ten-Thousandths"); addValueName(GRAY_RESPONSE_UNIT_HUNDRED_THOUSANDTHS, "Hundred-Thousandths"); } } // HalftoneHints static class HalftoneHints extends TIFFTag { public HalftoneHints() { super("HalftoneHints", TAG_HALFTONE_HINTS, 1 << TIFF_SHORT); } } // HostComputer static class HostComputer extends TIFFTag { public HostComputer() { super("HostComputer", TAG_HOST_COMPUTER, 1 << TIFF_ASCII); } } // ImageDescription static class ImageDescription extends TIFFTag { public ImageDescription() { super("ImageDescription", TAG_IMAGE_DESCRIPTION, 1 << TIFF_ASCII); } } // ImageLength tag static class ImageLength extends TIFFTag { public ImageLength() { super("ImageLength", TAG_IMAGE_LENGTH, (1 << TIFF_SHORT) | (1 << TIFF_LONG)); } } // ImageWidth tag static class ImageWidth extends TIFFTag { public ImageWidth() { super("ImageWidth", TAG_IMAGE_WIDTH, (1 << TIFF_SHORT) | (1 << TIFF_LONG)); } } // InkNames static class InkNames extends TIFFTag { public InkNames() { super("InkNames", TAG_INK_NAMES, 1 << TIFF_ASCII); } } // InkSet static class InkSet extends TIFFTag { public InkSet() { super("InkSet", TAG_INK_SET, 1 << TIFF_SHORT); addValueName(INK_SET_CMYK, "CMYK"); addValueName(INK_SET_NOT_CMYK, "Not CMYK"); } } // JPEGTables (Tech note) static class JPEGTables extends TIFFTag { public JPEGTables() { super("JPEGTables", TAG_JPEG_TABLES, 1 << TIFF_UNDEFINED); } } // JPEGACTables static class JPEGACTables extends TIFFTag { public JPEGACTables() { super("JPEGACTables", TAG_JPEG_AC_TABLES, 1 << TIFF_LONG); } } // JPEGDCTables static class JPEGDCTables extends TIFFTag { public JPEGDCTables() { super("JPEGDCTables", TAG_JPEG_DC_TABLES, 1 << TIFF_LONG); } } // JPEGInterchangeFormat static class JPEGInterchangeFormat extends TIFFTag { public JPEGInterchangeFormat() { super("JPEGInterchangeFormat", TAG_JPEG_INTERCHANGE_FORMAT, 1 << TIFF_LONG); } } // JPEGInterchangeFormatLength static class JPEGInterchangeFormatLength extends TIFFTag { public JPEGInterchangeFormatLength() { super("JPEGInterchangeFormatLength", TAG_JPEG_INTERCHANGE_FORMAT_LENGTH, 1 << TIFF_LONG); } } // JPEGLosslessPredictors static class JPEGLosslessPredictors extends TIFFTag { public JPEGLosslessPredictors() { super("JPEGLosslessPredictors", TAG_JPEG_LOSSLESS_PREDICTORS, 1 << TIFF_SHORT); addValueName(1, "A"); addValueName(2, "B"); addValueName(3, "C"); addValueName(4, "A+B-C"); addValueName(5, "A+((B-C)/2)"); addValueName(6, "B+((A-C)/2)"); addValueName(7, "(A+B)/2"); } } // JPEGPointTransforms static class JPEGPointTransforms extends TIFFTag { public JPEGPointTransforms() { super("JPEGPointTransforms", TAG_JPEG_POINT_TRANSFORMS, 1 << TIFF_SHORT); } } // JPEGProc static class JPEGProc extends TIFFTag { public JPEGProc() { super("JPEGProc", TAG_JPEG_PROC, 1 << TIFF_SHORT); addValueName(JPEG_PROC_BASELINE, "Baseline sequential process"); addValueName(JPEG_PROC_LOSSLESS, "Lossless process with Huffman coding"); } } // JPEGQTables static class JPEGQTables extends TIFFTag { public JPEGQTables() { super("JPEGQTables", TAG_JPEG_Q_TABLES, 1 << TIFF_LONG); } } // JPEGRestartInterval static class JPEGRestartInterval extends TIFFTag { public JPEGRestartInterval() { super("JPEGRestartInterval", TAG_JPEG_RESTART_INTERVAL, 1 << TIFF_SHORT); } } // Make static class Make extends TIFFTag { public Make() { super("Make", TAG_MAKE, 1 << TIFF_ASCII); } } // MaxSampleValue static class MaxSampleValue extends TIFFTag { public MaxSampleValue() { super("MaxSampleValue", TAG_MAX_SAMPLE_VALUE, 1 << TIFF_SHORT); } } // MinSampleValue static class MinSampleValue extends TIFFTag { public MinSampleValue() { super("MinSampleValue", TAG_MIN_SAMPLE_VALUE, 1 << TIFF_SHORT); } } // Model static class Model extends TIFFTag { public Model() { super("Model", TAG_MODEL, 1 << TIFF_ASCII); } } // NewSubfileType static class NewSubfileType extends TIFFTag { public NewSubfileType() { super("NewSubfileType", TAG_NEW_SUBFILE_TYPE, 1 << TIFF_LONG); addValueName(0, "Default"); addValueName(NEW_SUBFILE_TYPE_REDUCED_RESOLUTION, "ReducedResolution"); addValueName(NEW_SUBFILE_TYPE_SINGLE_PAGE, "SinglePage"); addValueName(NEW_SUBFILE_TYPE_SINGLE_PAGE | NEW_SUBFILE_TYPE_REDUCED_RESOLUTION, "SinglePage+ReducedResolution"); addValueName(NEW_SUBFILE_TYPE_TRANSPARENCY, "Transparency"); addValueName(NEW_SUBFILE_TYPE_TRANSPARENCY | NEW_SUBFILE_TYPE_REDUCED_RESOLUTION, "Transparency+ReducedResolution"); addValueName(NEW_SUBFILE_TYPE_TRANSPARENCY | NEW_SUBFILE_TYPE_SINGLE_PAGE, "Transparency+SinglePage"); addValueName(NEW_SUBFILE_TYPE_TRANSPARENCY | NEW_SUBFILE_TYPE_SINGLE_PAGE | NEW_SUBFILE_TYPE_REDUCED_RESOLUTION, "Transparency+SinglePage+ReducedResolution"); } } // NumberOfInks static class NumberOfInks extends TIFFTag { public NumberOfInks() { super("NumberOfInks", TAG_NUMBER_OF_INKS, 1 << TIFF_SHORT); } } // Orientation static class Orientation extends TIFFTag { public Orientation() { super("Orientation", TAG_ORIENTATION, 1 << TIFF_SHORT); addValueName(ORIENTATION_ROW_0_TOP_COLUMN_0_LEFT, "Row 0=Top, Column 0=Left"); addValueName(ORIENTATION_ROW_0_TOP_COLUMN_0_RIGHT, "Row 0=Top, Column 0=Right"); addValueName(ORIENTATION_ROW_0_BOTTOM_COLUMN_0_RIGHT, "Row 0=Bottom, Column 0=Right"); addValueName(ORIENTATION_ROW_0_BOTTOM_COLUMN_0_LEFT, "Row 0=Bottom, Column 0=Left"); addValueName(ORIENTATION_ROW_0_LEFT_COLUMN_0_TOP, "Row 0=Left, Column 0=Top"); addValueName(ORIENTATION_ROW_0_RIGHT_COLUMN_0_TOP, "Row 0=Right, Column 0=Top"); addValueName(ORIENTATION_ROW_0_RIGHT_COLUMN_0_BOTTOM, "Row 0=Right, Column 0=Bottom"); } } // PageName static class PageName extends TIFFTag { public PageName() { super("PageName", TAG_PAGE_NAME, 1 << TIFF_ASCII); } } // PageNumber static class PageNumber extends TIFFTag { public PageNumber() { super("PageNumber", TAG_PAGE_NUMBER, 1 << TIFF_SHORT); } } // PhotometricInterpretation static class PhotometricInterpretation extends TIFFTag { public PhotometricInterpretation() { super("PhotometricInterpretation", TAG_PHOTOMETRIC_INTERPRETATION, 1 << TIFF_SHORT); addValueName(PHOTOMETRIC_INTERPRETATION_WHITE_IS_ZERO, "WhiteIsZero"); addValueName(PHOTOMETRIC_INTERPRETATION_BLACK_IS_ZERO, "BlackIsZero"); addValueName(PHOTOMETRIC_INTERPRETATION_RGB, "RGB"); addValueName(PHOTOMETRIC_INTERPRETATION_PALETTE_COLOR, "Palette Color"); addValueName(PHOTOMETRIC_INTERPRETATION_TRANSPARENCY_MASK, "Transparency Mask"); addValueName(PHOTOMETRIC_INTERPRETATION_CMYK, "CMYK"); addValueName(PHOTOMETRIC_INTERPRETATION_Y_CB_CR, "YCbCr"); addValueName(PHOTOMETRIC_INTERPRETATION_CIELAB, "CIELAB"); addValueName(PHOTOMETRIC_INTERPRETATION_ICCLAB, "ICCLAB"); // Non-baseline } } // PlanarConfiguration static class PlanarConfiguration extends TIFFTag { public PlanarConfiguration() { super("PlanarConfiguration", TAG_PLANAR_CONFIGURATION, 1 << TIFF_SHORT); addValueName(PLANAR_CONFIGURATION_CHUNKY, "Chunky"); addValueName(PLANAR_CONFIGURATION_PLANAR, "Planar"); } } // Predictor static class Predictor extends TIFFTag { public Predictor() { super("Predictor", TAG_PREDICTOR, 1 << TIFF_SHORT); addValueName(PREDICTOR_NONE, "None"); addValueName(PREDICTOR_HORIZONTAL_DIFFERENCING, "Horizontal Differencing"); } } // PrimaryChromaticities static class PrimaryChromaticities extends TIFFTag { public PrimaryChromaticities() { super("PrimaryChromaticities", TAG_PRIMARY_CHROMATICITES, 1 << TIFF_RATIONAL); } } // ReferenceBlackWhite static class ReferenceBlackWhite extends TIFFTag { public ReferenceBlackWhite() { super("ReferenceBlackWhite", TAG_REFERENCE_BLACK_WHITE, 1 << TIFF_RATIONAL); } } // ResolutionUnit static class ResolutionUnit extends TIFFTag { public ResolutionUnit() { super("ResolutionUnit", TAG_RESOLUTION_UNIT, 1 << TIFF_SHORT); addValueName(RESOLUTION_UNIT_NONE, "None"); addValueName(RESOLUTION_UNIT_INCH, "Inch"); addValueName(RESOLUTION_UNIT_CENTIMETER, "Centimeter"); } } // RowsPerStrip static class RowsPerStrip extends TIFFTag { public RowsPerStrip() { super("RowsPerStrip", TAG_ROWS_PER_STRIP, (1 << TIFF_SHORT) | (1 << TIFF_LONG)); } } // SampleFormat static class SampleFormat extends TIFFTag { public SampleFormat() { super("SampleFormat", TAG_SAMPLE_FORMAT, 1 << TIFF_SHORT); addValueName(SAMPLE_FORMAT_UNSIGNED_INTEGER, "Unsigned Integer"); addValueName(SAMPLE_FORMAT_SIGNED_INTEGER, "Signed Integer"); addValueName(SAMPLE_FORMAT_FLOATING_POINT, "Floating Point"); addValueName(SAMPLE_FORMAT_UNDEFINED, "Undefined"); } } // SamplesPerPixel static class SamplesPerPixel extends TIFFTag { public SamplesPerPixel() { super("SamplesPerPixel", TAG_SAMPLES_PER_PIXEL, 1 << TIFF_SHORT); } } // SMaxSampleValue static class SMaxSampleValue extends TIFFTag { public SMaxSampleValue() { super("SMaxSampleValue", TAG_S_MAX_SAMPLE_VALUE, (1 << TIFF_BYTE) | (1 << TIFF_SHORT) | (1 << TIFF_LONG) | (1 << TIFF_RATIONAL) | (1 << TIFF_SBYTE) | (1 << TIFF_SSHORT) | (1 << TIFF_SLONG) | (1 << TIFF_SRATIONAL) | (1 << TIFF_FLOAT) | (1 << TIFF_DOUBLE)); } } // SMinSampleValue static class SMinSampleValue extends TIFFTag { public SMinSampleValue() { super("SMinSampleValue", TAG_S_MIN_SAMPLE_VALUE, (1 << TIFF_BYTE) | (1 << TIFF_SHORT) | (1 << TIFF_LONG) | (1 << TIFF_RATIONAL) | (1 << TIFF_SBYTE) | (1 << TIFF_SSHORT) | (1 << TIFF_SLONG) | (1 << TIFF_SRATIONAL) | (1 << TIFF_FLOAT) | (1 << TIFF_DOUBLE)); } } // Software static class Software extends TIFFTag { public Software() { super("Software", TAG_SOFTWARE, 1 << TIFF_ASCII); } } // StripByteCounts static class StripByteCounts extends TIFFTag { public StripByteCounts() { super("StripByteCounts", TAG_STRIP_BYTE_COUNTS, (1 << TIFF_SHORT) | (1 << TIFF_LONG)); } } // StripOffsets static class StripOffsets extends TIFFTag { public StripOffsets() { super("StripOffsets", TAG_STRIP_OFFSETS, (1 << TIFF_SHORT) | (1 << TIFF_LONG)); } } // SubfileType (deprecated) static class SubfileType extends TIFFTag { public SubfileType() { super("SubfileType", TAG_SUBFILE_TYPE, 1 << TIFF_SHORT); addValueName(SUBFILE_TYPE_FULL_RESOLUTION, "FullResolution"); addValueName(SUBFILE_TYPE_REDUCED_RESOLUTION, "ReducedResolution"); addValueName(SUBFILE_TYPE_SINGLE_PAGE, "SinglePage"); } } // T4Options static class T4Options extends TIFFTag { public T4Options() { super("T4Options", TAG_T4_OPTIONS, 1 << TIFF_LONG); addValueName(0, "Default 1DCoding"); // 0x00 addValueName(T4_OPTIONS_2D_CODING, "2DCoding"); // 0x01 addValueName(T4_OPTIONS_UNCOMPRESSED, "Uncompressed"); // 0x02 addValueName(T4_OPTIONS_2D_CODING | T4_OPTIONS_UNCOMPRESSED, "2DCoding+Uncompressed"); // 0x03 addValueName(T4_OPTIONS_EOL_BYTE_ALIGNED, "EOLByteAligned"); // 0x04 addValueName(T4_OPTIONS_2D_CODING | T4_OPTIONS_EOL_BYTE_ALIGNED, "2DCoding+EOLByteAligned"); // 0x05 addValueName(T4_OPTIONS_UNCOMPRESSED | T4_OPTIONS_EOL_BYTE_ALIGNED, "Uncompressed+EOLByteAligned"); // 0x06 addValueName(T4_OPTIONS_2D_CODING | T4_OPTIONS_UNCOMPRESSED | T4_OPTIONS_EOL_BYTE_ALIGNED, "2DCoding+Uncompressed+EOLByteAligned"); // 0x07 } } // T6Options static class T6Options extends TIFFTag { public T6Options() { super("T6Options", TAG_T6_OPTIONS, 1 << TIFF_LONG); addValueName(0, "Default"); // 0x00 // 0x01 is not possible as bit 0 is unused and always zero. addValueName(T6_OPTIONS_UNCOMPRESSED, "Uncompressed"); // 0x02 } } // TargetPrinter static class TargetPrinter extends TIFFTag { public TargetPrinter() { super("TargetPrinter", TAG_TARGET_PRINTER, 1 << TIFF_ASCII); } } // Threshholding static class Threshholding extends TIFFTag { public Threshholding() { super("Threshholding", TAG_THRESHHOLDING, 1 << TIFF_SHORT); addValueName(1, "None"); addValueName(2, "OrderedDither"); addValueName(3, "RandomizedDither"); } } // TileByteCounts static class TileByteCounts extends TIFFTag { public TileByteCounts() { super("TileByteCounts", TAG_TILE_BYTE_COUNTS, (1 << TIFF_SHORT) | (1 << TIFF_LONG)); } } // TileOffsets static class TileOffsets extends TIFFTag { public TileOffsets() { super("TileOffsets", TAG_TILE_OFFSETS, 1 << TIFF_LONG); } } // TileLength tag static class TileLength extends TIFFTag { public TileLength() { super("TileLength", TAG_TILE_LENGTH, (1 << TIFF_SHORT) | (1 << TIFF_LONG)); } } // TileWidth tag static class TileWidth extends TIFFTag { public TileWidth() { super("TileWidth", TAG_TILE_WIDTH, (1 << TIFF_SHORT) | (1 << TIFF_LONG)); } } // TransferFunction static class TransferFunction extends TIFFTag { public TransferFunction() { super("TransferFunction", TAG_TRANSFER_FUNCTION, 1 << TIFF_SHORT); } } // TransferRange static class TransferRange extends TIFFTag { public TransferRange() { super("TransferRange", TAG_TRANSFER_RANGE, 1 << TIFF_SHORT); } } // WhitePoint static class WhitePoint extends TIFFTag { public WhitePoint() { super("WhitePoint", TAG_WHITE_POINT, 1 << TIFF_RATIONAL); } } // XPosition static class XPosition extends TIFFTag { public XPosition() { super("XPosition", TAG_X_POSITION, 1 << TIFF_RATIONAL); } } // XResolution static class XResolution extends TIFFTag { public XResolution() { super("XResolution", TAG_X_RESOLUTION, 1 << TIFF_RATIONAL); } } // YCbCrCoefficients static class YCbCrCoefficients extends TIFFTag { public YCbCrCoefficients() { super("YCbCrCoefficients", TAG_Y_CB_CR_COEFFICIENTS, 1 << TIFF_RATIONAL); } } // YCbCrPositioning static class YCbCrPositioning extends TIFFTag { public YCbCrPositioning() { super("YCbCrPositioning", TAG_Y_CB_CR_POSITIONING, 1 << TIFF_SHORT); addValueName(Y_CB_CR_POSITIONING_CENTERED, "Centered"); addValueName(Y_CB_CR_POSITIONING_COSITED, "Cosited"); } } // YCbCrSubSampling static class YCbCrSubSampling extends TIFFTag { public YCbCrSubSampling() { super("YCbCrSubSampling", TAG_Y_CB_CR_SUBSAMPLING, 1 << TIFF_SHORT); } } // YPosition static class YPosition extends TIFFTag { public YPosition() { super("YPosition", TAG_Y_POSITION, 1 << TIFF_RATIONAL); } } // YResolution static class YResolution extends TIFFTag { public YResolution() { super("YResolution", TAG_Y_RESOLUTION, 1 << TIFF_RATIONAL); } } // Non-6.0 tags // ICC Profile (Spec. ICC.1:2001-12, File Format for Color Profiles) static class ICCProfile extends TIFFTag { public ICCProfile() { super("ICC Profile", TAG_ICC_PROFILE, 1 << TIFF_UNDEFINED); } } private static List tags; private static void initTags() { tags = new ArrayList(76); tags.add(new BaselineTIFFTagSet.Artist()); tags.add(new BaselineTIFFTagSet.BitsPerSample()); tags.add(new BaselineTIFFTagSet.CellLength()); tags.add(new BaselineTIFFTagSet.CellWidth()); tags.add(new BaselineTIFFTagSet.ColorMap()); tags.add(new BaselineTIFFTagSet.Compression()); tags.add(new BaselineTIFFTagSet.Copyright()); tags.add(new BaselineTIFFTagSet.DateTime()); tags.add(new BaselineTIFFTagSet.DocumentName()); tags.add(new BaselineTIFFTagSet.DotRange()); tags.add(new BaselineTIFFTagSet.ExtraSamples()); tags.add(new BaselineTIFFTagSet.FillOrder()); tags.add(new BaselineTIFFTagSet.FreeByteCounts()); tags.add(new BaselineTIFFTagSet.FreeOffsets()); tags.add(new BaselineTIFFTagSet.GrayResponseCurve()); tags.add(new BaselineTIFFTagSet.GrayResponseUnit()); tags.add(new BaselineTIFFTagSet.HalftoneHints()); tags.add(new BaselineTIFFTagSet.HostComputer()); tags.add(new BaselineTIFFTagSet.ImageDescription()); tags.add(new BaselineTIFFTagSet.ICCProfile()); tags.add(new BaselineTIFFTagSet.ImageLength()); tags.add(new BaselineTIFFTagSet.ImageWidth()); tags.add(new BaselineTIFFTagSet.InkNames()); tags.add(new BaselineTIFFTagSet.InkSet()); tags.add(new BaselineTIFFTagSet.JPEGACTables()); tags.add(new BaselineTIFFTagSet.JPEGDCTables()); tags.add(new BaselineTIFFTagSet.JPEGInterchangeFormat()); tags.add(new BaselineTIFFTagSet.JPEGInterchangeFormatLength()); tags.add(new BaselineTIFFTagSet.JPEGLosslessPredictors()); tags.add(new BaselineTIFFTagSet.JPEGPointTransforms()); tags.add(new BaselineTIFFTagSet.JPEGProc()); tags.add(new BaselineTIFFTagSet.JPEGQTables()); tags.add(new BaselineTIFFTagSet.JPEGRestartInterval()); tags.add(new BaselineTIFFTagSet.JPEGTables()); tags.add(new BaselineTIFFTagSet.Make()); tags.add(new BaselineTIFFTagSet.MaxSampleValue()); tags.add(new BaselineTIFFTagSet.MinSampleValue()); tags.add(new BaselineTIFFTagSet.Model()); tags.add(new BaselineTIFFTagSet.NewSubfileType()); tags.add(new BaselineTIFFTagSet.NumberOfInks()); tags.add(new BaselineTIFFTagSet.Orientation()); tags.add(new BaselineTIFFTagSet.PageName()); tags.add(new BaselineTIFFTagSet.PageNumber()); tags.add(new BaselineTIFFTagSet.PhotometricInterpretation()); tags.add(new BaselineTIFFTagSet.PlanarConfiguration()); tags.add(new BaselineTIFFTagSet.Predictor()); tags.add(new BaselineTIFFTagSet.PrimaryChromaticities()); tags.add(new BaselineTIFFTagSet.ReferenceBlackWhite()); tags.add(new BaselineTIFFTagSet.ResolutionUnit()); tags.add(new BaselineTIFFTagSet.RowsPerStrip()); tags.add(new BaselineTIFFTagSet.SampleFormat()); tags.add(new BaselineTIFFTagSet.SamplesPerPixel()); tags.add(new BaselineTIFFTagSet.SMaxSampleValue()); tags.add(new BaselineTIFFTagSet.SMinSampleValue()); tags.add(new BaselineTIFFTagSet.Software()); tags.add(new BaselineTIFFTagSet.StripByteCounts()); tags.add(new BaselineTIFFTagSet.StripOffsets()); tags.add(new BaselineTIFFTagSet.SubfileType()); tags.add(new BaselineTIFFTagSet.T4Options()); tags.add(new BaselineTIFFTagSet.T6Options()); tags.add(new BaselineTIFFTagSet.TargetPrinter()); tags.add(new BaselineTIFFTagSet.Threshholding()); tags.add(new BaselineTIFFTagSet.TileByteCounts()); tags.add(new BaselineTIFFTagSet.TileOffsets()); tags.add(new BaselineTIFFTagSet.TileLength()); tags.add(new BaselineTIFFTagSet.TileWidth()); tags.add(new BaselineTIFFTagSet.TransferFunction()); tags.add(new BaselineTIFFTagSet.TransferRange()); tags.add(new BaselineTIFFTagSet.WhitePoint()); tags.add(new BaselineTIFFTagSet.XPosition()); tags.add(new BaselineTIFFTagSet.XResolution()); tags.add(new BaselineTIFFTagSet.YCbCrCoefficients()); tags.add(new BaselineTIFFTagSet.YCbCrPositioning()); tags.add(new BaselineTIFFTagSet.YCbCrSubSampling()); tags.add(new BaselineTIFFTagSet.YPosition()); tags.add(new BaselineTIFFTagSet.YResolution()); } private BaselineTIFFTagSet() { super(tags); } /** * Returns a shared instance of a BaselineTIFFTagSet. * * @return a BaselineTIFFTagSet instance. */ public synchronized static BaselineTIFFTagSet getInstance() { if (theInstance == null) { initTags(); theInstance = new BaselineTIFFTagSet(); tags = null; } return theInstance; } } jai-imageio-core-1.2/src/share/classes/com/sun/media/imageio/plugins/tiff/TIFFDirectory.java0000664000175100017510000004426310473440561030775 0ustar tilletille/* * $RCSfile: TIFFDirectory.java,v $ * * * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.4 $ * $Date: 2006-08-25 00:16:49 $ * $State: Exp $ */ package com.sun.media.imageio.plugins.tiff; import java.util.ArrayList; import java.util.Arrays; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.NoSuchElementException; import java.util.Set; import java.util.TreeMap; import javax.imageio.metadata.IIOInvalidTreeException; import javax.imageio.metadata.IIOMetadata; import javax.imageio.metadata.IIOMetadataFormatImpl; import org.w3c.dom.Node; import com.sun.media.imageioimpl.plugins.tiff.TIFFIFD; import com.sun.media.imageioimpl.plugins.tiff.TIFFImageMetadata; /** * A convenience class for simplifying interaction with TIFF native * image metadata. A TIFF image metadata tree represents an Image File * Directory (IFD) from a TIFF 6.0 stream. An IFD consists of a number of * IFD Entries each of which associates an identifying tag number with * a compatible value. A TIFFDirectory instance corresponds * to an IFD and contains a set of {@link TIFFField}s each of which * corresponds to an IFD Entry in the IFD. * *

    When reading, a TIFFDirectory may be created by passing * the value returned by {@link javax.imageio.ImageReader#getImageMetadata * ImageReader.getImageMetadata()} to {@link #createFromMetadata * createFromMetadata()}. The {@link TIFFField}s in the directory may then * be obtained using the accessor methods provided in this class.

    * *

    When writing, an {@link IIOMetadata} object for use by one of the * write() methods of {@link javax.imageio.ImageWriter} may be * created from a TIFFDirectory by {@link #getAsMetadata()}. * The TIFFDirectory itself may be created by construction or * from the IIOMetadata object returned by * {@link javax.imageio.ImageWriter#getDefaultImageMetadata * ImageWriter.getDefaultImageMetadata()}. The TIFFFields in the * directory may be set using the mutator methods provided in this class.

    * *

    A TIFFDirectory is aware of the tag numbers in the * group of {@link TIFFTagSet}s associated with it. When * a TIFFDirectory is created from a native image metadata * object, these tag sets are derived from the tagSets attribute * of the TIFFIFD node.

    * *

    A TIFFDirectory might also have a parent {@link TIFFTag}. * This will occur if the directory represents an IFD other than the root * IFD of the image. The parent tag is the tag of the IFD Entry which is a * pointer to the IFD represented by this TIFFDirectory. The * {@link TIFFTag#isIFDPointer} method of this parent TIFFTag * must return true. When a TIFFDirectory is * created from a native image metadata object, the parent tag set is set * from the parentTagName attribute of the corresponding * TIFFIFD node. Note that a TIFFDirectory instance * which has a non-null parent tag will be contained in the * data field of a TIFFField instance which has a tag field * equal to the contained directory's parent tag.

    * *

    As an example consider an EXIF image. The TIFFDirectory * instance corresponding to the EXIF IFD in the EXIF stream would have parent * tag {@link EXIFParentTIFFTagSet#TAG_EXIF_IFD_POINTER TAG_EXIF_IFD_POINTER} * and would include {@link EXIFTIFFTagSet} in its group of known tag sets. * The TIFFDirectory corresponding to this EXIF IFD will be * contained in the data field of a TIFFField which will in turn * be contained in the TIFFDirectory corresponding to the primary * IFD of the EXIF image which will itself have a null-valued * parent tag.

    * *

    Note that this implementation is not synchronized. If multiple * threads use a TIFFDirectory instance concurrently, and at * least one of the threads modifies the directory, for example, by adding * or removing TIFFFields or TIFFTagSets, it * must be synchronized externally.

    * * @see IIOMetadata * @see TIFFField * @see TIFFTag * @see TIFFTagSet * * @since 1.1-beta */ // XXX doc: not thread safe public class TIFFDirectory implements Cloneable { /** The largest low-valued tag number in the TIFF 6.0 specification. */ private static final int MAX_LOW_FIELD_TAG_NUM = BaselineTIFFTagSet.TAG_REFERENCE_BLACK_WHITE; /** The TIFFTagSets associated with this directory. */ private List tagSets; /** The parent TIFFTag of this directory. */ private TIFFTag parentTag; /** * The fields in this directory which have a low tag number. These are * managed as an array for efficiency as they are the most common fields. */ private TIFFField[] lowFields = new TIFFField[MAX_LOW_FIELD_TAG_NUM + 1]; /** The number of low tag numbered fields in the directory. */ private int numLowFields = 0; /** * A mapping of Integer tag numbers to TIFFFields * for fields which are not low tag numbered. */ private Map highFields = new TreeMap(); /** * Creates a TIFFDirectory instance from the contents of * an image metadata object. The supplied object must support an image * metadata format supported by the TIFF {@link javax.imageio.ImageWriter} * plug-in. This will usually be either the TIFF native image metadata * format com_sun_media_imageio_plugins_tiff_1.0 or the Java * Image I/O standard metadata format javax_imageio_1.0. * * @param tiffImageMetadata A metadata object which supports a compatible * image metadata format. * * @return A TIFFDirectory populated from the contents of * the supplied metadata object. * * @throws IllegalArgumentException if tiffImageMetadata * is null. * @throws IllegalArgumentException if tiffImageMetadata * does not support a compatible image metadata format. * @throws IIOInvalidTreeException if the supplied metadata object * cannot be parsed. */ public static TIFFDirectory createFromMetadata(IIOMetadata tiffImageMetadata) throws IIOInvalidTreeException { if(tiffImageMetadata == null) { throw new IllegalArgumentException("tiffImageMetadata == null"); } TIFFImageMetadata tim; if(tiffImageMetadata instanceof TIFFImageMetadata) { tim = (TIFFImageMetadata)tiffImageMetadata; } else { // Create a native metadata object. ArrayList l = new ArrayList(1); l.add(BaselineTIFFTagSet.getInstance()); tim = new TIFFImageMetadata(l); // Determine the format name to use. String formatName = null; if(TIFFImageMetadata.nativeMetadataFormatName.equals (tiffImageMetadata.getNativeMetadataFormatName())) { formatName = TIFFImageMetadata.nativeMetadataFormatName; } else { String[] extraNames = tiffImageMetadata.getExtraMetadataFormatNames(); if(extraNames != null) { for(int i = 0; i < extraNames.length; i++) { if(TIFFImageMetadata.nativeMetadataFormatName.equals (extraNames[i])) { formatName = extraNames[i]; break; } } } if(formatName == null) { if(tiffImageMetadata.isStandardMetadataFormatSupported()) { formatName = IIOMetadataFormatImpl.standardMetadataFormatName; } else { throw new IllegalArgumentException ("Parameter does not support required metadata format!"); } } } // Set the native metadata object from the tree. tim.setFromTree(formatName, tiffImageMetadata.getAsTree(formatName)); } return tim.getRootIFD(); } /** * Converts a TIFFDirectory to a TIFFIFD. */ private static TIFFIFD getDirectoryAsIFD(TIFFDirectory dir) { if(dir instanceof TIFFIFD) { return (TIFFIFD)dir; } TIFFIFD ifd = new TIFFIFD(Arrays.asList(dir.getTagSets()), dir.getParentTag()); TIFFField[] fields = dir.getTIFFFields(); int numFields = fields.length; for(int i = 0; i < numFields; i++) { TIFFField f = fields[i]; TIFFTag tag = f.getTag(); if(tag.isIFDPointer()) { TIFFDirectory subIFD = getDirectoryAsIFD((TIFFDirectory)f.getData()); f = new TIFFField(tag, f.getType(), f.getCount(), subIFD); } ifd.addTIFFField(f); } return ifd; } /** * Constructs a TIFFDirectory which is aware of a given * group of {@link TIFFTagSet}s. An optional parent {@link TIFFTag} * may also be specified. * * @param tagSets The TIFFTagSets associated with this * directory. * @param parentTag The parent TIFFTag of this directory; * may be null. * @throws IllegalArgumentException if tagSets is * null. */ public TIFFDirectory(TIFFTagSet[] tagSets, TIFFTag parentTag) { if(tagSets == null) { throw new IllegalArgumentException("tagSets == null!"); } this.tagSets = new ArrayList(tagSets.length); int numTagSets = tagSets.length; for(int i = 0; i < numTagSets; i++) { this.tagSets.add(tagSets[i]); } this.parentTag = parentTag; } /** * Returns the {@link TIFFTagSet}s of which this directory is aware. * * @return The TIFFTagSets associated with this * TIFFDirectory. */ public TIFFTagSet[] getTagSets() { return (TIFFTagSet[])tagSets.toArray(new TIFFTagSet[tagSets.size()]); } /** * Adds an element to the group of {@link TIFFTagSet}s of which this * directory is aware. * * @param tagSet The TIFFTagSet to add. * @throws IllegalArgumentException if tagSet is * null. */ public void addTagSet(TIFFTagSet tagSet) { if(tagSet == null) { throw new IllegalArgumentException("tagSet == null"); } if(!tagSets.contains(tagSet)) { tagSets.add(tagSet); } } /** * Removes an element from the group of {@link TIFFTagSet}s of which this * directory is aware. * * @param tagSet The TIFFTagSet to remove. * @throws IllegalArgumentException if tagSet is * null. */ public void removeTagSet(TIFFTagSet tagSet) { if(tagSet == null) { throw new IllegalArgumentException("tagSet == null"); } if(tagSets.contains(tagSet)) { tagSets.remove(tagSet); } } /** * Returns the parent {@link TIFFTag} of this directory if one * has been defined or null otherwise. * * @return The parent TIFFTag of this * TIFFDiectory or null. */ public TIFFTag getParentTag() { return parentTag; } /** * Returns the {@link TIFFTag} which has tag number equal to * tagNumber or null if no such tag * exists in the {@link TIFFTagSet}s associated with this * directory. * * @param tagNumber The tag number of interest. * @return The corresponding TIFFTag or null. */ public TIFFTag getTag(int tagNumber) { return TIFFIFD.getTag(tagNumber, tagSets); } /** * Returns the number of {@link TIFFField}s in this directory. * * @return The number of TIFFFields in this * TIFFDirectory. */ public int getNumTIFFFields() { return numLowFields + highFields.size(); } /** * Determines whether a TIFF field with the given tag number is * contained in this directory. * * @return Whether a {@link TIFFTag} with tag number equal to * tagNumber is present in this TIFFDirectory. */ public boolean containsTIFFField(int tagNumber) { return (tagNumber >= 0 && tagNumber <= MAX_LOW_FIELD_TAG_NUM && lowFields[tagNumber] != null) || highFields.containsKey(new Integer(tagNumber)); } /** * Adds a TIFF field to the directory. * * @param f The field to add. * @throws IllegalArgumentException if f is null. */ public void addTIFFField(TIFFField f) { if(f == null) { throw new IllegalArgumentException("f == null"); } int tagNumber = f.getTagNumber(); if(tagNumber >= 0 && tagNumber <= MAX_LOW_FIELD_TAG_NUM) { if(lowFields[tagNumber] == null) { numLowFields++; } lowFields[tagNumber] = f; } else { highFields.put(new Integer(tagNumber), f); } } /** * Retrieves a TIFF field from the directory. * * @param tagNumber The tag number of the tag associated with the field. * @return A TIFFField with the requested tag number of * null if no such field is present. */ public TIFFField getTIFFField(int tagNumber) { TIFFField f; if(tagNumber >= 0 && tagNumber <= MAX_LOW_FIELD_TAG_NUM) { f = lowFields[tagNumber]; } else { f = (TIFFField)highFields.get(new Integer(tagNumber)); } return f; } /** * Removes a TIFF field from the directory. * * @param tagNumber The tag number of the tag associated with the field. */ public void removeTIFFField(int tagNumber) { if(tagNumber >= 0 && tagNumber <= MAX_LOW_FIELD_TAG_NUM) { if(lowFields[tagNumber] != null) { numLowFields--; lowFields[tagNumber] = null; } } else { highFields.remove(new Integer(tagNumber)); } } /** * Retrieves all TIFF fields from the directory. * * @return An array of all TIFF fields in order of numerically increasing * tag number. */ public TIFFField[] getTIFFFields() { // Allocate return value. TIFFField[] fields = new TIFFField[numLowFields + highFields.size()]; // Copy any low-index fields. int nextIndex = 0; for(int i = 0; i <= MAX_LOW_FIELD_TAG_NUM; i++) { if(lowFields[i] != null) { fields[nextIndex++] = lowFields[i]; if(nextIndex == numLowFields) break; } } // Copy any high-index fields. if(!highFields.isEmpty()) { Iterator keys = highFields.keySet().iterator(); while(keys.hasNext()) { fields[nextIndex++] = (TIFFField)highFields.get(keys.next()); } } return fields; } /** * Removes all TIFF fields from the directory. */ public void removeTIFFFields() { Arrays.fill(lowFields, (Object)null); numLowFields = 0; highFields.clear(); } /** * Converts the directory to a metadata object. * * @return A metadata instance initialized from the contents of this * TIFFDirectory. */ public IIOMetadata getAsMetadata() { return new TIFFImageMetadata(getDirectoryAsIFD(this)); } /** * Clones the directory and all the fields contained therein. * * @return A clone of this TIFFDirectory. */ public Object clone() { TIFFDirectory dir = new TIFFDirectory(getTagSets(), getParentTag()); TIFFField[] fields = getTIFFFields(); int numFields = fields.length; for(int i = 0; i < numFields; i++) { dir.addTIFFField(fields[i]); } return dir; } } jai-imageio-core-1.2/src/share/classes/com/sun/media/imageio/plugins/tiff/EXIFGPSTagSet.java0000664000175100017510000005175610330454115030572 0ustar tilletille/* * $RCSfile: EXIFGPSTagSet.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.1 $ * $Date: 2005-10-28 16:56:45 $ * $State: Exp $ */ package com.sun.media.imageio.plugins.tiff; import java.util.ArrayList; import java.util.List; /** * A class representing the tags found in an EXIF GPS Info IFD. * *

    The definitions of the data types referenced by the field * definitions may be found in the {@link TIFFTag * TIFFTag} class. * * @see EXIFTIFFTagSet */ public class EXIFGPSTagSet extends TIFFTagSet { private static EXIFGPSTagSet theInstance = null; /** * A tag indicating the GPS tag version (type BYTE, count = 4). * * @see #GPS_VERSION_2_2 */ public static final int TAG_GPS_VERSION_ID = 0; /** * An array of bytes containing the values {'2', '2', '0', * '0'} to be used with the "GPSVersionID" tag to indicate * GPS version 2.2. * * @see #TAG_GPS_VERSION_ID */ public static byte[] GPS_VERSION_2_2 = { '2', '2', '0', '0' }; /** * A tag indicating the North or South latitude (type ASCII, count = 2). * * @see #LATITUDE_REF_NORTH * @see #LATITUDE_REF_SOUTH */ public static final int TAG_GPS_LATITUDE_REF = 1; /** * A tag indicating the Latitude (type RATIONAL, count = 3). */ public static final int TAG_GPS_LATITUDE = 2; /** * A tag indicating the East or West Longitude (type ASCII, count = 2). * * @see #LONGITUDE_REF_EAST * @see #LONGITUDE_REF_WEST */ public static final int TAG_GPS_LONGITUDE_REF = 3; /** * A tag indicating the Longitude (type RATIONAL, count = 3). */ public static final int TAG_GPS_LONGITUDE = 4; /** * A tag indicating the Altitude reference (type BYTE, count = 1); * * @see #ALTITUDE_REF_SEA_LEVEL * @see #ALTITUDE_REF_SEA_LEVEL_REFERENCE */ public static final int TAG_GPS_ALTITUDE_REF = 5; /** * A tag indicating the Altitude (type RATIONAL, count = 1). */ public static final int TAG_GPS_ALTITUDE = 6; /** * A tag indicating the GPS time (atomic clock) (type RATIONAL, count = 3). */ public static final int TAG_GPS_TIME_STAMP = 7; /** * A tag indicating the GPS satellites used for measurement (type ASCII). */ public static final int TAG_GPS_SATELLITES = 8; /** * A tag indicating the GPS receiver status (type ASCII, count = 2). * * @see #STATUS_MEASUREMENT_IN_PROGRESS * @see #STATUS_MEASUREMENT_INTEROPERABILITY */ public static final int TAG_GPS_STATUS = 9; /** * A tag indicating the GPS measurement mode (type ASCII, count = 2). * * @see #MEASURE_MODE_2D * @see #MEASURE_MODE_3D */ public static final int TAG_GPS_MEASURE_MODE = 10; /** * A tag indicating the Measurement precision (type RATIONAL, count = 1). */ public static final int TAG_GPS_DOP = 11; /** * A tag indicating the Speed unit (type ASCII, count = 2). * * @see #SPEED_REF_KILOMETERS_PER_HOUR * @see #SPEED_REF_MILES_PER_HOUR * @see #SPEED_REF_KNOTS */ public static final int TAG_GPS_SPEED_REF = 12; /** * A tag indicating the Speed of GPS receiver (type RATIONAL, count = 1). */ public static final int TAG_GPS_SPEED = 13; /** * A tag indicating the Reference for direction of movement (type ASCII, * count = 2). * * @see #DIRECTION_REF_TRUE * @see #DIRECTION_REF_MAGNETIC */ public static final int TAG_GPS_TRACK_REF = 14; /** * A tag indicating the Direction of movement (type RATIONAL, count = 1). */ public static final int TAG_GPS_TRACK = 15; /** * A tag indicating the Reference for direction of image (type ASCII, * count = 2). * * @see #DIRECTION_REF_TRUE * @see #DIRECTION_REF_MAGNETIC */ public static final int TAG_GPS_IMG_DIRECTION_REF = 16; /** * A tag indicating the Direction of image (type RATIONAL, count = 1). */ public static final int TAG_GPS_IMG_DIRECTION = 17; /** * A tag indicating the Geodetic survey data used (type ASCII). */ public static final int TAG_GPS_MAP_DATUM = 18; /** * A tag indicating the Reference for latitude of destination (type * ASCII, count = 2). * * @see #LATITUDE_REF_NORTH * @see #LATITUDE_REF_SOUTH */ public static final int TAG_GPS_DEST_LATITUDE_REF = 19; /** * A tag indicating the Latitude of destination (type RATIONAL, count = 3). */ public static final int TAG_GPS_DEST_LATITUDE = 20; /** * A tag indicating the Reference for longitude of destination (type * ASCII, count = 2). * * @see #LONGITUDE_REF_EAST * @see #LONGITUDE_REF_WEST */ public static final int TAG_GPS_DEST_LONGITUDE_REF = 21; /** * A tag indicating the Longitude of destination (type RATIONAL, * count = 3). */ public static final int TAG_GPS_DEST_LONGITUDE = 22; /** * A tag indicating the Reference for bearing of destination (type ASCII, * count = 2). * * @see #DIRECTION_REF_TRUE * @see #DIRECTION_REF_MAGNETIC */ public static final int TAG_GPS_DEST_BEARING_REF = 23; /** * A tag indicating the Bearing of destination (type RATIONAL, count = 1). */ public static final int TAG_GPS_DEST_BEARING = 24; /** * A tag indicating the Reference for distance to destination (type ASCII, * count = 2). * * @see #DEST_DISTANCE_REF_KILOMETERS * @see #DEST_DISTANCE_REF_MILES * @see #DEST_DISTANCE_REF_KNOTS */ public static final int TAG_GPS_DEST_DISTANCE_REF = 25; /** * A tag indicating the Distance to destination (type RATIONAL, count = 1). */ public static final int TAG_GPS_DEST_DISTANCE = 26; /** * A tag indicating the Name of GPS processing method (type UNDEFINED). */ public static final int TAG_GPS_PROCESSING_METHOD = 27; /** * A tag indicating the Name of GPS area (type UNDEFINED). */ public static final int TAG_GPS_AREA_INFORMATION = 28; /** * A tag indicating the GPS date (type ASCII, count 11). */ public static final int TAG_GPS_DATE_STAMP = 29; /** * A tag indicating the GPS differential correction (type SHORT, * count = 1). * * @see #DIFFERENTIAL_CORRECTION_NONE * @see #DIFFERENTIAL_CORRECTION_APPLIED */ public static final int TAG_GPS_DIFFERENTIAL = 30; /** * A value to be used with the "GPSLatitudeRef" and * "GPSDestLatitudeRef" tags. * * @see #TAG_GPS_LATITUDE_REF * @see #TAG_GPS_DEST_LATITUDE_REF */ public static final String LATITUDE_REF_NORTH = "N"; /** * A value to be used with the "GPSLatitudeRef" and * "GPSDestLatitudeRef" tags. * * @see #TAG_GPS_LATITUDE_REF * @see #TAG_GPS_DEST_LATITUDE_REF */ public static final String LATITUDE_REF_SOUTH = "S"; /** * A value to be used with the "GPSLongitudeRef" and * "GPSDestLongitudeRef" tags. * * @see #TAG_GPS_LONGITUDE_REF * @see #TAG_GPS_DEST_LONGITUDE_REF */ public static final String LONGITUDE_REF_EAST = "E"; /** * A value to be used with the "GPSLongitudeRef" and * "GPSDestLongitudeRef" tags. * * @see #TAG_GPS_LONGITUDE_REF * @see #TAG_GPS_DEST_LONGITUDE_REF */ public static final String LONGITUDE_REF_WEST = "W"; /** * A value to be used with the "GPSAltitudeRef" tag. * * @see #TAG_GPS_ALTITUDE_REF */ public static final int ALTITUDE_REF_SEA_LEVEL = 0; /** * A value to be used with the "GPSAltitudeRef" tag. * * @see #TAG_GPS_ALTITUDE_REF */ public static final int ALTITUDE_REF_SEA_LEVEL_REFERENCE = 1; /** * A value to be used with the "GPSStatus" tag. * * @see #TAG_GPS_STATUS */ public static final String STATUS_MEASUREMENT_IN_PROGRESS = "A"; /** * A value to be used with the "GPSStatus" tag. * * @see #TAG_GPS_STATUS */ public static final String STATUS_MEASUREMENT_INTEROPERABILITY = "V"; /** * A value to be used with the "GPSMeasureMode" tag. * * @see #TAG_GPS_MEASURE_MODE */ public static final String MEASURE_MODE_2D = "2"; /** * A value to be used with the "GPSMeasureMode" tag. * * @see #TAG_GPS_MEASURE_MODE */ public static final String MEASURE_MODE_3D = "3"; /** * A value to be used with the "GPSSpeedRef" tag. * * @see #TAG_GPS_SPEED_REF */ public static final String SPEED_REF_KILOMETERS_PER_HOUR = "K"; /** * A value to be used with the "GPSSpeedRef" tag. * * @see #TAG_GPS_SPEED_REF */ public static final String SPEED_REF_MILES_PER_HOUR = "M"; /** * A value to be used with the "GPSSpeedRef" tag. * * @see #TAG_GPS_SPEED_REF */ public static final String SPEED_REF_KNOTS = "N"; /** * A value to be used with the "GPSTrackRef", "GPSImgDirectionRef", * and "GPSDestBearingRef" tags. * * @see #TAG_GPS_TRACK_REF * @see #TAG_GPS_IMG_DIRECTION_REF * @see #TAG_GPS_DEST_BEARING_REF */ public static final String DIRECTION_REF_TRUE = "T"; /** * A value to be used with the "GPSTrackRef", "GPSImgDirectionRef", * and "GPSDestBearingRef" tags. * * @see #TAG_GPS_TRACK_REF * @see #TAG_GPS_IMG_DIRECTION_REF * @see #TAG_GPS_DEST_BEARING_REF */ public static final String DIRECTION_REF_MAGNETIC = "M"; /** * A value to be used with the "GPSDestDistanceRef" tag. * * @see #TAG_GPS_DEST_DISTANCE_REF */ public static final String DEST_DISTANCE_REF_KILOMETERS = "K"; /** * A value to be used with the "GPSDestDistanceRef" tag. * * @see #TAG_GPS_DEST_DISTANCE_REF */ public static final String DEST_DISTANCE_REF_MILES = "M"; /** * A value to be used with the "GPSDestDistanceRef" tag. * * @see #TAG_GPS_DEST_DISTANCE_REF */ public static final String DEST_DISTANCE_REF_KNOTS = "N"; /** * A value to be used with the "GPSDifferential" tag. * * @see #TAG_GPS_DIFFERENTIAL */ public static int DIFFERENTIAL_CORRECTION_NONE = 0; /** * A value to be used with the "GPSDifferential" tag. * * @see #TAG_GPS_DIFFERENTIAL */ public static int DIFFERENTIAL_CORRECTION_APPLIED = 1; static class GPSVersionID extends TIFFTag { public GPSVersionID() { super("GPSVersionID", TAG_GPS_VERSION_ID, 1 << TIFFTag.TIFF_BYTE); } } static class GPSLatitudeRef extends TIFFTag { public GPSLatitudeRef() { super("GPSLatitudeRef", TAG_GPS_LATITUDE_REF, 1 << TIFFTag.TIFF_ASCII); } } static class GPSLatitude extends TIFFTag { public GPSLatitude() { super("GPSLatitude", TAG_GPS_LATITUDE, 1 << TIFFTag.TIFF_RATIONAL); } } static class GPSLongitudeRef extends TIFFTag { public GPSLongitudeRef() { super("GPSLongitudeRef", TAG_GPS_LONGITUDE_REF, 1 << TIFFTag.TIFF_ASCII); } } static class GPSLongitude extends TIFFTag { public GPSLongitude() { super("GPSLongitude", TAG_GPS_LONGITUDE, 1 << TIFFTag.TIFF_RATIONAL); } } static class GPSAltitudeRef extends TIFFTag { public GPSAltitudeRef() { super("GPSAltitudeRef", TAG_GPS_ALTITUDE_REF, 1 << TIFFTag.TIFF_BYTE); addValueName(ALTITUDE_REF_SEA_LEVEL, "Sea level"); addValueName(ALTITUDE_REF_SEA_LEVEL_REFERENCE, "Sea level reference (negative value)"); } } static class GPSAltitude extends TIFFTag { public GPSAltitude() { super("GPSAltitude", TAG_GPS_ALTITUDE, 1 << TIFFTag.TIFF_RATIONAL); } } static class GPSTimeStamp extends TIFFTag { public GPSTimeStamp() { super("GPSTimeStamp", TAG_GPS_TIME_STAMP, 1 << TIFFTag.TIFF_RATIONAL); } } static class GPSSatellites extends TIFFTag { public GPSSatellites() { super("GPSSatellites", TAG_GPS_SATELLITES, 1 << TIFFTag.TIFF_ASCII); } } static class GPSStatus extends TIFFTag { public GPSStatus() { super("GPSStatus", TAG_GPS_STATUS, 1 << TIFFTag.TIFF_ASCII); } } static class GPSMeasureMode extends TIFFTag { public GPSMeasureMode() { super("GPSMeasureMode", TAG_GPS_MEASURE_MODE, 1 << TIFFTag.TIFF_ASCII); } } static class GPSDOP extends TIFFTag { public GPSDOP() { super("GPSDOP", TAG_GPS_DOP, 1 << TIFFTag.TIFF_RATIONAL); } } static class GPSSpeedRef extends TIFFTag { public GPSSpeedRef() { super("GPSSpeedRef", TAG_GPS_SPEED_REF, 1 << TIFFTag.TIFF_ASCII); } } static class GPSSpeed extends TIFFTag { public GPSSpeed() { super("GPSSpeed", TAG_GPS_SPEED, 1 << TIFFTag.TIFF_RATIONAL); } } static class GPSTrackRef extends TIFFTag { public GPSTrackRef() { super("GPSTrackRef", TAG_GPS_TRACK_REF, 1 << TIFFTag.TIFF_ASCII); } } static class GPSTrack extends TIFFTag { public GPSTrack() { super("GPSTrack", TAG_GPS_TRACK, 1 << TIFFTag.TIFF_RATIONAL); } } static class GPSImgDirectionRef extends TIFFTag { public GPSImgDirectionRef() { super("GPSImgDirectionRef", TAG_GPS_IMG_DIRECTION_REF, 1 << TIFFTag.TIFF_ASCII); } } static class GPSImgDirection extends TIFFTag { public GPSImgDirection() { super("GPSImgDirection", TAG_GPS_IMG_DIRECTION, 1 << TIFFTag.TIFF_RATIONAL); } } static class GPSMapDatum extends TIFFTag { public GPSMapDatum() { super("GPSMapDatum", TAG_GPS_MAP_DATUM, 1 << TIFFTag.TIFF_ASCII); } } static class GPSDestLatitudeRef extends TIFFTag { public GPSDestLatitudeRef() { super("GPSDestLatitudeRef", TAG_GPS_DEST_LATITUDE_REF, 1 << TIFFTag.TIFF_ASCII); } } static class GPSDestLatitude extends TIFFTag { public GPSDestLatitude() { super("GPSDestLatitude", TAG_GPS_DEST_LATITUDE, 1 << TIFFTag.TIFF_RATIONAL); } } static class GPSDestLongitudeRef extends TIFFTag { public GPSDestLongitudeRef() { super("GPSDestLongitudeRef", TAG_GPS_DEST_LONGITUDE_REF, 1 << TIFFTag.TIFF_ASCII); } } static class GPSDestLongitude extends TIFFTag { public GPSDestLongitude() { super("GPSDestLongitude", TAG_GPS_DEST_LONGITUDE, 1 << TIFFTag.TIFF_RATIONAL); } } static class GPSDestBearingRef extends TIFFTag { public GPSDestBearingRef() { super("GPSDestBearingRef", TAG_GPS_DEST_BEARING_REF, 1 << TIFFTag.TIFF_ASCII); } } static class GPSDestBearing extends TIFFTag { public GPSDestBearing() { super("GPSDestBearing", TAG_GPS_DEST_BEARING, 1 << TIFFTag.TIFF_RATIONAL); } } static class GPSDestDistanceRef extends TIFFTag { public GPSDestDistanceRef() { super("GPSDestDistanceRef", TAG_GPS_DEST_DISTANCE_REF, 1 << TIFFTag.TIFF_ASCII); } } static class GPSDestDistance extends TIFFTag { public GPSDestDistance() { super("GPSDestDistance", TAG_GPS_DEST_DISTANCE, 1 << TIFFTag.TIFF_RATIONAL); } } static class GPSProcessingMethod extends TIFFTag { public GPSProcessingMethod() { super("GPSProcessingMethod", TAG_GPS_PROCESSING_METHOD, 1 << TIFFTag.TIFF_UNDEFINED); } } static class GPSAreaInformation extends TIFFTag { public GPSAreaInformation() { super("GPSAreaInformation", TAG_GPS_AREA_INFORMATION, 1 << TIFFTag.TIFF_UNDEFINED); } } static class GPSDateStamp extends TIFFTag { public GPSDateStamp() { super("GPSDateStamp", TAG_GPS_DATE_STAMP, 1 << TIFFTag.TIFF_ASCII); } } static class GPSDifferential extends TIFFTag { public GPSDifferential() { super("GPSDifferential", TAG_GPS_DIFFERENTIAL, 1 << TIFFTag.TIFF_SHORT); addValueName(DIFFERENTIAL_CORRECTION_NONE, "Measurement without differential correction"); addValueName(DIFFERENTIAL_CORRECTION_APPLIED, "Differential correction applied"); } } private static List initTags() { ArrayList tags = new ArrayList(31); tags.add(new GPSVersionID()); tags.add(new GPSLatitudeRef()); tags.add(new GPSLatitude()); tags.add(new GPSLongitudeRef()); tags.add(new GPSLongitude()); tags.add(new GPSAltitudeRef()); tags.add(new GPSAltitude()); tags.add(new GPSTimeStamp()); tags.add(new GPSSatellites()); tags.add(new GPSStatus()); tags.add(new GPSMeasureMode()); tags.add(new GPSDOP()); tags.add(new GPSSpeedRef()); tags.add(new GPSSpeed()); tags.add(new GPSTrackRef()); tags.add(new GPSTrack()); tags.add(new GPSImgDirectionRef()); tags.add(new GPSImgDirection()); tags.add(new GPSMapDatum()); tags.add(new GPSDestLatitudeRef()); tags.add(new GPSDestLatitude()); tags.add(new GPSDestLongitudeRef()); tags.add(new GPSDestLongitude()); tags.add(new GPSDestBearingRef()); tags.add(new GPSDestBearing()); tags.add(new GPSDestDistanceRef()); tags.add(new GPSDestDistance()); tags.add(new GPSProcessingMethod()); tags.add(new GPSAreaInformation()); tags.add(new GPSDateStamp()); tags.add(new GPSDifferential()); return tags; } private EXIFGPSTagSet() { super(initTags()); } /** * Returns a shared instance of an EXIFGPSTagSet. * * @return an EXIFGPSTagSet instance. */ public synchronized static EXIFGPSTagSet getInstance() { if (theInstance == null) { theInstance = new EXIFGPSTagSet(); } return theInstance; } } jai-imageio-core-1.2/src/share/classes/com/sun/media/imageio/plugins/tiff/FaxTIFFTagSet.java0000664000175100017510000001224410203036165030641 0ustar tilletille/* * $RCSfile: FaxTIFFTagSet.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.1 $ * $Date: 2005-02-11 05:01:17 $ * $State: Exp $ */ package com.sun.media.imageio.plugins.tiff; import java.util.ArrayList; import java.util.List; /** * A class representing the extra tags found in a * * TIFF-F (RFC 2036) file. */ public class FaxTIFFTagSet extends TIFFTagSet { private static FaxTIFFTagSet theInstance = null; // RFC 2036 - TIFF-F extensions /** Tag indicating the number of bad fax lines (type SHORT or LONG). */ public static final int TAG_BAD_FAX_LINES = 326; /** * Tag indicating the number of lines of clean fax data (type * SHORT). * * @see #CLEAN_FAX_DATA_NO_ERRORS * @see #CLEAN_FAX_DATA_ERRORS_CORRECTED * @see #CLEAN_FAX_DATA_ERRORS_UNCORRECTED */ public static final int TAG_CLEAN_FAX_DATA = 327; /** * A value to be used with the "CleanFaxData" tag. * * @see #TAG_CLEAN_FAX_DATA */ public static final int CLEAN_FAX_DATA_NO_ERRORS = 0; /** * A value to be used with the "CleanFaxData" tag. * * @see #TAG_CLEAN_FAX_DATA */ public static final int CLEAN_FAX_DATA_ERRORS_CORRECTED = 1; /** * A value to be used with the "CleanFaxData" tag. * * @see #TAG_CLEAN_FAX_DATA */ public static final int CLEAN_FAX_DATA_ERRORS_UNCORRECTED = 2; /** * Tag indicating the number of consecutive bad lines (type * SHORT or LONG). */ public static final int TAG_CONSECUTIVE_BAD_LINES = 328; // TIFF-F extensions (RFC 2306) // XXX TIFF-F suggested extensions (FaxImageFlags, etc.)? static class BadFaxLines extends TIFFTag { public BadFaxLines() { super("BadFaxLines", TAG_BAD_FAX_LINES, 1 << TIFF_SHORT | 1 << TIFF_LONG); } } static class CleanFaxData extends TIFFTag { public CleanFaxData() { super("CleanFaxData", TAG_CLEAN_FAX_DATA, 1 << TIFF_SHORT); addValueName(CLEAN_FAX_DATA_NO_ERRORS, "No errors"); addValueName(CLEAN_FAX_DATA_ERRORS_CORRECTED, "Errors corrected"); addValueName(CLEAN_FAX_DATA_ERRORS_UNCORRECTED, "Errors uncorrected"); } } static class ConsecutiveBadFaxLines extends TIFFTag { public ConsecutiveBadFaxLines() { super("ConsecutiveBadFaxLines", TAG_CONSECUTIVE_BAD_LINES, 1 << TIFF_SHORT | 1 << TIFF_LONG); } } private static List tags; private static void initTags() { tags = new ArrayList(42); tags.add(new FaxTIFFTagSet.BadFaxLines()); tags.add(new FaxTIFFTagSet.CleanFaxData()); tags.add(new FaxTIFFTagSet.ConsecutiveBadFaxLines()); } private FaxTIFFTagSet() { super(tags); } /** * Returns a shared instance of a FaxTIFFTagSet. * * @return a FaxTIFFTagSet instance. */ public synchronized static FaxTIFFTagSet getInstance() { if (theInstance == null) { initTags(); theInstance = new FaxTIFFTagSet(); tags = null; } return theInstance; } } jai-imageio-core-1.2/src/share/classes/com/sun/media/imageio/plugins/tiff/TIFFTag.java0000664000175100017510000003236310417024535027537 0ustar tilletille/* * $RCSfile: TIFFTag.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.4 $ * $Date: 2006-04-11 22:10:35 $ * $State: Exp $ */ package com.sun.media.imageio.plugins.tiff; import java.util.Map; import java.util.HashMap; import javax.imageio.metadata.IIOMetadataNode; import org.w3c.dom.Node; /** * A class defining the notion of a TIFF tag. A TIFF tag is a key * that may appear in an Image File Directory (IFD). In the IFD * each tag has some data associated with it, which may consist of zero * or more values of a given data type. The combination of a tag and a * value is known as an IFD Entry or TIFF Field. * *

    The actual tag values used in the root IFD of a standard ("baseline") * tiff stream are defined in the {@link BaselineTIFFTagSet * BaselineTIFFTagSet} class. * * @see BaselineTIFFTagSet * @see TIFFField * @see TIFFTagSet */ public class TIFFTag { // TIFF 6.0 + Adobe PageMaker(R) 6.0 TIFF Technical Notes 1 IFD data type /** Flag for 8 bit unsigned integers. */ public static final int TIFF_BYTE = 1; /** Flag for null-terminated ASCII strings. */ public static final int TIFF_ASCII = 2; /** Flag for 16 bit unsigned integers. */ public static final int TIFF_SHORT = 3; /** Flag for 32 bit unsigned integers. */ public static final int TIFF_LONG = 4; /** Flag for pairs of 32 bit unsigned integers. */ public static final int TIFF_RATIONAL = 5; /** Flag for 8 bit signed integers. */ public static final int TIFF_SBYTE = 6; /** Flag for 8 bit uninterpreted bytes. */ public static final int TIFF_UNDEFINED = 7; /** Flag for 16 bit signed integers. */ public static final int TIFF_SSHORT = 8; /** Flag for 32 bit signed integers. */ public static final int TIFF_SLONG = 9; /** Flag for pairs of 32 bit signed integers. */ public static final int TIFF_SRATIONAL = 10; /** Flag for 32 bit IEEE floats. */ public static final int TIFF_FLOAT = 11; /** Flag for 64 bit IEEE doubles. */ public static final int TIFF_DOUBLE = 12; /** * Flag for IFD pointer defined in TIFF Tech Note 1 in * TIFF Specification Supplement 1. */ public static final int TIFF_IFD_POINTER = 13; /** * The numerically smallest constant representing a TIFF data type. */ public static final int MIN_DATATYPE = TIFF_BYTE; /** * The numerically largest constant representing a TIFF data type. */ public static final int MAX_DATATYPE = TIFF_IFD_POINTER; private static final int[] sizeOfType = { 0, // 0 = n/a 1, // 1 = byte 1, // 2 = ascii 2, // 3 = short 4, // 4 = long 8, // 5 = rational 1, // 6 = sbyte 1, // 7 = undefined 2, // 8 = sshort 4, // 9 = slong 8, // 10 = srational 4, // 11 = float 8, // 12 = double 4, // 13 = IFD_POINTER }; // Other tags // Tech notes: http://partners.adobe.com/asn/developer/pdfs/tn/TIFFPM6.pdf // // Tech note 1: TIFF Trees // // Adds additional data type 13 = "IFD" (like LONG) // public static final int TAG_SUB_IFDS = 330; // IFD or LONG) // // Tech note 2: Clipping Path // public static final int TAG_CLIP_PATH = 343; // BYTE // public static final int TAG_X_CLIP_PATH_UNITS = 344; // DWORD // public static final int TAG_Y_CLIP_PATH_UNITS = 345; // DWORD // // Tech note 3: Indexed Images // public static final int TAG_INDEXED = 346; // SHORT // // Tech note 4: ICC L*a*b* // // New PhotometricInterpretation = 9 // // Adobe // // PageMaker stuff // public static final int TAG_IMAGE_ID = 32781; // ASCII // public static final int TAG_OPI_PROXY = 351; // SHORT // // Photoshop stuff // public static final int TAG_IMAGE_SOURCE_DATA = 37724; // UNDEFINED // // 34377 - Image Resource Blocks // // GeoTIFF // public static final int TAG_MODEL_PIXEL_SCALE = 33550; // public static final int TAG_MODEL_TRANSFORMATION = 34264; // public static final int TAG_MODEL_TIEPOINT = 33922; // public static final int TAG_GEO_KEY_DIRECTORY = 34735; // public static final int TAG_GEO_DOUBLE_PARAMS = 34736; // public static final int TAG_GEO_ASCII_PARAMS = 34737; // public static final int TAG_INTERGRAPH_MATRIX = 33920; // // 33918 - Intergraph // // See http://remotesensing.org/lists/libtiff_archive/msg00557.html // // Helios ICC profile tagging // // 34841 - HELIOS ICC profile reference (ASCII) // // eiSTream Annotation Specification , Version 1.00.06 // // Formerly Wang? // // 32932 - eiStream Annotation Data (BYTE/any) // // 32934 - ??? int number; String name; int dataTypes; TIFFTagSet tagSet = null; // Mnemonic names for integral enumerated constants Map valueNames = null; /** * Constructs a TIFFTag with a given name, tag number, set * of legal data types, and TIFFTagSet to which it refers. * The tagSet parameter will generally be * non-null only if this TIFFTag corresponds * to a pointer to a TIFF IFD. In this case tagSet will * represent the set of TIFFTags which appear in the IFD * pointed to. A TIFFTag represents an IFD pointer if and * only if tagSet is non-null or the data * type TIFF_IFD_POINTER is legal. * *

    If there are mnemonic names to be associated with the legal * data values for the tag, {@link #addValueName(int, String) * addValueName()} should be called on the new instance * for each name.

    * *

    See the documentation for {@link #getDataTypes() * getDataTypes()} for an explanation of how the set * of data types is to be converted into a bit mask.

    * * @param name the name of the tag; may be null. * @param number the number used to represent the tag. * @param dataTypes a bit mask indicating the set of legal data * types for this tag. * @param tagSet the TIFFTagSet to which this tag * belongs; may be null. */ public TIFFTag(String name, int number, int dataTypes, TIFFTagSet tagSet) { this.name = name; this.number = number; this.dataTypes = dataTypes; this.tagSet = tagSet; } /** * Constructs a TIFFTag with a given name, tag * number, and set of legal data types. The tag will have no * associated TIFFTagSet. * * @param name the name of the tag; may be null. * @param number the number used to represent the tag. * @param dataTypes a bit mask indicating the set of legal data * types for this tag. * * @see #TIFFTag(String, int, int, TIFFTagSet) */ public TIFFTag(String name, int number, int dataTypes) { this(name, number, dataTypes, null); } /** * Returns the number of bytes used to store a value of the given * data type. * * @param dataType the data type to be queried. * * @return the number of bytes used to store the given data type. * * @throws IllegalArgumentException if datatype is * less than MIN_DATATYPE or greater than * MAX_DATATYPE. */ public static int getSizeOfType(int dataType) { if (dataType < MIN_DATATYPE ||dataType > MAX_DATATYPE) { throw new IllegalArgumentException("dataType out of range!"); } return sizeOfType[dataType]; } /** * Returns the name of the tag, as it will appear in image metadata. * * @return the tag name, as a String. */ public String getName() { return name; } /** * Returns the integer used to represent the tag. * * @return the tag number, as an int. */ public int getNumber() { return number; } /** * Returns a bit mask indicating the set of data types that may * be used to store the data associated with the tag. * For example, a tag that can store both SHORT and LONG values * would return a value of: * *
         * (1 << TIFFTag.TIFF_SHORT) | (1 << TIFFTag.TIFF_LONG)
         * 
    * * @return an int containing a bitmask encoding the * set of valid data types. */ public int getDataTypes() { return dataTypes; } /** * Returns true if the given data type * may be used for the data associated with this tag. * * @param dataType the data type to be queried, one of * TIFF_BYTE, TIFF_SHORT, etc. * * @return a boolean indicating whether the given * data type may be used with this tag. * * @throws IllegalArgumentException if datatype is * less than MIN_DATATYPE or greater than * MAX_DATATYPE. */ public boolean isDataTypeOK(int dataType) { if (dataType < MIN_DATATYPE || dataType > MAX_DATATYPE) { throw new IllegalArgumentException("datatype not in range!"); } return (dataTypes & (1 << dataType)) != 0; } /** * Returns the TIFFTagSet of which this tag is a part. * * @return the containing TIFFTagSet. */ public TIFFTagSet getTagSet() { return tagSet; } /** * Returns true if this tag is used to point to an IFD * structure containing additional tags. This condition will be * satisfied if and only if either * getTagSet() != null or * isDataTypeOK(TIFF_IFD_POINTER) == true. * *

    Many TIFF extensions use this mechanism in order to limit the * number of new tags that may appear in the root IFD.

    * * @return true if this tag points to an IFD. */ public boolean isIFDPointer() { return tagSet != null || ((dataTypes & (1 << TIFF_IFD_POINTER)) != 0); } /** * Returns true if there are mnemonic names associated with * the set of legal values for the data associated with this tag. * * @return true if mnemonic value names are available. */ public boolean hasValueNames() { return valueNames != null; } /** * Adds a mnemonic name for a particular value that this tag's * data may take on. * * @param value the data value. * @param name the name to associate with the value. */ protected void addValueName(int value, String name) { if (valueNames == null) { valueNames = new HashMap(); } valueNames.put(new Integer(value), name); } /** * Returns the mnemonic name associated with a particular value * that this tag's data may take on, or null if * no name is present. * * @param value the data value. * * @return the mnemonic name associated with the value, as a * String. */ public String getValueName(int value) { if (valueNames == null) { return null; } return (String)valueNames.get(new Integer(value)); } } jai-imageio-core-1.2/src/share/classes/com/sun/media/imageio/plugins/tiff/TIFFColorConverter.java0000664000175100017510000000703210424264607031771 0ustar tilletille/* * $RCSfile: TIFFColorConverter.java,v $ * * * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed or intended for * use in the design, construction, operation or maintenance of any * nuclear facility. * * $Revision: 1.2 $ * $Date: 2006-04-28 01:01:59 $ * $State: Exp $ */ package com.sun.media.imageio.plugins.tiff; /** * An abstract class that performs simple color conversion on 3-banded source * images, for use with the TIFF Image I/O plug-in. */ public abstract class TIFFColorConverter { /** * Constructs an instance of a TIFFColorConverter. */ public TIFFColorConverter() {} /** * Converts an RGB triple into the native color space of this * TIFFColorConverter, and stores the result in the first three * entries of the result array. * * @param r the red value. * @param g the green value. * @param b the blue value. * @param result an array of floats containing three elements. * @throws NullPointerException if result is * null. * @throws ArrayIndexOutOfBoundsException if * result.length < 3. */ public abstract void fromRGB(float r, float g, float b, float[] result); /** * Converts a triple in the native color space of this * TIFFColorConverter into an RGB triple, and stores the result in * the first three entries of the rgb array. * * @param x0 the value of channel 0. * @param x1 the value of channel 1. * @param x2 the value of channel 2. * @param rgb an array of floats containing three elements. * @throws NullPointerException if rgb is * null. * @throws ArrayIndexOutOfBoundsException if * rgb.length < 3. */ public abstract void toRGB(float x0, float x1, float x2, float[] rgb); } jai-imageio-core-1.2/src/share/classes/jj2000/0000775000175100017510000000000011650556204017724 5ustar tilletillejai-imageio-core-1.2/src/share/classes/jj2000/j2k/0000775000175100017510000000000011650556205020413 5ustar tilletillejai-imageio-core-1.2/src/share/classes/jj2000/j2k/io/0000775000175100017510000000000011650556205021022 5ustar tilletillejai-imageio-core-1.2/src/share/classes/jj2000/j2k/io/BinaryDataInput.java0000664000175100017510000002070510203036165024716 0ustar tilletille/* * $RCSfile: BinaryDataInput.java,v $ * $Revision: 1.1 $ * $Date: 2005-02-11 05:02:15 $ * $State: Exp $ * * Interface: BinaryDataInput * * Description: Stream like interface for binary * input from a stream or file. * * * * COPYRIGHT: * * This software module was originally developed by Raphal Grosbois and * Diego Santa Cruz (Swiss Federal Institute of Technology-EPFL); Joel * Askelf (Ericsson Radio Systems AB); and Bertrand Berthelot, David * Bouchard, Flix Henry, Gerard Mozelle and Patrice Onno (Canon Research * Centre France S.A) in the course of development of the JPEG2000 * standard as specified by ISO/IEC 15444 (JPEG 2000 Standard). This * software module is an implementation of a part of the JPEG 2000 * Standard. Swiss Federal Institute of Technology-EPFL, Ericsson Radio * Systems AB and Canon Research Centre France S.A (collectively JJ2000 * Partners) agree not to assert against ISO/IEC and users of the JPEG * 2000 Standard (Users) any of their rights under the copyright, not * including other intellectual property rights, for this software module * with respect to the usage by ISO/IEC and Users of this software module * or modifications thereof for use in hardware or software products * claiming conformance to the JPEG 2000 Standard. Those intending to use * this software module in hardware or software products are advised that * their use may infringe existing patents. The original developers of * this software module, JJ2000 Partners and ISO/IEC assume no liability * for use of this software module or modifications thereof. No license * or right to this software module is granted for non JPEG 2000 Standard * conforming products. JJ2000 Partners have full right to use this * software module for his/her own purpose, assign or donate this * software module to any third party and to inhibit third parties from * using this software module for non JPEG 2000 Standard conforming * products. This copyright notice must be included in all copies or * derivative works of this software module. * * Copyright (c) 1999/2000 JJ2000 Partners. * * * */ package jj2000.j2k.io; import java.io.*; /** * This interface defines the input of binary data from streams and/or files. * *

    Byte level input (i.e., for byte, int, long, float, etc.) should * always be byte aligned. For example, a request to read an * int should always realign the input at the byte level. * *

    The implementation of this interface should clearly define if * multi-byte input data is read in little- or big-endian byte * ordering (least significant byte first or most significant byte * first, respectively). * * @see EndianType * */ public interface BinaryDataInput { /** * Should read a signed byte (i.e., 8 bit) from the input. * reading, the input should be realigned at the byte level. * * @return The next byte-aligned signed byte (8 bit) from the * input. * * @exception EOFException If the end-of file was reached before * getting all the necessary data. * * @exception IOException If an I/O error ocurred. * * * */ public byte readByte() throws EOFException, IOException; /** * Should read an unsigned byte (i.e., 8 bit) from the input. It is * returned as an int since Java does not have an * unsigned byte type. Prior to reading, the input should be * realigned at the byte level. * * @return The next byte-aligned unsigned byte (8 bit) from the * input, as an int. * * @exception EOFException If the end-of file was reached before * getting all the necessary data. * * @exception IOException If an I/O error ocurred. * * * */ public int readUnsignedByte() throws EOFException, IOException; /** * Should read a signed short (i.e., 16 bit) from the input. Prior to * reading, the input should be realigned at the byte level. * * @return The next byte-aligned signed short (16 bit) from the * input. * * @exception EOFException If the end-of file was reached before * getting all the necessary data. * * @exception IOException If an I/O error ocurred. * * * */ public short readShort() throws EOFException, IOException; /** * Should read an unsigned short (i.e., 16 bit) from the input. It is * returned as an int since Java does not have an * unsigned short type. Prior to reading, the input should be * realigned at the byte level. * * @return The next byte-aligned unsigned short (16 bit) from the * input, as an int. * * @exception EOFException If the end-of file was reached before * getting all the necessary data. * * @exception IOException If an I/O error ocurred. * * * */ public int readUnsignedShort() throws EOFException, IOException; /** * Should read a signed int (i.e., 32 bit) from the input. Prior to * reading, the input should be realigned at the byte level. * * @return The next byte-aligned signed int (32 bit) from the * input. * * @exception EOFException If the end-of file was reached before * getting all the necessary data. * * @exception IOException If an I/O error ocurred. * * * */ public int readInt() throws EOFException, IOException; /** * Should read an unsigned int (i.e., 32 bit) from the input. It is * returned as a long since Java does not have an * unsigned short type. Prior to reading, the input should be * realigned at the byte level. * * @return The next byte-aligned unsigned int (32 bit) from the * input, as a long. * * @exception EOFException If the end-of file was reached before * getting all the necessary data. * * @exception IOException If an I/O error ocurred. * * * */ public long readUnsignedInt() throws EOFException, IOException; /** * Should read a signed long (i.e., 64 bit) from the input. Prior to * reading, the input should be realigned at the byte level. * * @return The next byte-aligned signed long (64 bit) from the * input. * * @exception EOFException If the end-of file was reached before * getting all the necessary data. * * @exception IOException If an I/O error ocurred. * * * */ public long readLong() throws EOFException, IOException; /** * Should read an IEEE single precision (i.e., 32 bit) * floating-point number from the input. Prior to reading, the * input should be realigned at the byte level. * * @return The next byte-aligned IEEE float (32 bit) from the * input. * * @exception EOFException If the end-of file was reached before * getting all the necessary data. * * @exception IOException If an I/O error ocurred. * * * */ public float readFloat() throws EOFException, IOException; /** * Should read an IEEE double precision (i.e., 64 bit) * floating-point number from the input. Prior to reading, the * input should be realigned at the byte level. * * @return The next byte-aligned IEEE double (64 bit) from the * input. * * @exception EOFException If the end-of file was reached before * getting all the necessary data. * * @exception IOException If an I/O error ocurred. * * * */ public double readDouble() throws EOFException, IOException; /** * Returns the endianess (i.e., byte ordering) of the implementing * class. Note that an implementing class may implement only one * type of endianness or both, which would be decided at creatiuon * time. * * @return Either EndianType.BIG_ENDIAN or * EndianType.LITTLE_ENDIAN * * @see EndianType * * * */ public int getByteOrdering(); /** * Skips n bytes from the input. Prior to skipping, the * input should be realigned at the byte level. * * @param n The number of bytes to skip * * @exception EOFException If the end-of file was reached before * all the bytes could be skipped. * * @exception IOException If an I/O error ocurred. * * * */ public int skipBytes(int n)throws EOFException, IOException; } jai-imageio-core-1.2/src/share/classes/jj2000/j2k/io/RandomAccessIO.java0000664000175100017510000001306310203036165024451 0ustar tilletille/* * $RCSfile: RandomAccessIO.java,v $ * $Revision: 1.1 $ * $Date: 2005-02-11 05:02:16 $ * $State: Exp $ * * Interface: RandomAccessIO.java * * Description: Interface definition for random access I/O. * * * * COPYRIGHT: * * This software module was originally developed by Raphal Grosbois and * Diego Santa Cruz (Swiss Federal Institute of Technology-EPFL); Joel * Askelf (Ericsson Radio Systems AB); and Bertrand Berthelot, David * Bouchard, Flix Henry, Gerard Mozelle and Patrice Onno (Canon Research * Centre France S.A) in the course of development of the JPEG2000 * standard as specified by ISO/IEC 15444 (JPEG 2000 Standard). This * software module is an implementation of a part of the JPEG 2000 * Standard. Swiss Federal Institute of Technology-EPFL, Ericsson Radio * Systems AB and Canon Research Centre France S.A (collectively JJ2000 * Partners) agree not to assert against ISO/IEC and users of the JPEG * 2000 Standard (Users) any of their rights under the copyright, not * including other intellectual property rights, for this software module * with respect to the usage by ISO/IEC and Users of this software module * or modifications thereof for use in hardware or software products * claiming conformance to the JPEG 2000 Standard. Those intending to use * this software module in hardware or software products are advised that * their use may infringe existing patents. The original developers of * this software module, JJ2000 Partners and ISO/IEC assume no liability * for use of this software module or modifications thereof. No license * or right to this software module is granted for non JPEG 2000 Standard * conforming products. JJ2000 Partners have full right to use this * software module for his/her own purpose, assign or donate this * software module to any third party and to inhibit third parties from * using this software module for non JPEG 2000 Standard conforming * products. This copyright notice must be included in all copies or * derivative works of this software module. * * Copyright (c) 1999/2000 JJ2000 Partners. */ package jj2000.j2k.io; import java.io.*; /** * This abstract class defines the interface to perform random access I/O. It * implements the BinaryDataInput and BinaryDataOutput * interfaces so that binary data input/output can be performed. * *

    This interface supports streams of up to 2 GB in length. * * @see BinaryDataInput * @see BinaryDataOutput * */ public interface RandomAccessIO extends BinaryDataInput, BinaryDataOutput { /** * Closes the I/O stream. Prior to closing the stream, any buffered data * (at the bit and byte level) should be written. * * @exception IOException If an I/O error ocurred. * */ public void close() throws IOException; /** * Returns the current position in the stream, which is the position from * where the next byte of data would be read. The first byte in the stream * is in position 0. * * @return The offset of the current position, in bytes. * * @exception IOException If an I/O error ocurred. * */ public int getPos() throws IOException; /** * Returns the current length of the stream, in bytes, taking into account * any buffering. * * @return The length of the stream, in bytes. * * @exception IOException If an I/O error ocurred. * */ public int length() throws IOException; /** * Moves the current position for the next read or write operation to * offset. The offset is measured from the beginning of the stream. The * offset may be set beyond the end of the file, if in write mode. Setting * the offset beyond the end of the file does not change the file * length. The file length will change only by writing after the offset * has been set beyond the end of the file. * * @param off The offset where to move to. * * @exception EOFException If in read-only and seeking beyond EOF. * * @exception IOException If an I/O error ocurred. * */ public void seek(int off) throws IOException; /** * Reads a byte of data from the stream. Prior to reading, the stream is * realigned at the byte level. * * @return The byte read, as an int. * * @exception EOFException If the end-of file was reached. * * @exception IOException If an I/O error ocurred. * */ public int read() throws EOFException, IOException; /** * Reads up to len bytes of data from this file into an array of * bytes. This method reads repeatedly from the stream until all the bytes * are read. This method blocks until all the bytes are read, the end of * the stream is detected, or an exception is thrown. * * @param b The buffer into which the data is to be read. It must be long * enough. * * @param off The index in 'b' where to place the first byte read. * * @param len The number of bytes to read. * * @exception EOFException If the end-of file was reached before * getting all the necessary data. * * @exception IOException If an I/O error ocurred. * */ public void readFully(byte b[], int off, int len) throws IOException; /** * Writes a byte to the stream. Prior to writing, the stream is realigned * at the byte level. * * @param b The byte to write. The lower 8 bits of b are * written. * * @exception IOException If an I/O error ocurred. * */ public void write(int b) throws IOException; } jai-imageio-core-1.2/src/share/classes/jj2000/j2k/io/BufferedRandomAccessFile.java0000664000175100017510000004471010203036165026467 0ustar tilletille/* * $RCSfile: BufferedRandomAccessFile.java,v $ * $Revision: 1.1 $ * $Date: 2005-02-11 05:02:16 $ * $State: Exp $ * * Interface: RandomAccessIO.java * * Description: Abstract class for buffered random access I/O. * * * * COPYRIGHT: * * This software module was originally developed by Raphal Grosbois and * Diego Santa Cruz (Swiss Federal Institute of Technology-EPFL); Joel * Askelf (Ericsson Radio Systems AB); and Bertrand Berthelot, David * Bouchard, Flix Henry, Gerard Mozelle and Patrice Onno (Canon Research * Centre France S.A) in the course of development of the JPEG2000 * standard as specified by ISO/IEC 15444 (JPEG 2000 Standard). This * software module is an implementation of a part of the JPEG 2000 * Standard. Swiss Federal Institute of Technology-EPFL, Ericsson Radio * Systems AB and Canon Research Centre France S.A (collectively JJ2000 * Partners) agree not to assert against ISO/IEC and users of the JPEG * 2000 Standard (Users) any of their rights under the copyright, not * including other intellectual property rights, for this software module * with respect to the usage by ISO/IEC and Users of this software module * or modifications thereof for use in hardware or software products * claiming conformance to the JPEG 2000 Standard. Those intending to use * this software module in hardware or software products are advised that * their use may infringe existing patents. The original developers of * this software module, JJ2000 Partners and ISO/IEC assume no liability * for use of this software module or modifications thereof. No license * or right to this software module is granted for non JPEG 2000 Standard * conforming products. JJ2000 Partners have full right to use this * software module for his/her own purpose, assign or donate this * software module to any third party and to inhibit third parties from * using this software module for non JPEG 2000 Standard conforming * products. This copyright notice must be included in all copies or * derivative works of this software module. * * Copyright (c) 1999/2000 JJ2000 Partners. */ package jj2000.j2k.io; import java.io.*; /** * This class defines a Buffered Random Access File. It implements the * BinaryDataInput and BinaryDataOutput interfaces so that * binary data input/output can be performed. This class is abstract since no * assumption is done about the byte ordering type (little Endian, big * Endian). So subclasses will have to implement methods like * readShort(), writeShort(), readFloat(), ... * *

    BufferedRandomAccessFile (BRAF for short) is a * RandomAccessFile containing an extra buffer. When the BRAF is * accessed, it checks if the requested part of the file is in the buffer or * not. If that is the case, the read/write is done on the buffer. If not, the * file is uppdated to reflect the current status of the buffer and the file * is then accessed for a new buffer containing the requested byte/bit. * * @see RandomAccessIO * @see BinaryDataOutput * @see BinaryDataInput * @see BEBufferedRandomAccessFile * */ public abstract class BufferedRandomAccessFile implements RandomAccessIO, EndianType { /** * The name of the current file * */ private String fileName; /** * Whether the opened file is read only or not (defined by the constructor * arguments) * */ private boolean isReadOnly = true; /** * The RandomAccessFile associated with the buffer * */ private RandomAccessFile theFile; /** * Buffer of bytes containing the part of the file that is currently being * accessed * */ protected byte[] byteBuffer; /** * Boolean keeping track of whether the byte buffer has been changed since * it was read. * */ protected boolean byteBufferChanged; /** * The current offset of the buffer (which will differ from the offset of * the file) * */ protected int offset; /** * The current position in the byte-buffer * */ protected int pos; /** * The maximum number of bytes that can be read from the buffer * */ protected int maxByte; /** * Whether the end of the file is in the current buffer or not * */ protected boolean isEOFInBuffer; /* The endianess of the class */ protected int byteOrdering; /** * Constructor. Always needs a size for the buffer. * * @param file The file associated with the buffer * * @param mode "r" for read, "rw" or "rw+" for read and write mode ("rw+" * opens the file for update whereas "rw" removes it * before. So the 2 modes are different only if the file * already exists). * * @param bufferSize The number of bytes to buffer * * @exception java.io.IOException If an I/O error ocurred. * */ protected BufferedRandomAccessFile(File file, String mode, int bufferSize) throws IOException{ fileName = file.getName(); if(mode.equals("rw") || mode.equals("rw+")){ // mode read / write isReadOnly = false; if(mode.equals("rw")){ // mode read / (over)write if(file.exists()) // Output file already exists file.delete(); } mode = "rw"; } theFile=new RandomAccessFile(file,mode); byteBuffer=new byte[bufferSize]; readNewBuffer(0); } /** * Constructor. Uses the default value for the byte-buffer * size (512 bytes). * * @param file The file associated with the buffer * * @param mode "r" for read, "rw" or "rw+" for read and write mode * ("rw+" opens the file for update whereas "rw" removes * it before. So the 2 modes are different only if the * file already exists). * * @exception java.io.IOException If an I/O error ocurred. * */ protected BufferedRandomAccessFile(File file, String mode ) throws IOException{ this(file, mode, 512); } /** * Constructor. Always needs a size for the buffer. * * @param name The name of the file associated with the buffer * * @param mode "r" for read, "rw" or "rw+" for read and write mode * ("rw+" opens the file for update whereas "rw" removes * it before. So the 2 modes are different only if the * file already exists). * * @param bufferSize The number of bytes to buffer * * @exception java.io.IOException If an I/O error ocurred. * */ protected BufferedRandomAccessFile(String name, String mode, int bufferSize) throws IOException{ this(new File(name), mode, bufferSize); } /** * Constructor. Uses the default value for the byte-buffer * size (512 bytes). * * @param name The name of the file associated with the buffer * * @param mode "r" for read, "rw" or "rw+" for read and write mode * ("rw+" opens the file for update whereas "rw" removes * it before. So the 2 modes are different only if the * file already exists). * * @exception java.io.IOException If an I/O error ocurred. * */ protected BufferedRandomAccessFile(String name, String mode ) throws IOException{ this(name, mode, 512); } /** * Reads a new buffer from the file. If there has been any * changes made since the buffer was read, the buffer is * first written to the file. * * @param off The offset where to move to. * * @exception java.io.IOException If an I/O error ocurred. * */ protected final void readNewBuffer(int off) throws IOException{ /* If the buffer have changed. We need to write it to * the file before reading a new buffer. */ if(byteBufferChanged){ flush(); } // Don't allow to seek beyond end of file if reading only if (isReadOnly && off >= theFile.length()) { throw new EOFException(); } // Set new offset offset = off; theFile.seek(offset); maxByte = theFile.read(byteBuffer,0,byteBuffer.length); pos=0; if(maxByte=offset)&&(off<(offset+byteBuffer.length)) ){ if (isReadOnly && isEOFInBuffer && off > offset+maxByte) { // We are seeking beyond EOF in read-only mode! throw new EOFException(); } pos = off-offset; } else{ readNewBuffer(off); } } /** * Reads an unsigned byte of data from the stream. Prior to reading, the * stream is realigned at the byte level. * * @return The byte read. * * @exception java.io.IOException If an I/O error ocurred. * * @exception java.io.EOFException If the end of file was reached * */ public final int read() throws IOException, EOFException{ if(pos 0) { // There still is some data to read if (pos len) clen = len; System.arraycopy(byteBuffer,pos,b,off,clen); pos += clen; off += clen; len -= clen; } else if (isEOFInBuffer) { pos = maxByte+1; // Set position to EOF throw new EOFException(); } else { // Buffer empty => get more data readNewBuffer(offset+pos); } } } /** * Writes a byte to the stream. Prior to writing, the stream is * realigned at the byte level. * * @param b The byte to write. The lower 8 bits of b are * written. * * @exception java.io.IOException If an I/O error ocurred. * */ public final void write(int b) throws IOException{ // As long as pos is less than the length of the buffer we can write // to the buffer. If the position is after the buffer a new buffer is // needed if(pos=maxByte){ maxByte=pos+1; } pos++; byteBufferChanged =true; } else{ readNewBuffer(offset+pos); write(b); } } /** * Writes a byte to the stream. Prior to writing, the stream is * realigned at the byte level. * * @param b The byte to write. * * @exception java.io.IOException If an I/O error ocurred. * */ public final void write(byte b) throws IOException{ // As long as pos is less than the length of the buffer we can write // to the buffer. If the position is after the buffer a new buffer is // needed if(pos=maxByte){ maxByte=pos+1; } pos++; byteBufferChanged =true; } else{ readNewBuffer(offset+pos); write(b); } } /** * Writes aan array of bytes to the stream. Prior to writing, the stream is * realigned at the byte level. * * @param b The array of bytes to write. * * @param offset The first byte in b to write * * @param length The number of bytes from b to write * * @exception java.io.IOException If an I/O error ocurred. * */ public final void write(byte[] b, int offset, int length) throws IOException{ int i,stop; stop = offset+length; if(stop > b.length) throw new ArrayIndexOutOfBoundsException(b.length); for(i=offset ; iv (i.e., 8 least * significant bits) to the output. Prior to writing, the output * should be realigned at the byte level. * *

    Signed or unsigned data can be written. To write a signed * value just pass the byte value as an argument. To * write unsigned data pass the int value as an argument * (it will be automatically casted, and only the 8 least * significant bits will be written). * * @param v The value to write to the output * * @exception java.io.IOException If an I/O error ocurred. * */ public final void writeByte(int v) throws IOException{ write(v); } /** * Any data that has been buffered must be written (including * buffering at the bit level), and the stream should be realigned * at the byte level. * * @exception java.io.IOException If an I/O error ocurred. * */ public final void flush() throws IOException{ if(byteBufferChanged){ theFile.seek(offset); theFile.write(byteBuffer,0,maxByte); byteBufferChanged = false; } } /** * Reads a signed byte (i.e., 8 bit) from the input. Prior to * reading, the input should be realigned at the byte level. * * @return The next byte-aligned signed byte (8 bit) from the * input. * * @exception java.io.EOFException If the end-of file was reached before * getting all the necessary data. * * @exception java.io.IOException If an I/O error ocurred. * */ public final byte readByte() throws EOFException, IOException { if(posint since Java does not have an * unsigned byte type. Prior to reading, the input should be * realigned at the byte level. * * @return The next byte-aligned unsigned byte (8 bit) from the * input, as an int. * * @exception java.io.EOFException If the end-of file was reached before * getting all the necessary data. * * @exception java.io.IOException If an I/O error ocurred. * */ public final int readUnsignedByte() throws EOFException, IOException{ return read(); } /** * Returns the endianess (i.e., byte ordering) of the implementing * class. Note that an implementing class may implement only one * type of endianness or both, which would be decided at creation * time. * * @return Either EndianType.BIG_ENDIAN or * EndianType.LITTLE_ENDIAN * * @see EndianType * */ public int getByteOrdering(){ return byteOrdering; } /** * Skips n bytes from the input. Prior to skipping, the * input should be realigned at the byte level. * * @param n The number of bytes to skip * * @exception java.io.EOFException If the end-of file was reached before * all the bytes could be skipped. * * @exception java.io.IOException If an I/O error ocurred. * */ public int skipBytes(int n)throws EOFException, IOException{ if(n<0) throw new IllegalArgumentException("Can not skip negative number "+ "of bytes"); if(n <= (maxByte-pos)){ pos += n; return n; } else{ seek(offset+pos+n); return n; } } /** * Returns a string of information about the file * */ public String toString(){ return "BufferedRandomAccessFile: "+fileName+" ("+ ((isReadOnly)?"read only":"read/write")+ ")"; } } jai-imageio-core-1.2/src/share/classes/jj2000/j2k/io/BEBufferedRandomAccessFile.java0000664000175100017510000003142110203036165026671 0ustar tilletille/* * $RCSfile: BEBufferedRandomAccessFile.java,v $ * $Revision: 1.1 $ * $Date: 2005-02-11 05:02:15 $ * $State: Exp $ * * Interface: RandomAccessIO.java * * Description: Class for random access I/O (big-endian ordering). * * * * COPYRIGHT: * * This software module was originally developed by Raphal Grosbois and * Diego Santa Cruz (Swiss Federal Institute of Technology-EPFL); Joel * Askelf (Ericsson Radio Systems AB); and Bertrand Berthelot, David * Bouchard, Flix Henry, Gerard Mozelle and Patrice Onno (Canon Research * Centre France S.A) in the course of development of the JPEG2000 * standard as specified by ISO/IEC 15444 (JPEG 2000 Standard). This * software module is an implementation of a part of the JPEG 2000 * Standard. Swiss Federal Institute of Technology-EPFL, Ericsson Radio * Systems AB and Canon Research Centre France S.A (collectively JJ2000 * Partners) agree not to assert against ISO/IEC and users of the JPEG * 2000 Standard (Users) any of their rights under the copyright, not * including other intellectual property rights, for this software module * with respect to the usage by ISO/IEC and Users of this software module * or modifications thereof for use in hardware or software products * claiming conformance to the JPEG 2000 Standard. Those intending to use * this software module in hardware or software products are advised that * their use may infringe existing patents. The original developers of * this software module, JJ2000 Partners and ISO/IEC assume no liability * for use of this software module or modifications thereof. No license * or right to this software module is granted for non JPEG 2000 Standard * conforming products. JJ2000 Partners have full right to use this * software module for his/her own purpose, assign or donate this * software module to any third party and to inhibit third parties from * using this software module for non JPEG 2000 Standard conforming * products. This copyright notice must be included in all copies or * derivative works of this software module. * * Copyright (c) 1999/2000 JJ2000 Partners. */ package jj2000.j2k.io; import java.io.*; /** * This class defines a Buffered Random Access File, where all I/O is * considered to be big-endian, and extends the * BufferedRandomAccessFile class. * * @see RandomAccessIO * @see BinaryDataOutput * @see BinaryDataInput * @see BufferedRandomAccessFile */ public class BEBufferedRandomAccessFile extends BufferedRandomAccessFile implements RandomAccessIO, EndianType{ /** * Constructor. Always needs a size for the buffer. * * @param file The file associated with the buffer * * @param mode "r" for read, "rw" or "rw+" for read and write mode ("rw+" * opens the file for update whereas "rw" removes it * before. So the 2 modes are different only if the file * already exists). * * @param bufferSize The number of bytes to buffer * * @exception java.io.IOException If an I/O error ocurred. * */ public BEBufferedRandomAccessFile(File file, String mode, int bufferSize) throws IOException{ super(file, mode, bufferSize); byteOrdering = BIG_ENDIAN; } /** * Constructor. Uses the default value for the byte-buffer size (512 * bytes). * * @param file The file associated with the buffer * * @param mode "r" for read, "rw" or "rw+" for read and write mode ("rw+" * opens the file for update whereas "rw" removes it * before. So the 2 modes are different only if the file * already exists). * * @exception java.io.IOException If an I/O error ocurred. * */ public BEBufferedRandomAccessFile(File file, String mode ) throws IOException{ super(file, mode); byteOrdering = BIG_ENDIAN; } /** * Constructor. Always needs a size for the buffer. * * @param name The name of the file associated with the buffer * * @param mode "r" for read, "rw" or "rw+" for read and write mode ("rw+" * opens the file for update whereas "rw" removes it * before. So the 2 modes are different only if the file * already exists). * * @param bufferSize The number of bytes to buffer * * @exception java.io.IOException If an I/O error ocurred. * */ public BEBufferedRandomAccessFile(String name, String mode, int bufferSize) throws IOException{ super(name, mode, bufferSize); byteOrdering = BIG_ENDIAN; } /** * Constructor. Uses the default value for the byte-buffer size (512 * bytes). * * @param name The name of the file associated with the buffer * * @param mode "r" for read, "rw" or "rw+" for read and write mode ("rw+" * opens the file for update whereas "rw" removes it * before. So the 2 modes are different only if the file * already exists). * * @exception java.io.IOException If an I/O error ocurred. * */ public BEBufferedRandomAccessFile(String name, String mode ) throws IOException{ super(name, mode); byteOrdering = BIG_ENDIAN; } /** * Writes the short value of v (i.e., 16 least significant bits) * to the output. Prior to writing, the output should be realigned at the * byte level. * *

    Signed or unsigned data can be written. To write a signed value just * pass the short value as an argument. To write unsigned data * pass the int value as an argument (it will be automatically * casted, and only the 16 least significant bits will be written). * * @param v The value to write to the output * * @exception java.io.IOException If an I/O error ocurred. * */ public final void writeShort(int v) throws IOException{ write(v>>>8); write(v); } /** * Writes the int value of v (i.e., the 32 bits) to the * output. Prior to writing, the output should be realigned at the byte * level. * * @param v The value to write to the output * * @exception java.io.IOException If an I/O error ocurred. * */ public final void writeInt(int v)throws IOException{ write(v>>>24); write(v>>>16); write(v>>>8); write(v); } /** * Writes the long value of v (i.e., the 64 bits) to the * output. Prior to writing, the output should be realigned at the byte * level. * * @param v The value to write to the output * * @exception java.io.IOException If an I/O error ocurred. * */ public final void writeLong(long v)throws IOException{ write((int)(v>>>56)); write((int)(v>>>48)); write((int)(v>>>40)); write((int)(v>>>32)); write((int)(v>>>24)); write((int)(v>>>16)); write((int)(v>>>8)); write((int)v); } /** * Writes the IEEE float value v (i.e., 32 bits) to the * output. Prior to writing, the output should be realigned at the byte * level. * * @param v The value to write to the output * * @exception java.io.IOException If an I/O error ocurred. * */ public final void writeFloat(float v) throws IOException{ int intV = Float.floatToIntBits(v); write(intV>>>24); write(intV>>>16); write(intV>>>8); write(intV); } /** * Writes the IEEE double value v (i.e., 64 bits) to the * output. Prior to writing, the output should be realigned at the byte * level. * * @param v The value to write to the output * * @exception java.io.IOException If an I/O error ocurred. * */ public final void writeDouble(double v)throws IOException{ long longV = Double.doubleToLongBits(v); write((int)(longV>>>56)); write((int)(longV>>>48)); write((int)(longV>>>40)); write((int)(longV>>>32)); write((int)(longV>>>24)); write((int)(longV>>>16)); write((int)(longV>>>8)); write((int)(longV)); } /** * Reads a signed short (i.e., 16 bit) from the input. Prior to reading, * the input should be realigned at the byte level. * * @return The next byte-aligned signed short (16 bit) from the * input. * * @exception java.io.EOFException If the end-of file was reached before * getting all the necessary data. * * @exception java.io.IOException If an I/O error ocurred. * */ public final short readShort() throws IOException, EOFException{ return (short)( (read()<<8)| (read()) ); } /** * Reads an unsigned short (i.e., 16 bit) from the input. It is returned * as an int since Java does not have an unsigned short * type. Prior to reading, the input should be realigned at the byte * level. * * @return The next byte-aligned unsigned short (16 bit) from the * input, as an int. * * @exception java.io.EOFException If the end-of file was reached before * getting all the necessary data. * * @exception java.io.IOException If an I/O error ocurred. * */ public final int readUnsignedShort() throws IOException, EOFException{ return ( (read()<<8)| read() ); } /** * Reads a signed int (i.e., 32 bit) from the input. Prior to reading, the * input should be realigned at the byte level. * * @return The next byte-aligned signed int (32 bit) from the * input. * * @exception java.io.EOFException If the end-of file was reached before * getting all the necessary data. * * @exception java.io.IOException If an I/O error ocurred. * */ public final int readInt() throws IOException, EOFException{ return ( (read()<<24)| (read()<<16)| (read()<<8)| read() ); } /** * Reads an unsigned int (i.e., 32 bit) from the input. It is returned as * a long since Java does not have an unsigned short type. Prior * to reading, the input should be realigned at the byte level. * * @return The next byte-aligned unsigned int (32 bit) from the * input, as a long. * * @exception java.io.EOFException If the end-of file was reached before * getting all the necessary data. * * @exception java.io.IOException If an I/O error ocurred. * */ public final long readUnsignedInt() throws IOException, EOFException{ return (long)( (read()<<24)| (read()<<16)| (read()<<8)| read() ); } /** * Reads a signed long (i.e., 64 bit) from the input. Prior to reading, * the input should be realigned at the byte level. * * @return The next byte-aligned signed long (64 bit) from the * input. * * @exception java.io.EOFException If the end-of file was reached before * getting all the necessary data. * * @exception java.io.IOException If an I/O error ocurred. * */ public final long readLong() throws IOException, EOFException{ return ( ((long)read()<<56)| ((long)read()<<48)| ((long)read()<<40)| ((long)read()<<32)| ((long)read()<<24)| ((long)read()<<16)| ((long)read()<<8)| ((long)read()) ); } /** * Reads an IEEE single precision (i.e., 32 bit) floating-point number * from the input. Prior to reading, the input should be realigned at the * byte level. * * @return The next byte-aligned IEEE float (32 bit) from the * input. * * @exception java.io.EOFException If the end-of file was reached before * getting all the necessary data. * * @exception java.io.IOException If an I/O error ocurred. * */ public final float readFloat() throws EOFException, IOException{ return Float.intBitsToFloat( (read()<<24)| (read()<<16)| (read()<<8)| (read()) ); } /** * Reads an IEEE double precision (i.e., 64 bit) floating-point number * from the input. Prior to reading, the input should be realigned at the * byte level. * * @return The next byte-aligned IEEE double (64 bit) from the * input. * * @exception java.io.EOFException If the end-of file was reached before * getting all the necessary data. * * @exception java.io.IOException If an I/O error ocurred. * */ public final double readDouble() throws IOException, EOFException{ return Double.longBitsToDouble( ((long)read()<<56)| ((long)read()<<48)| ((long)read()<<40)| ((long)read()<<32)| ((long)read()<<24)| ((long)read()<<16)| ((long)read()<<8)| ((long)read()) ); } /** * Returns a string of information about the file and the endianess */ public String toString(){ return super.toString()+"\nBig-Endian ordering"; } } jai-imageio-core-1.2/src/share/classes/jj2000/j2k/io/BinaryDataOutput.java0000664000175100017510000001442510203036165025121 0ustar tilletille/* * $RCSfile: BinaryDataOutput.java,v $ * $Revision: 1.1 $ * $Date: 2005-02-11 05:02:15 $ * $State: Exp $ * * Interface: BinaryDataOutput * * Description: Stream like interface for bit as well as byte * level output to a stream or file. * * * * COPYRIGHT: * * This software module was originally developed by Raphal Grosbois and * Diego Santa Cruz (Swiss Federal Institute of Technology-EPFL); Joel * Askelf (Ericsson Radio Systems AB); and Bertrand Berthelot, David * Bouchard, Flix Henry, Gerard Mozelle and Patrice Onno (Canon Research * Centre France S.A) in the course of development of the JPEG2000 * standard as specified by ISO/IEC 15444 (JPEG 2000 Standard). This * software module is an implementation of a part of the JPEG 2000 * Standard. Swiss Federal Institute of Technology-EPFL, Ericsson Radio * Systems AB and Canon Research Centre France S.A (collectively JJ2000 * Partners) agree not to assert against ISO/IEC and users of the JPEG * 2000 Standard (Users) any of their rights under the copyright, not * including other intellectual property rights, for this software module * with respect to the usage by ISO/IEC and Users of this software module * or modifications thereof for use in hardware or software products * claiming conformance to the JPEG 2000 Standard. Those intending to use * this software module in hardware or software products are advised that * their use may infringe existing patents. The original developers of * this software module, JJ2000 Partners and ISO/IEC assume no liability * for use of this software module or modifications thereof. No license * or right to this software module is granted for non JPEG 2000 Standard * conforming products. JJ2000 Partners have full right to use this * software module for his/her own purpose, assign or donate this * software module to any third party and to inhibit third parties from * using this software module for non JPEG 2000 Standard conforming * products. This copyright notice must be included in all copies or * derivative works of this software module. * * Copyright (c) 1999/2000 JJ2000 Partners. * * * */ package jj2000.j2k.io; import java.io.*; /** * This interface defines the output of binary data to streams and/or files. * *

    Byte level output (i.e., for byte, int, long, float, etc.) should * always be byte aligned. For example, a request to write an * int should always realign the output at the byte level. * *

    The implementation of this interface should clearly define if * multi-byte output data is written in little- or big-endian byte * ordering (least significant byte first or most significant byte * first, respectively). * * @see EndianType * */ public interface BinaryDataOutput { /** * Should write the byte value of v (i.e., 8 least * significant bits) to the output. Prior to writing, the output * should be realigned at the byte level. * *

    Signed or unsigned data can be written. To write a signed * value just pass the byte value as an argument. To * write unsigned data pass the int value as an argument * (it will be automatically casted, and only the 8 least * significant bits will be written). * * @param v The value to write to the output * * @exception IOException If an I/O error ocurred. * * * */ public void writeByte(int v) throws IOException; /** * Should write the short value of v (i.e., 16 least * significant bits) to the output. Prior to writing, the output * should be realigned at the byte level. * *

    Signed or unsigned data can be written. To write a signed * value just pass the short value as an argument. To * write unsigned data pass the int value as an argument * (it will be automatically casted, and only the 16 least * significant bits will be written). * * @param v The value to write to the output * * @exception IOException If an I/O error ocurred. * * * */ public void writeShort(int v) throws IOException; /** * Should write the int value of v (i.e., the 32 bits) to * the output. Prior to writing, the output should be realigned at * the byte level. * * @param v The value to write to the output * * @exception IOException If an I/O error ocurred. * * * */ public void writeInt(int v) throws IOException; /** * Should write the long value of v (i.e., the 64 bits) * to the output. Prior to writing, the output should be realigned * at the byte level. * * @param v The value to write to the output * * @exception IOException If an I/O error ocurred. * * * */ public void writeLong(long v) throws IOException; /** * Should write the IEEE float value v (i.e., 32 bits) to * the output. Prior to writing, the output should be realigned at * the byte level. * * @param v The value to write to the output * * @exception IOException If an I/O error ocurred. * * * */ public void writeFloat(float v) throws IOException; /** * Should write the IEEE double value v (i.e., 64 bits) * to the output. Prior to writing, the output should be realigned * at the byte level. * * @param v The value to write to the output * * @exception IOException If an I/O error ocurred. * * * */ public void writeDouble(double v) throws IOException; /** * Returns the endianness (i.e., byte ordering) of the implementing * class. Note that an implementing class may implement only one * type of endianness or both, which would be decided at creatiuon * time. * * @return Either EndianType.BIG_ENDIAN or * EndianType.LITTLE_ENDIAN * * @see EndianType * * * */ public int getByteOrdering(); /** * Any data that has been buffered must be written, and the stream should * be realigned at the byte level. * * @exception IOException If an I/O error ocurred. * * * */ public void flush() throws IOException; } jai-imageio-core-1.2/src/share/classes/jj2000/j2k/io/EndianType.java0000664000175100017510000000571210203036165023721 0ustar tilletille/* * $RCSfile: EndianType.java,v $ * $Revision: 1.1 $ * $Date: 2005-02-11 05:02:16 $ * $State: Exp $ * * Interface: EndianType * * Description: Defines the two types of endianess (i.e. byte * ordering). * * * * COPYRIGHT: * * This software module was originally developed by Raphal Grosbois and * Diego Santa Cruz (Swiss Federal Institute of Technology-EPFL); Joel * Askelf (Ericsson Radio Systems AB); and Bertrand Berthelot, David * Bouchard, Flix Henry, Gerard Mozelle and Patrice Onno (Canon Research * Centre France S.A) in the course of development of the JPEG2000 * standard as specified by ISO/IEC 15444 (JPEG 2000 Standard). This * software module is an implementation of a part of the JPEG 2000 * Standard. Swiss Federal Institute of Technology-EPFL, Ericsson Radio * Systems AB and Canon Research Centre France S.A (collectively JJ2000 * Partners) agree not to assert against ISO/IEC and users of the JPEG * 2000 Standard (Users) any of their rights under the copyright, not * including other intellectual property rights, for this software module * with respect to the usage by ISO/IEC and Users of this software module * or modifications thereof for use in hardware or software products * claiming conformance to the JPEG 2000 Standard. Those intending to use * this software module in hardware or software products are advised that * their use may infringe existing patents. The original developers of * this software module, JJ2000 Partners and ISO/IEC assume no liability * for use of this software module or modifications thereof. No license * or right to this software module is granted for non JPEG 2000 Standard * conforming products. JJ2000 Partners have full right to use this * software module for his/her own purpose, assign or donate this * software module to any third party and to inhibit third parties from * using this software module for non JPEG 2000 Standard conforming * products. This copyright notice must be included in all copies or * derivative works of this software module. * * Copyright (c) 1999/2000 JJ2000 Partners. * * * */ package jj2000.j2k.io; /** * This interface defines constants for the two types of byte * ordering: little- and big-endian. * *

    Little-endian is least significant byte first. * *

    Big-endian is most significant byte first. * *

    This interface defines the constants only. In order to use the * constants in any other class you can either use the fully qualified * name (e.g., EndianType.LITTLE_ENDIAN) or declare this * interface in the implements clause of the class and then access the * identifier directly. * */ public interface EndianType { /** Identifier for big-endian byte ordering (i.e. most significant * byte first) */ public static final int BIG_ENDIAN = 0; /** Identifier for little-endian byte ordering (i.e. least * significant byte first) */ public static final int LITTLE_ENDIAN = 1; } jai-imageio-core-1.2/src/share/classes/jj2000/j2k/codestream/0000775000175100017510000000000011650556205022541 5ustar tilletillejai-imageio-core-1.2/src/share/classes/jj2000/j2k/codestream/PrecInfo.java0000664000175100017510000001106010203036165025076 0ustar tilletille/* * $RCSfile: PrecInfo.java,v $ * $Revision: 1.1 $ * $Date: 2005-02-11 05:02:00 $ * $State: Exp $ * * Class: PrecInfo * * Description: Keeps information about a precinct * * COPYRIGHT: * * This software module was originally developed by Raphal Grosbois and * Diego Santa Cruz (Swiss Federal Institute of Technology-EPFL); Joel * Askelf (Ericsson Radio Systems AB); and Bertrand Berthelot, David * Bouchard, Flix Henry, Gerard Mozelle and Patrice Onno (Canon Research * Centre France S.A) in the course of development of the JPEG2000 * standard as specified by ISO/IEC 15444 (JPEG 2000 Standard). This * software module is an implementation of a part of the JPEG 2000 * Standard. Swiss Federal Institute of Technology-EPFL, Ericsson Radio * Systems AB and Canon Research Centre France S.A (collectively JJ2000 * Partners) agree not to assert against ISO/IEC and users of the JPEG * 2000 Standard (Users) any of their rights under the copyright, not * including other intellectual property rights, for this software module * with respect to the usage by ISO/IEC and Users of this software module * or modifications thereof for use in hardware or software products * claiming conformance to the JPEG 2000 Standard. Those intending to use * this software module in hardware or software products are advised that * their use may infringe existing patents. The original developers of * this software module, JJ2000 Partners and ISO/IEC assume no liability * for use of this software module or modifications thereof. No license * or right to this software module is granted for non JPEG 2000 Standard * conforming products. JJ2000 Partners have full right to use this * software module for his/her own purpose, assign or donate this * software module to any third party and to inhibit third parties from * using this software module for non JPEG 2000 Standard conforming * products. This copyright notice must be included in all copies or * derivative works of this software module. * * Copyright (c) 1999/2000 JJ2000 Partners. * */ package jj2000.j2k.codestream; /** * Class that holds precinct coordinates and references to contained * code-blocks in each subband. * */ public class PrecInfo { /** Precinct horizontal upper-left coordinate in the reference grid */ public int rgulx; /** Precinct vertical upper-left coordinate in the reference grid */ public int rguly; /** Precinct width reported in the reference grid */ public int rgw; /** Precinct height reported in the reference grid */ public int rgh; /** Precinct horizontal upper-left coordinate in the corresponding * resolution level*/ public int ulx; /** Precinct vertical upper-left coordinate in the corresponding * resolution level*/ public int uly; /** Precinct width in the corresponding resolution level */ public int w; /** Precinct height in the corresponding resolution level */ public int h; /** Resolution level index */ public int r; /** Code-blocks belonging to this precinct in each subbands of the * resolution level */ public CBlkCoordInfo[][][] cblk; /** Number of code-blocks in each subband belonging to this precinct */ public int[] nblk; /** * Class constructor. * * @param r Resolution level index. * @param ulx Precinct horizontal offset. * @param uly Precinct vertical offset. * @param w Precinct width. * @param h Precinct height. * @param rgulx Precinct horizontal offset in the image reference grid. * @param rguly Precinct horizontal offset in the image reference grid. * @param rgw Precinct width in the reference grid. * @param rgh Precinct height in the reference grid. * */ public PrecInfo(int r,int ulx,int uly,int w,int h,int rgulx,int rguly, int rgw,int rgh) { this.r = r; this.ulx = ulx; this.uly = uly; this.w = w; this.h = h; this.rgulx = rgulx; this.rguly = rguly; this.rgw = rgw; this.rgh = rgh; if (r==0) { cblk = new CBlkCoordInfo[1][][]; nblk = new int[1]; } else { cblk = new CBlkCoordInfo[4][][]; nblk = new int[4]; } } /** * Returns PrecInfo object information in a String * * @return PrecInfo information * */ public String toString() { return "ulx="+ulx+",uly="+uly+",w="+w+",h="+h+",rgulx="+rgulx+ ",rguly="+rguly+",rgw="+rgw+",rgh="+rgh; } } jai-imageio-core-1.2/src/share/classes/jj2000/j2k/codestream/CorruptedCodestreamException.java0000664000175100017510000000562510203036165031240 0ustar tilletille/* * $RCSfile: CorruptedCodestreamException.java,v $ * $Revision: 1.1 $ * $Date: 2005-02-11 05:01:59 $ * $State: Exp $ * * Class: CorruptedCodestreamException * * Description: Exception thrown when illegal bit stream * values are decoded. * * * * COPYRIGHT: * * This software module was originally developed by Raphal Grosbois and * Diego Santa Cruz (Swiss Federal Institute of Technology-EPFL); Joel * Askelf (Ericsson Radio Systems AB); and Bertrand Berthelot, David * Bouchard, Flix Henry, Gerard Mozelle and Patrice Onno (Canon Research * Centre France S.A) in the course of development of the JPEG2000 * standard as specified by ISO/IEC 15444 (JPEG 2000 Standard). This * software module is an implementation of a part of the JPEG 2000 * Standard. Swiss Federal Institute of Technology-EPFL, Ericsson Radio * Systems AB and Canon Research Centre France S.A (collectively JJ2000 * Partners) agree not to assert against ISO/IEC and users of the JPEG * 2000 Standard (Users) any of their rights under the copyright, not * including other intellectual property rights, for this software module * with respect to the usage by ISO/IEC and Users of this software module * or modifications thereof for use in hardware or software products * claiming conformance to the JPEG 2000 Standard. Those intending to use * this software module in hardware or software products are advised that * their use may infringe existing patents. The original developers of * this software module, JJ2000 Partners and ISO/IEC assume no liability * for use of this software module or modifications thereof. No license * or right to this software module is granted for non JPEG 2000 Standard * conforming products. JJ2000 Partners have full right to use this * software module for his/her own purpose, assign or donate this * software module to any third party and to inhibit third parties from * using this software module for non JPEG 2000 Standard conforming * products. This copyright notice must be included in all copies or * derivative works of this software module. * * Copyright (c) 1999/2000 JJ2000 Partners. * * * */ package jj2000.j2k.codestream; import java.io.*; /** * Thsi exception is thrown whenever an illegal value is read from a * bit stream. The cause can be either a corrupted bit stream, or a a * bit stream which is illegal. * */ public class CorruptedCodestreamException extends IOException { /** * Constructs a new CorruptedCodestreamException exception * with no detail message. * * */ public CorruptedCodestreamException() { super(); } /** * Constructs a new CorruptedCodestreamException exception * with the specified detail message. * * @param s The detail message. * * */ public CorruptedCodestreamException(String s) { super(s); } } jai-imageio-core-1.2/src/share/classes/jj2000/j2k/codestream/ProgressionType.java0000664000175100017510000000713110203036165026551 0ustar tilletille/* * $RCSfile: ProgressionType.java,v $ * $Revision: 1.1 $ * $Date: 2005-02-11 05:02:00 $ * $State: Exp $ * * Class: ProgressionType * * Description: The definition of the different bit stream * profiles. * * * * COPYRIGHT: * * This software module was originally developed by Raphal Grosbois and * Diego Santa Cruz (Swiss Federal Institute of Technology-EPFL); Joel * Askelf (Ericsson Radio Systems AB); and Bertrand Berthelot, David * Bouchard, Flix Henry, Gerard Mozelle and Patrice Onno (Canon Research * Centre France S.A) in the course of development of the JPEG2000 * standard as specified by ISO/IEC 15444 (JPEG 2000 Standard). This * software module is an implementation of a part of the JPEG 2000 * Standard. Swiss Federal Institute of Technology-EPFL, Ericsson Radio * Systems AB and Canon Research Centre France S.A (collectively JJ2000 * Partners) agree not to assert against ISO/IEC and users of the JPEG * 2000 Standard (Users) any of their rights under the copyright, not * including other intellectual property rights, for this software module * with respect to the usage by ISO/IEC and Users of this software module * or modifications thereof for use in hardware or software products * claiming conformance to the JPEG 2000 Standard. Those intending to use * this software module in hardware or software products are advised that * their use may infringe existing patents. The original developers of * this software module, JJ2000 Partners and ISO/IEC assume no liability * for use of this software module or modifications thereof. No license * or right to this software module is granted for non JPEG 2000 Standard * conforming products. JJ2000 Partners have full right to use this * software module for his/her own purpose, assign or donate this * software module to any third party and to inhibit third parties from * using this software module for non JPEG 2000 Standard conforming * products. This copyright notice must be included in all copies or * derivative works of this software module. * * Copyright (c) 1999/2000 JJ2000 Partners. * */ package jj2000.j2k.codestream; /** * This interface defines the identifiers for the different bit stream * profiles and progression types. * *

    Each progressive type has a different number: 'PT_SNR_PROG', * 'PT_RES_PROG', or 'PT_ARB_PROG'. These are the same identifiers are used in * the codestream syntax. * *

    Each profile identifier is a flag bit. Therefore, several * profiles can appear at the same time. * *

    This interface defines the constants only. In order to use the constants * in any other class you can either use the fully qualified name (e.g., * ProgressionType.LY_RES_COMP_POS_PROG) or declare this interface in * the implements clause of the class and then access the identifier * directly.

    * */ public interface ProgressionType { /** The bit stream is Layer/Resolution/Component/Position progressive : 0 * */ public final static int LY_RES_COMP_POS_PROG = 0; /** The bit stream is Resolution/Layer/Component/Position progressive : 1 * */ public final static int RES_LY_COMP_POS_PROG = 1; /** The bit stream is Resolution/Position/Component/Layer progressive : 2 * */ public final static int RES_POS_COMP_LY_PROG = 2; /** The bit stream is Position/Component/Resolution/Layer progressive : 3 * */ public final static int POS_COMP_RES_LY_PROG = 3; /** The bit stream is Component/Position/Resolution/Layer progressive : 4 * */ public final static int COMP_POS_RES_LY_PROG = 4; } jai-imageio-core-1.2/src/share/classes/jj2000/j2k/codestream/CoordInfo.java0000664000175100017510000000665410203036165025270 0ustar tilletille/* * $RCSfile: CoordInfo.java,v $ * $Revision: 1.1 $ * $Date: 2005-02-11 05:01:59 $ * $State: Exp $ * * Class: CoordInfo * * Description: Used to store the coordinates of code-blocks/packets * * * * COPYRIGHT: * * This software module was originally developed by Raphal Grosbois and * Diego Santa Cruz (Swiss Federal Institute of Technology-EPFL); Joel * Askelf (Ericsson Radio Systems AB); and Bertrand Berthelot, David * Bouchard, Flix Henry, Gerard Mozelle and Patrice Onno (Canon Research * Centre France S.A) in the course of development of the JPEG2000 * standard as specified by ISO/IEC 15444 (JPEG 2000 Standard). This * software module is an implementation of a part of the JPEG 2000 * Standard. Swiss Federal Institute of Technology-EPFL, Ericsson Radio * Systems AB and Canon Research Centre France S.A (collectively JJ2000 * Partners) agree not to assert against ISO/IEC and users of the JPEG * 2000 Standard (Users) any of their rights under the copyright, not * including other intellectual property rights, for this software module * with respect to the usage by ISO/IEC and Users of this software module * or modifications thereof for use in hardware or software products * claiming conformance to the JPEG 2000 Standard. Those intending to use * this software module in hardware or software products are advised that * their use may infringe existing patents. The original developers of * this software module, JJ2000 Partners and ISO/IEC assume no liability * for use of this software module or modifications thereof. No license * or right to this software module is granted for non JPEG 2000 Standard * conforming products. JJ2000 Partners have full right to use this * software module for his/her own purpose, assign or donate this * software module to any third party and to inhibit third parties from * using this software module for non JPEG 2000 Standard conforming * products. This copyright notice must be included in all copies or * derivative works of this software module. * * Copyright (c) 1999/2000 JJ2000 Partners. * */ package jj2000.j2k.codestream; /** * This class is used to store the coordinates of objects such as code-blocks * or precincts. As this is an abstract class, it cannot be used directly but * derived classes have been created for code-blocks and packets * (CBlkCoordInfo and PrecCoordInfo). * * @see PrecCoordInfo * @see CBlkCoordInfo * */ public abstract class CoordInfo { /** Horizontal upper left coordinate in the subband */ public int ulx; /** Vertical upper left coordinate in the subband */ public int uly; /** Object's width */ public int w; /** Object's height */ public int h; /** * Constructor. Creates a CoordInfo object. * * @param ulx The horizontal upper left coordinate in the subband * * @param uly The vertical upper left coordinate in the subband * * @param w The width * * @param h The height * * @param idx The object's index * */ public CoordInfo(int ulx, int uly, int w, int h) { this.ulx = ulx; this.uly = uly; this.w = w; this.h = h; } /** Empty contructor */ public CoordInfo() { } /** * Returns object's information in a String * * @return String with object's information * */ public String toString() { return "ulx="+ulx+", uly="+uly+", w="+w+", h="+h; } } jai-imageio-core-1.2/src/share/classes/jj2000/j2k/codestream/writer/0000775000175100017510000000000011650556205024055 5ustar tilletillejai-imageio-core-1.2/src/share/classes/jj2000/j2k/codestream/writer/TagTreeEncoder.java0000664000175100017510000004342310203036165027550 0ustar tilletille/* * $RCSfile: TagTreeEncoder.java,v $ * $Revision: 1.1 $ * $Date: 2005-02-11 05:02:03 $ * $State: Exp $ * * Class: TagTreeEncoder * * Description: Encoder of tag trees * * * * COPYRIGHT: * * This software module was originally developed by Raphal Grosbois and * Diego Santa Cruz (Swiss Federal Institute of Technology-EPFL); Joel * Askelf (Ericsson Radio Systems AB); and Bertrand Berthelot, David * Bouchard, Flix Henry, Gerard Mozelle and Patrice Onno (Canon Research * Centre France S.A) in the course of development of the JPEG2000 * standard as specified by ISO/IEC 15444 (JPEG 2000 Standard). This * software module is an implementation of a part of the JPEG 2000 * Standard. Swiss Federal Institute of Technology-EPFL, Ericsson Radio * Systems AB and Canon Research Centre France S.A (collectively JJ2000 * Partners) agree not to assert against ISO/IEC and users of the JPEG * 2000 Standard (Users) any of their rights under the copyright, not * including other intellectual property rights, for this software module * with respect to the usage by ISO/IEC and Users of this software module * or modifications thereof for use in hardware or software products * claiming conformance to the JPEG 2000 Standard. Those intending to use * this software module in hardware or software products are advised that * their use may infringe existing patents. The original developers of * this software module, JJ2000 Partners and ISO/IEC assume no liability * for use of this software module or modifications thereof. No license * or right to this software module is granted for non JPEG 2000 Standard * conforming products. JJ2000 Partners have full right to use this * software module for his/her own purpose, assign or donate this * software module to any third party and to inhibit third parties from * using this software module for non JPEG 2000 Standard conforming * products. This copyright notice must be included in all copies or * derivative works of this software module. * * Copyright (c) 1999/2000 JJ2000 Partners. * * * */ package jj2000.j2k.codestream.writer; import jj2000.j2k.util.*; import jj2000.j2k.io.*; import java.io.*; /** * This class implements the tag tree encoder. A tag tree codes a 2D * matrix of integer elements in an efficient way. The encoding * procedure 'encode()' codes information about a value of the matrix, * given a threshold. The procedure encodes the sufficient information * to identify whether or not the value is greater than or equal to * the threshold. * *

    The tag tree saves encoded information to a BitOutputBuffer. * *

    A particular and useful property of tag trees is that it is * possible to change a value of the matrix, provided both new and old * values of the element are both greater than or equal to the largest * threshold which has yet been supplied to the coding procedure * 'encode()'. This property can be exploited through the 'setValue()' * method. * *

    This class allows saving the state of the tree at any point and * restoring it at a later time, by calling save() and restore(). * *

    A tag tree can also be reused, or restarted, if one of the * reset() methods is called. * *

    The TagTreeDecoder class implements the tag tree decoder. * *

    Tag trees that have one dimension, or both, as 0 are allowed for * convenience. Of course no values can be set or coded in such cases. * * @see BitOutputBuffer * * @see jj2000.j2k.codestream.reader.TagTreeDecoder * */ public class TagTreeEncoder { /** The horizontal dimension of the base level */ protected int w; /** The vertical dimensions of the base level */ protected int h; /** The number of levels in the tag tree */ protected int lvls; /** The tag tree values. The first index is the level, starting at * level 0 (leafs). The second index is the element within the * level, in lexicographical order. */ protected int treeV[][]; /** The tag tree state. The first index is the level, starting at * level 0 (leafs). The second index is the element within the * level, in lexicographical order. */ protected int treeS[][]; /** The saved tag tree values. The first index is the level, * starting at level 0 (leafs). The second index is the element * within the level, in lexicographical order. */ protected int treeVbak[][]; /** The saved tag tree state. The first index is the level, starting at * level 0 (leafs). The second index is the element within the * level, in lexicographical order. */ protected int treeSbak[][]; /** The saved state. If true the values and states of the tree * have been saved since the creation or last reset. */ protected boolean saved; /** * Creates a tag tree encoder with 'w' elements along the * horizontal dimension and 'h' elements along the vertical * direction. The total number of elements is thus 'vdim' x * 'hdim'. * *

    The values of all elements are initialized to Integer.MAX_VALUE. * * @param h The number of elements along the horizontal direction. * * @param w The number of elements along the vertical direction. * * * */ public TagTreeEncoder(int h, int w) { int k; // Check arguments if ( w < 0 || h < 0 ) { throw new IllegalArgumentException(); } // Initialize elements init(w,h); // Set values to max for (k = treeV.length-1; k >= 0; k--) { ArrayUtil.intArraySet(treeV[k],Integer.MAX_VALUE); } } /** * Creates a tag tree encoder with 'w' elements along the * horizontal dimension and 'h' elements along the vertical * direction. The total number of elements is thus 'vdim' x * 'hdim'. The values of the leafs in the tag tree are initialized * to the values of the 'val' array. * *

    The values in the 'val' array are supposed to appear in * lexicographical order, starting at index 0. * * @param h The number of elements along the horizontal direction. * * @param w The number of elements along the vertical direction. * * @param val The values with which initialize the leafs of the * tag tree. * * * */ public TagTreeEncoder(int h, int w, int val[]) { int k; // Check arguments if ( w < 0 || h < 0 || val.length < w*h ) { throw new IllegalArgumentException(); } // Initialize elements init(w,h); // Update leaf values for (k=w*h-1; k>=0; k--) { treeV[0][k]=val[k]; } // Calculate values at other levels recalcTreeV(); } /** * Returns the number of leafs along the horizontal direction. * * @return The number of leafs along the horizontal direction. * * * */ public final int getWidth() { return w; } /** * Returns the number of leafs along the vertical direction. * * @return The number of leafs along the vertical direction. * * * */ public final int getHeight() { return h; } /** * Initializes the variables of this class, given the dimensions * at the base level (leaf level). All the state ('treeS' array) * and values ('treeV' array) are intialized to 0. This method is * called by the constructors. * * @param w The number of elements along the vertical direction. * * @param h The number of elements along the horizontal direction. * * * */ private void init(int w, int h) { int i; // Initialize dimensions this.w = w; this.h = h; // Calculate the number of levels if (w == 0 || h == 0) { lvls = 0; } else { lvls = 1; while (h != 1 || w != 1) { // Loop until we reach root w = (w+1)>>1; h = (h+1)>>1; lvls++; } } // Allocate tree values and states // (no need to initialize to 0 since it's the default) treeV = new int[lvls][]; treeS = new int[lvls][]; w = this.w; h = this.h; for (i=0; i>1; h = (h+1)>>1; } } /** * Recalculates the values of the elements in the tag tree, in * levels 1 and up, based on the values of the leafs (level 0). * * * */ private void recalcTreeV() { int m,n,bi,lw,tm1,tm2,lh,k; // Loop on all other levels, updating minimum for (k=0; k>k; lh = (h+(1<>k; for (m=((lh>>1)<<1)-2;m>=0;m-=2) { // All quads with 2 lines for (n=((lw>>1)<<1)-2;n>=0;n-=2) { // All quads with 2 columns // Take minimum of 4 elements and put it in higher // level bi = m*lw+n; tm1 = (treeV[k][bi] < treeV[k][bi+1]) ? treeV[k][bi] : treeV[k][bi+1]; tm2 = (treeV[k][bi+lw] < treeV[k][bi+lw+1]) ? treeV[k][bi+lw] : treeV[k][bi+lw+1]; treeV[k+1][(m>>1)*((lw+1)>>1)+(n>>1)] = tm1 < tm2 ? tm1 : tm2; } // Now we may have quad with 1 column, 2 lines if (lw%2 != 0) { n = ((lw>>1)<<1); // Take minimum of 2 elements and put it in higher // level bi = m*lw+n; treeV[k+1][(m>>1)*((lw+1)>>1)+(n>>1)] = (treeV[k][bi] < treeV[k][bi+lw]) ? treeV[k][bi] : treeV[k][bi+lw]; } } // Now we may have quads with 1 line, 2 or 1 columns if (lh%2 != 0) { m = ((lh>>1)<<1); for (n=((lw>>1)<<1)-2;n>=0;n-=2) { // All quads with 2 columns // Take minimum of 2 elements and put it in higher // level bi = m*lw+n; treeV[k+1][(m>>1)*((lw+1)>>1)+(n>>1)] = (treeV[k][bi] < treeV[k][bi+1]) ? treeV[k][bi] : treeV[k][bi+1]; } // Now we may have quad with 1 column, 1 line if (lw%2 != 0) { // Just copy the value n = ((lw>>1)<<1); treeV[k+1][(m>>1)*((lw+1)>>1)+(n>>1)] = treeV[k][m*lw+n]; } } } } /** * Changes the value of a leaf in the tag tree. The new and old * values of the element must be not smaller than the largest * threshold which has yet been supplied to 'encode()'. * * @param m The vertical index of the element. * * @param n The horizontal index of the element. * * @param v The new value of the element. * * * */ public void setValue(int m, int n, int v) { int k,idx; // Check arguments if (lvls == 0 || n < 0 || n >= w || v < treeS[lvls-1][0] || treeV[0][m*w+n] < treeS[lvls-1][0]) { throw new IllegalArgumentException(); } // Update the leaf value treeV[0][m*w+n] = v; // Update all parents for (k=1; k>k)*((w+(1<>k)+(n>>k); if (v < treeV[k][idx]) { // We need to update minimum and continue checking // in higher levels treeV[k][idx] = v; } else { // We are done: v is equal or less to minimum // in this level, no other minimums to update. break; } } } /** * Sets the values of the leafs to the new set of values and * updates the tag tree accordingly. No leaf can change its value * if either the new or old value is smaller than largest * threshold which has yet been supplied to 'encode()'. However * such a leaf can keep its old value (i.e. new and old value must * be identical. * *

    This method is more efficient than the setValue() method if * a large proportion of the leafs change their value. Note that * for leafs which don't have their value defined yet the value * should be Integer.MAX_VALUE (which is the default * initialization value). * * @param val The new values for the leafs, in lexicographical order. * * @see #setValue * * * */ public void setValues(int val[]) { int i,maxt; if (lvls == 0) { // Can't set values on empty tree throw new IllegalArgumentException(); } // Check the values maxt = treeS[lvls-1][0]; for (i=w*h-1; i>=0; i--) { if ((treeV[0][i] < maxt || val[i] < maxt) && treeV[0][i] != val[i]) { throw new IllegalArgumentException(); } // Update leaf value treeV[0][i] = val[i]; } // Recalculate tree at other levels recalcTreeV(); } /** * Encodes information for the specified element of the tree, * given the threshold and sends it to the 'out' stream. The * information that is coded is whether or not the value of the * element is greater than or equal to the value of the threshold. * * @param m The vertical index of the element. * * @param n The horizontal index of the element. * * @param t The threshold to use for encoding. It must be non-negative. * * @param out The stream where to write the coded information. * * * */ public void encode(int m, int n, int t, BitOutputBuffer out) { int k,ts,idx,tmin; // Check arguments if (m >= h || n >= w || t < 0) { throw new IllegalArgumentException(); } // Initialize k = lvls-1; tmin = treeS[k][0]; // Loop on levels while (true) { // Index of element in level 'k' idx = (m>>k)*((w+(1<>k)+(n>>k); // Cache state ts = treeS[k][idx]; if (ts < tmin) { ts = tmin; } while (t > ts) { if (treeV[k][idx] > ts) { out.writeBit(0); // Send '0' bit } else if (treeV[k][idx] == ts) { out.writeBit(1); // Send '1' bit } else { // we are done: set ts and get out of this while ts = t; break; } // Increment of treeS[k][idx] ts++; } // Update state treeS[k][idx] = ts; // Update tmin or terminate if (k>0) { tmin = ts < treeV[k][idx] ? ts : treeV[k][idx]; k--; } else { // Terminate return; } } } /** * Saves the current values and state of the tree. Calling * restore() restores the tag tree the saved state. * * @see #restore * * * */ public void save() { int k,i; if (treeVbak == null) { // Nothing saved yet // Allocate saved arrays // treeV and treeS have the same dimensions treeVbak = new int[lvls][]; treeSbak = new int[lvls][]; for (k=lvls-1 ; k >= 0; k--) { treeVbak[k] = new int[treeV[k].length]; treeSbak[k] = new int[treeV[k].length]; } } // Copy the arrays for (k=treeV.length-1 ; k >= 0; k--) { System.arraycopy(treeV[k],0,treeVbak[k],0,treeV[k].length); System.arraycopy(treeS[k],0,treeSbak[k],0,treeS[k].length); } // Set saved state saved = true; } /** * Restores the saved values and state of the tree. An * IllegalArgumentException is thrown if the tree values and state * have not been saved yet. * * @see #save * * * */ public void restore() { int k,i; if (!saved) { // Nothing saved yet throw new IllegalArgumentException(); } // Copy the arrays for (k=lvls-1 ; k >= 0; k--) { System.arraycopy(treeVbak[k],0,treeV[k],0,treeV[k].length); System.arraycopy(treeSbak[k],0,treeS[k],0,treeS[k].length); } } /** * Resets the tree values and state. All the values are set to * Integer.MAX_VALUE and the states to 0. * * * */ public void reset() { int k; // Set all values to Integer.MAX_VALUE // and states to 0 for (k = lvls-1; k >= 0; k--) { ArrayUtil.intArraySet(treeV[k],Integer.MAX_VALUE); ArrayUtil.intArraySet(treeS[k],0); } // Invalidate saved tree saved = false; } /** * Resets the tree values and state. The values are set to the * values in 'val'. The states are all set to 0. * * @param val The new values for the leafs, in lexicographical order. * * * */ public void reset(int val[]) { int k; // Set values for leaf level for (k=w*h-1; k>=0; k--) { treeV[0][k] = val[k]; } // Calculate values at other levels recalcTreeV(); // Set all states to 0 for (k = lvls-1; k >= 0; k--) { ArrayUtil.intArraySet(treeS[k],0); } // Invalidate saved tree saved = false; } } jai-imageio-core-1.2/src/share/classes/jj2000/j2k/codestream/writer/PktEncoder.java0000664000175100017510000015636510203036165026765 0ustar tilletille/* * $RCSfile: PktEncoder.java,v $ * $Revision: 1.1 $ * $Date: 2005-02-11 05:02:03 $ * $State: Exp $ * * Class: PktEncoder * * Description: Builds bit stream packets and keeps * interpacket dependencies. * * * * COPYRIGHT: * * This software module was originally developed by Raphal Grosbois and * Diego Santa Cruz (Swiss Federal Institute of Technology-EPFL); Joel * Askelf (Ericsson Radio Systems AB); and Bertrand Berthelot, David * Bouchard, Flix Henry, Gerard Mozelle and Patrice Onno (Canon Research * Centre France S.A) in the course of development of the JPEG2000 * standard as specified by ISO/IEC 15444 (JPEG 2000 Standard). This * software module is an implementation of a part of the JPEG 2000 * Standard. Swiss Federal Institute of Technology-EPFL, Ericsson Radio * Systems AB and Canon Research Centre France S.A (collectively JJ2000 * Partners) agree not to assert against ISO/IEC and users of the JPEG * 2000 Standard (Users) any of their rights under the copyright, not * including other intellectual property rights, for this software module * with respect to the usage by ISO/IEC and Users of this software module * or modifications thereof for use in hardware or software products * claiming conformance to the JPEG 2000 Standard. Those intending to use * this software module in hardware or software products are advised that * their use may infringe existing patents. The original developers of * this software module, JJ2000 Partners and ISO/IEC assume no liability * for use of this software module or modifications thereof. No license * or right to this software module is granted for non JPEG 2000 Standard * conforming products. JJ2000 Partners have full right to use this * software module for his/her own purpose, assign or donate this * software module to any third party and to inhibit third parties from * using this software module for non JPEG 2000 Standard conforming * products. This copyright notice must be included in all copies or * derivative works of this software module. * * Copyright (c) 1999/2000 JJ2000 Partners. * */ package jj2000.j2k.codestream.writer; import java.awt.Point; import jj2000.j2k.wavelet.analysis.*; import jj2000.j2k.entropy.encoder.*; import jj2000.j2k.codestream.*; import jj2000.j2k.wavelet.*; import jj2000.j2k.image.*; import jj2000.j2k.util.*; import jj2000.j2k.*; import java.util.Vector; import com.sun.media.imageioimpl.plugins.jpeg2000.J2KImageWriteParamJava; /** * This class builds packets and keeps the state information of packet * interdependencies. It also supports saving the state and reverting * (restoring) to the last saved state, with the save() and restore() methods. * *

    Each time the encodePacket() method is called a new packet is encoded, * the packet header is returned by the method, and the packet body can be * obtained with the getLastBodyBuf() and getLastBodyLen() methods. * */ public class PktEncoder { /** The prefix for packet encoding options: 'P' */ public final static char OPT_PREFIX = 'P'; /** The list of parameters that is accepted for packet encoding.*/ private final static String [][] pinfo = { { "Psop", "[] true|false"+ "[ [] true|false ...]", "Specifies whether start of packet (SOP) markers should be used. "+ "'true' enables, 'false' disables it.","false"}, { "Peph", "[] true|false"+ "[ [] true|false ...]", "Specifies whether end of packet header (EPH) markers should be "+ " used. 'true' enables, 'false' disables it.","false"} }; /** The initial value for the lblock */ private final static int INIT_LBLOCK = 3; /** The source object */ private CodedCBlkDataSrcEnc infoSrc; /** The encoder specs */ J2KImageWriteParamJava wp; /** * The tag tree for inclusion information. The indexes are outlined * below. Note that the layer indexes start at 1, therefore, the layer * index minus 1 is used. The subband indices are used as they are defined * in the Subband class. The tile indices start at 0 and follow a * lexicographical order. * *

      *
    • 1st index: tile index, in lexicographical order
    • *
    • 2nd index: component index
    • *
    • 3rd index: resolution level
    • *
    • 4th index: subband index
    • *
    • 5th index: precinct index
    • *
    **/ private TagTreeEncoder ttIncl[][][][][]; /** * The tag tree for the maximum significant bit-plane. The indexes are * outlined below. Note that the layer indexes start at 1, therefore, the * layer index minus 1 is used. The subband indices are used as they are * defined in the Subband class. The tile indices start at 0 and follow a * lexicographical order. * *
      *
    • 1st index: tile index, in lexicographical order
    • *
    • 2nd index: component index
    • *
    • 3rd index: resolution level
    • *
    • 4th index: subband index - subband index offset
    • *
    • 5th index: precinct index
    • *
    * */ private TagTreeEncoder ttMaxBP[][][][][]; /** * The base number of bits for sending code-block length information * (referred as Lblock in the JPEG 2000 standard). The indexes are * outlined below. Note that the layer indexes start at 1, therefore, the * layer index minus 1 is used. The subband indices are used as they are * defined in the Subband class. The tile indices start at 0 and follow a * lexicographical order. * *
      *
    • 1st index: tile index, in lexicographical order
    • *
    • 2nd index: component index
    • *
    • 3rd index: resolution level
    • *
    • 4th index: subband index - subband index offset
    • *
    • 5th index: code-block index, in lexicographical order
    • *
    * */ private int lblock[][][][][]; /** * The last encoded truncation point for each code-block. A negative value * means that no information has been included for the block, yet. The * indexes are outlined below. The subband indices are used as they are * defined in the Subband class. The tile indices start at 0 and follow a * lexicographical order. The code-block indices follow a lexicographical * order within the subband tile. * *

    What is actually stored is the index of the element in * CBlkRateDistStats.truncIdxs that gives the real truncation point. * *

      *
    • 1st index: tile index, in lexicographical order
    • *
    • 2nd index: component index
    • *
    • 3rd index: resolution level
    • *
    • 4th index: subband index - subband index offset
    • *
    • 5th index: code-block index, in lexicographical order
    • *
    * */ private int prevtIdxs[][][][][]; /** * The saved base number of bits for sending code-block length * information. It is used for restoring previous saved state by * restore(). The indexes are outlined below. Note that the layer indexes * start at 1, therefore, the layer index minus 1 is used. The subband * indices are used as they are defined in the Subband class. The tile * indices start at 0 and follow a lexicographical order. * *
      *
    • 1st index: tile index, in lexicographical order
    • *
    • 2nd index: component index
    • *
    • 3rd index: resolution level
    • *
    • 4th index: subband index - subband index offset
    • *
    • 5th index: code-block index, in lexicographical order
    • *
    * */ private int bak_lblock[][][][][]; /** * The saved last encoded truncation point for each code-block. It is used * for restoring previous saved state by restore(). A negative value means * that no information has been included for the block, yet. The indexes * are outlined below. The subband indices are used as they are defined in * the Subband class. The tile indices start at 0 and follow a * lexicographical order. The code-block indices follow a lexicographical * order within the subband tile. * *
      *
    • 1st index: tile index, in lexicographical order
    • *
    • 2nd index: component index
    • *
    • 3rd index: resolution level
    • *
    • 4th index: subband index - subband index offset
    • *
    • 5th index: code-block index, in lexicographical order
    • *
    * */ private int bak_prevtIdxs[][][][][]; /** The body buffer of the last encoded packet */ private byte[] lbbuf; /** The body length of the last encoded packet */ private int lblen; /** The saved state */ private boolean saved; /** Whether or not there is ROI information in the last encoded Packet */ private boolean roiInPkt = false; /** Length to read in current packet body to get all the ROI information */ private int roiLen = 0; /** * Array containing the coordinates, width, height, indexes, ... of the * precincts. * *
      *
    • 1st dim: tile index.
    • *
    • 2nd dim: component index.
    • *
    • 3rd dim: resolution level index.
    • *
    • 4th dim: precinct index.
    • *
    * */ private PrecInfo ppinfo[][][][]; /** Whether or not the current packet is writable */ private boolean packetWritable; /** * Creates a new packet header encoder, using the information from the * 'infoSrc' object. The information used is the number of components, * number of tiles, subband decomposition, etc. * *

    Note that this constructor visits all the tiles in the 'infoSrc' * object. The 'infoSrc' object is left at the original tile (i.e. the * current tile before calling this constructor), but any side effects of * visiting the tiles is not reverted. * * @param infoSrc The source of information to construct the * object. * * @param encSpec The parameters for the encoding * * @param maxNumPrec Maximum number of precinct in each tile, component * and resolution level. * * @param pl ParameterList instance that holds command line options * */ public PktEncoder(CodedCBlkDataSrcEnc infoSrc, J2KImageWriteParamJava wp, Point[][][] numPrec) { this.infoSrc = infoSrc; this.wp = wp; // this.numPrec = numPrec; // Get number of components and tiles int nc = infoSrc.getNumComps(); int nt = infoSrc.getNumTiles(); // Do initial allocation ttIncl = new TagTreeEncoder[nt][nc][][][]; ttMaxBP = new TagTreeEncoder[nt][nc][][][]; lblock = new int[nt][nc][][][]; prevtIdxs = new int[nt][nc][][][]; ppinfo = new PrecInfo[nt][nc][][]; // Finish allocation SubbandAn root,sb; int maxs,mins; int mrl; Point tmpCoord = null; int numcb; // Number of code-blocks Vector cblks = null; infoSrc.setTile(0,0); for (int t=0; tsb.ulcx+sb.w) ? sb.ulcx+sb.w : p1x; s0y = (p0ysb.ulcy+sb.h) ? sb.ulcy+sb.h : p1y; // Code-blocks are located at (acb0x+k*cw,acb0y+l*ch) cw = sb.nomCBlkW; ch = sb.nomCBlkH; k0 = (int)Math.floor((sb.ulcy-acb0y)/(double)ch); kstart = (int)Math.floor((s0y-acb0y)/(double)ch); kend = (int)Math.floor((s1y-1-acb0y)/(double)ch); l0 = (int)Math.floor((sb.ulcx-acb0x)/(double)cw); lstart = (int)Math.floor((s0x-acb0x)/(double)cw); lend = (int)Math.floor((s1x-1-acb0x)/(double)cw); if(s1x-s0x<=0 || s1y-s0y<=0) { ppinfo[t][c][r][nPrec].nblk[0] = 0; ttIncl[t][c][r][nPrec][0] = new TagTreeEncoder(0,0); ttMaxBP[t][c][r][nPrec][0] = new TagTreeEncoder(0,0); } else { ttIncl[t][c][r][nPrec][0] = new TagTreeEncoder(kend-kstart+1,lend-lstart+1); ttMaxBP[t][c][r][nPrec][0] = new TagTreeEncoder(kend-kstart+1,lend-lstart+1); ppinfo[t][c][r][nPrec].cblk[0] = new CBlkCoordInfo[kend-kstart+1][lend-lstart+1]; ppinfo[t][c][r][nPrec]. nblk[0] = (kend-kstart+1)*(lend-lstart+1); for(int k=kstart; k<=kend; k++) { // Vertical cblks for(int l=lstart; l<=lend; l++) { // Horiz. cblks cb = new CBlkCoordInfo(k-k0,l-l0); ppinfo[t][c][r][nPrec]. cblk[0][k-kstart][l-lstart] = cb; } // Horizontal code-blocks } // Vertical code-blocks } } else { // HL, LH and HH subbands // HL subband acb0x = 0; acb0y = cb0y; p0x = acb0x+j*twoppx2; p1x = p0x + twoppx2; p0y = acb0y+i*twoppy2; p1y = p0y + twoppy2; sb = (SubbandAn)root.getSubbandByIdx(r,1); s0x = (p0xsb.ulcx+sb.w) ? sb.ulcx+sb.w : p1x; s0y = (p0ysb.ulcy+sb.h) ? sb.ulcy+sb.h : p1y; // Code-blocks are located at (acb0x+k*cw,acb0y+l*ch) cw = sb.nomCBlkW; ch = sb.nomCBlkH; k0 = (int)Math.floor((sb.ulcy-acb0y)/(double)ch); kstart = (int)Math.floor((s0y-acb0y)/(double)ch); kend = (int)Math.floor((s1y-1-acb0y)/(double)ch); l0 = (int)Math.floor((sb.ulcx-acb0x)/(double)cw); lstart = (int)Math.floor((s0x-acb0x)/(double)cw); lend = (int)Math.floor((s1x-1-acb0x)/(double)cw); if(s1x-s0x<=0 || s1y-s0y<=0) { ppinfo[t][c][r][nPrec].nblk[1] = 0; ttIncl[t][c][r][nPrec][1] = new TagTreeEncoder(0,0); ttMaxBP[t][c][r][nPrec][1] = new TagTreeEncoder(0,0); } else { ttIncl[t][c][r][nPrec][1] = new TagTreeEncoder(kend-kstart+1,lend-lstart+1); ttMaxBP[t][c][r][nPrec][1] = new TagTreeEncoder(kend-kstart+1,lend-lstart+1); ppinfo[t][c][r][nPrec].cblk[1] = new CBlkCoordInfo[kend-kstart+1][lend-lstart+1]; ppinfo[t][c][r][nPrec]. nblk[1] = (kend-kstart+1)*(lend-lstart+1); for(int k=kstart; k<=kend; k++) { // Vertical cblks for(int l=lstart; l<=lend; l++) { // Horiz. cblks cb = new CBlkCoordInfo(k-k0,l-l0); ppinfo[t][c][r][nPrec]. cblk[1][k-kstart][l-lstart] = cb; } // Horizontal code-blocks } // Vertical code-blocks } // LH subband acb0x = cb0x; acb0y = 0; p0x = acb0x+j*twoppx2; p1x = p0x + twoppx2; p0y = acb0y+i*twoppy2; p1y = p0y + twoppy2; sb = (SubbandAn)root.getSubbandByIdx(r,2); s0x = (p0xsb.ulcx+sb.w) ? sb.ulcx+sb.w : p1x; s0y = (p0ysb.ulcy+sb.h) ? sb.ulcy+sb.h : p1y; // Code-blocks are located at (acb0x+k*cw,acb0y+l*ch) cw = sb.nomCBlkW; ch = sb.nomCBlkH; k0 = (int)Math.floor((sb.ulcy-acb0y)/(double)ch); kstart = (int)Math.floor((s0y-acb0y)/(double)ch); kend = (int)Math.floor((s1y-1-acb0y)/(double)ch); l0 = (int)Math.floor((sb.ulcx-acb0x)/(double)cw); lstart = (int)Math.floor((s0x-acb0x)/(double)cw); lend = (int)Math.floor((s1x-1-acb0x)/(double)cw); if(s1x-s0x<=0 || s1y-s0y<=0) { ppinfo[t][c][r][nPrec].nblk[2] = 0; ttIncl[t][c][r][nPrec][2] = new TagTreeEncoder(0,0); ttMaxBP[t][c][r][nPrec][2] = new TagTreeEncoder(0,0); } else { ttIncl[t][c][r][nPrec][2] = new TagTreeEncoder(kend-kstart+1,lend-lstart+1); ttMaxBP[t][c][r][nPrec][2] = new TagTreeEncoder(kend-kstart+1,lend-lstart+1); ppinfo[t][c][r][nPrec].cblk[2] = new CBlkCoordInfo[kend-kstart+1][lend-lstart+1]; ppinfo[t][c][r][nPrec]. nblk[2] = (kend-kstart+1)*(lend-lstart+1); for(int k=kstart; k<=kend; k++) { // Vertical cblks for(int l=lstart; l<=lend; l++) { // Horiz cblks cb = new CBlkCoordInfo(k-k0,l-l0); ppinfo[t][c][r][nPrec]. cblk[2][k-kstart][l-lstart] = cb; } // Horizontal code-blocks } // Vertical code-blocks } // HH subband acb0x = 0; acb0y = 0; p0x = acb0x+j*twoppx2; p1x = p0x + twoppx2; p0y = acb0y+i*twoppy2; p1y = p0y + twoppy2; sb = (SubbandAn)root.getSubbandByIdx(r,3); s0x = (p0xsb.ulcx+sb.w) ? sb.ulcx+sb.w : p1x; s0y = (p0ysb.ulcy+sb.h) ? sb.ulcy+sb.h : p1y; // Code-blocks are located at (acb0x+k*cw,acb0y+l*ch) cw = sb.nomCBlkW; ch = sb.nomCBlkH; k0 = (int)Math.floor((sb.ulcy-acb0y)/(double)ch); kstart = (int)Math.floor((s0y-acb0y)/(double)ch); kend = (int)Math.floor((s1y-1-acb0y)/(double)ch); l0 = (int)Math.floor((sb.ulcx-acb0x)/(double)cw); lstart = (int)Math.floor((s0x-acb0x)/(double)cw); lend = (int)Math.floor((s1x-1-acb0x)/(double)cw); if(s1x-s0x<=0 || s1y-s0y<=0) { ppinfo[t][c][r][nPrec].nblk[3] = 0; ttIncl[t][c][r][nPrec][3] = new TagTreeEncoder(0,0); ttMaxBP[t][c][r][nPrec][3] = new TagTreeEncoder(0,0); } else { ttIncl[t][c][r][nPrec][3] = new TagTreeEncoder(kend-kstart+1,lend-lstart+1); ttMaxBP[t][c][r][nPrec][3] = new TagTreeEncoder(kend-kstart+1,lend-lstart+1); ppinfo[t][c][r][nPrec].cblk[3] = new CBlkCoordInfo[kend-kstart+1][lend-lstart+1]; ppinfo[t][c][r][nPrec]. nblk[3] = (kend-kstart+1)*(lend-lstart+1); for(int k=kstart; k<=kend; k++) { // Vertical cblks for(int l=lstart; l<=lend; l++) { // Horiz cblks cb = new CBlkCoordInfo(k-k0,l-l0); ppinfo[t][c][r][nPrec]. cblk[3][k-kstart][l-lstart] = cb; } // Horizontal code-blocks } // Vertical code-blocks } } } // Horizontal precincts } // Vertical precincts } /** * Encodes a packet and returns the buffer containing the encoded packet * header. The code-blocks appear in a 3D array of CBlkRateDistStats, * 'cbs'. The first index is the tile index in lexicographical order, the * second index is the subband index (as defined in the Subband class), * and the third index is the code-block index (whithin the subband tile) * in lexicographical order as well. The indexes of the new truncation * points for each code-block are specified by the 3D array of int * 'tIndx'. The indices of this array are the same as for cbs. The * truncation point indices in 'tIndx' are the indices of the elements of * the 'truncIdxs' array, of the CBlkRateDistStats class, that give the * real truncation points. If a truncation point index is negative it * means that the code-block has not been included in any layer yet. If * the truncation point is less than or equal to the highest truncation * point used in previous layers then the code-block is not included in * the packet. Otherwise, if larger, the code-block is included in the * packet. The body of the packet can be obtained with the * getLastBodyBuf() and getLastBodyLen() methods. * *

    Layers must be coded in increasing order, in consecutive manner, for * each tile, component and resolution level (e.g., layer 1, then layer 2, * etc.). For different tile, component and/or resolution level no * particular order must be followed.

    * * @param ly The layer index (starts at 1). * * @param c The component index. * * @param r The resolution level * * @param t Index of the current tile * * @param cbs The 3D array of coded code-blocks. * * @param tIndx The truncation point indices for each code-block. * * @param hbuf The header buffer. If null a new BitOutputBuffer is created * and returned. This buffer is reset before anything is written to it. * * @param bbuf The body buffer. If null a new one is created. If not large * enough a new one is created. * * @param pIdx The precinct index. * * @return The buffer containing the packet header. * */ public BitOutputBuffer encodePacket(int ly,int c,int r,int t, CBlkRateDistStats cbs[][], int tIndx[][],BitOutputBuffer hbuf, byte bbuf[],int pIdx) { int b,i,maxi; int ncb; int thmax; int newtp; int cblen; int prednbits,nbits,deltabits; TagTreeEncoder cur_ttIncl,cur_ttMaxBP; // inclusion and bit-depth tag // trees int cur_prevtIdxs[]; // last encoded truncation points CBlkRateDistStats cur_cbs[]; int cur_tIndx[]; // truncation points to encode int minsb = (r==0) ? 0 : 1; int maxsb = (r==0) ? 1 : 4; Point cbCoord = null; SubbandAn root = infoSrc.getAnSubbandTree(t,c); SubbandAn sb; roiInPkt = false; roiLen = 0; int mend,nend; // Checks if a precinct with such an index exists in this resolution // level if(pIdx>=ppinfo[t][c][r].length) { packetWritable = false; return hbuf; } PrecInfo prec = ppinfo[t][c][r][pIdx]; // First, we check if packet is empty (i.e precinct 'pIdx' has no // code-block in any of the subbands) boolean isPrecVoid = true; for(int s=minsb; s // stop isPrecVoid = false; break; } } if(isPrecVoid) { packetWritable = true; if(hbuf == null) { hbuf = new BitOutputBuffer(); } else { hbuf.reset(); } if (bbuf == null) { lbbuf = bbuf = new byte[1]; } hbuf.writeBit(0); lblen = 0; return hbuf; } if(hbuf == null) { hbuf = new BitOutputBuffer(); } else { hbuf.reset(); } // Invalidate last body buffer lbbuf = null; lblen = 0; // Signal that packet is present hbuf.writeBit(1); for(int s=minsb; scur_prevtIdxs[b] && cur_prevtIdxs[b]<0) { // First inclusion cur_ttIncl.setValue(m,n,ly-1); } if (ly==1) { // First layer, need to set the skip of MSBP cur_ttMaxBP.setValue(m,n,cur_cbs[b].skipMSBP); } } } // Now encode the information for(int m=0; mcur_prevtIdxs[b]) { // Code-block included in this layer if (cur_prevtIdxs[b]<0) { // First inclusion // Encode layer info cur_ttIncl.encode(m,n,ly,hbuf); // 2) Max bitdepth info. Encode value thmax = cur_cbs[b].skipMSBP+1; for (i=1; i<=thmax; i++) { cur_ttMaxBP.encode(m,n,i,hbuf); } // Count body size for packet lblen += cur_cbs[b]. truncRates[cur_cbs[b].truncIdxs[cur_tIndx[b]]]; } else { // Already in previous layer // Send "1" bit hbuf.writeBit(1); // Count body size for packet lblen += cur_cbs[b]. truncRates[cur_cbs[b]. truncIdxs[cur_tIndx[b]]] - cur_cbs[b]. truncRates[cur_cbs[b]. truncIdxs[cur_prevtIdxs[b]]]; } // 3) Truncation point information if (cur_prevtIdxs[b]<0) { newtp = cur_cbs[b].truncIdxs[cur_tIndx[b]]; } else { newtp = cur_cbs[b].truncIdxs[cur_tIndx[b]]- cur_cbs[b].truncIdxs[cur_prevtIdxs[b]]-1; } // Mix of switch and if is faster switch (newtp) { case 0: hbuf.writeBit(0); // Send one "0" bit break; case 1: hbuf.writeBits(2,2); // Send one "1" and one "0" break; case 2: case 3: case 4: // Send two "1" bits followed by 2 bits // representation of newtp-2 hbuf.writeBits((3<<2)|(newtp-2),4); break; default: if (newtp <= 35) { // Send four "1" bits followed by a five bits // representation of newtp-5 hbuf.writeBits((15<<5)|(newtp-5),9); } else if (newtp <= 163) { // Send nine "1" bits followed by a seven bits // representation of newtp-36 hbuf.writeBits((511<<7)|(newtp-36),16); } else { throw new ArithmeticException("Maximum number "+ "of truncation "+ "points exceeded"); } } } else { // Block not included in this layer if (cur_prevtIdxs[b]>=0) { // Already in previous layer. Send "0" bit hbuf.writeBit(0); } else { // Not in any previous layers cur_ttIncl.encode(m,n,ly,hbuf); } // Go to the next one. continue; } // Code-block length // We need to compute the maximum number of bits needed to // signal the length of each terminated segment and the // final truncation point. newtp = 1; maxi = cur_cbs[b].truncIdxs[cur_tIndx[b]]; cblen = (cur_prevtIdxs[b]<0) ? 0 : cur_cbs[b].truncRates[cur_cbs[b]. truncIdxs[cur_prevtIdxs[b]]]; // Loop on truncation points i = (cur_prevtIdxs[b]<0) ? 0 : cur_cbs[b].truncIdxs[cur_prevtIdxs[b]]+1; int minbits = 0; for (; i0) ? MathUtil.log2(cblen) : 0)+1; // Update Lblock increment if needed for(int j=prednbits; j0) ? MathUtil.log2(cblen) : 0)+1; // Update Lblock increment if needed for(int j=prednbits; j Copy the data to the body buffer // Ensure size for body data if (bbuf==null || bbuf.lengthcur_prevtIdxs[b]) { // Block included in this precinct -> Copy data to // body buffer and get code-size if (cur_prevtIdxs[b]<0) { cblen = cur_cbs[b]. truncRates[cur_cbs[b].truncIdxs[cur_tIndx[b]]]; System.arraycopy(cur_cbs[b].data,0, lbbuf,lblen,cblen); } else { cblen = cur_cbs[b]. truncRates[cur_cbs[b]. truncIdxs[cur_tIndx[b]]] - cur_cbs[b]. truncRates[cur_cbs[b]. truncIdxs[cur_prevtIdxs[b]]]; System. arraycopy(cur_cbs[b].data, cur_cbs[b]. truncRates[cur_cbs[b]. truncIdxs[cur_prevtIdxs [b]]], lbbuf,lblen,cblen); } lblen += cblen; // Verifies if this code-block contains new ROI // information if(cur_cbs[b].nROIcoeff!=0 && (cur_prevtIdxs[b]==-1 || cur_cbs[b].truncIdxs[cur_prevtIdxs[b]] <= cur_cbs[b].nROIcp-1) ) { roiInPkt = true; roiLen = lblen; } // Update truncation point cur_prevtIdxs[b] = cur_tIndx[b]; } } // End loop on horizontal code-blocks } // End loop on vertical code-blocks } // End loop on subbands packetWritable = true; // Must never happen if(hbuf.getLength()==0) { throw new Error("You have found a bug in PktEncoder, method:"+ " encodePacket"); } return hbuf; } /** * Returns the buffer of the body of the last encoded packet. The length * of the body can be retrieved with the getLastBodyLen() method. The * length of the array returned by this method may be larger than the * actual body length. * * @return The buffer of body of the last encoded packet. * * @exception IllegalArgumentException If no packet has been coded since * last reset(), last restore(), or object creation. * * @see #getLastBodyLen * */ public byte[] getLastBodyBuf() { if (lbbuf == null) { throw new IllegalArgumentException(); } return lbbuf; } /** * Returns the length of the body of the last encoded packet, in * bytes. The body itself can be retrieved with the getLastBodyBuf() * method. * * @return The length of the body of last encoded packet, in bytes. * * @see #getLastBodyBuf * */ public int getLastBodyLen() { return lblen; } /** * Saves the current state of this object. The last saved state * can be restored with the restore() method. * * @see #restore * */ public void save() { int maxsbi,minsbi; // Have we done any save yet? if (bak_lblock==null) { // Allocate backup buffers bak_lblock = new int[ttIncl.length][][][][]; bak_prevtIdxs = new int[ttIncl.length][][][][]; for (int t=ttIncl.length-1; t>=0; t--) { bak_lblock[t] = new int[ttIncl[t].length][][][]; bak_prevtIdxs[t] = new int[ttIncl[t].length][][][]; for (int c=ttIncl[t].length-1; c>=0; c--) { bak_lblock[t][c] = new int[lblock[t][c].length][][]; bak_prevtIdxs[t][c] = new int[ttIncl[t][c].length][][]; for (int r=lblock[t][c].length-1; r>=0; r--) { bak_lblock[t][c][r] = new int[lblock[t][c][r].length][]; bak_prevtIdxs[t][c][r] = new int[prevtIdxs[t][c][r].length][]; minsbi = (r==0) ? 0 : 1; maxsbi = (r==0) ? 1 : 4; for (int s=minsbi; s=0; t--) { // Loop on components for (int c=ttIncl[t].length-1; c>=0; c--) { // Initialize reference caches lblock_t_c = lblock[t][c]; bak_lblock_t_c = bak_lblock[t][c]; ttIncl_t_c = ttIncl[t][c]; ttMaxBP_t_c = ttMaxBP[t][c]; // Loop on resolution levels for (int r=lblock_t_c.length-1; r>=0; r--) { // Initialize reference caches ttIncl_t_c_r = ttIncl_t_c[r]; ttMaxBP_t_c_r = ttMaxBP_t_c[r]; prevtIdxs_t_c_r = prevtIdxs[t][c][r]; bak_prevtIdxs_t_c_r = bak_prevtIdxs[t][c][r]; // Loop on subbands minsbi = (r==0) ? 0 : 1; maxsbi = (r==0) ? 1 : 4; for (int s=minsbi; s=0; p--) { if(p=0; t--) { // Loop on components for (int c=ttIncl[t].length-1; c>=0; c--) { // Initialize reference caches lblock_t_c = lblock[t][c]; bak_lblock_t_c = bak_lblock[t][c]; ttIncl_t_c = ttIncl[t][c]; ttMaxBP_t_c = ttMaxBP[t][c]; // Loop on resolution levels for (int r=lblock_t_c.length-1; r>=0; r--) { // Initialize reference caches ttIncl_t_c_r = ttIncl_t_c[r]; ttMaxBP_t_c_r = ttMaxBP_t_c[r]; prevtIdxs_t_c_r = prevtIdxs[t][c][r]; bak_prevtIdxs_t_c_r = bak_prevtIdxs[t][c][r]; // Loop on subbands minsbi = (r==0) ? 0 : 1; maxsbi = (r==0) ? 1 : 4; for (int s=minsbi; s=0; p--) { if(p=0; t--) { // Loop on components for (int c=ttIncl[t].length-1; c>=0; c--) { // Initialize reference caches lblock_t_c = lblock[t][c]; ttIncl_t_c = ttIncl[t][c]; ttMaxBP_t_c = ttMaxBP[t][c]; // Loop on resolution levels for (int r=lblock_t_c.length-1; r>=0; r--) { // Initialize reference caches ttIncl_t_c_r = ttIncl_t_c[r]; ttMaxBP_t_c_r = ttMaxBP_t_c[r]; prevtIdxs_t_c_r = prevtIdxs[t][c][r]; // Loop on subbands minsbi = (r==0) ? 0 : 1; maxsbi = (r==0) ? 1 : 4; for (int s=minsbi; s=0; p--) { if(pA marker segment includes a marker and eventually marker segment * parameters. It is designed by the three letter code of the marker * associated with the marker segment. JPEG 2000 part I defines 6 types of * markers:
    • Delimiting : SOC,SOT,SOD,EOC (written in * FileCodestreamWriter).
    • Fixed information: SIZ.
    • * Functional: COD,COC,RGN,QCD,QCC,POC.
    • In bit-stream: SOP,EPH.
    • *
    • Pointer: TLM,PLM,PLT,PPM,PPT.
    • Informational: * CRG,COM.
    * *

    Main Header is written when Encoder instance calls encodeMainHeader * whereas tile-part headers are written when the EBCOTRateAllocator instance * calls encodeTilePartHeader. * * @see Encoder * @see Markers * @see EBCOTRateAllocator * */ public class HeaderEncoder implements Markers, StdEntropyCoderOptions { /** Nominal range bit of the component defining default values in QCD for * main header */ private int defimgn; /** Nominal range bit of the component defining default values in QCD for * tile headers */ private int deftilenr; /** The number of components in the image */ protected int nComp; /** Whether or not to write the JJ2000 COM marker segment */ private boolean enJJ2KMarkSeg = true; /** Other COM marker segments specified in the command line */ private String otherCOMMarkSeg = null; /** The ByteArrayOutputStream to store header data. This handler * is kept in order to use methods not accessible from a general * DataOutputStream. For the other methods, it's better to use * variable hbuf. * * @see #hbuf */ protected ByteArrayOutputStream baos; /** The DataOutputStream to store header data. This kind of object * is useful to write short, int, .... It's constructor takes * baos as parameter. * * @see #baos **/ protected DataOutputStream hbuf; /** The image data reader. Source of original data info */ protected ImgData origSrc; /** An array specifying, for each component,if the data was signed or not */ protected boolean isOrigSig[]; /** Reference to the rate allocator */ protected PostCompRateAllocator ralloc; /** Reference to the DWT module */ protected ForwardWT dwt; /** Reference to the tiler module */ protected Tiler tiler; /** Reference to the ROI module */ protected ROIScaler roiSc; /** The encoder specifications */ protected J2KImageWriteParamJava wp; /** * Initializes the header writer with the references to the coding chain. * * @param origsrc The original image data (before any component mixing, * tiling, etc.) * * @param isorigsig An array specifying for each component if it was * originally signed or not. * * @param dwt The discrete wavelet transform module. * * @param tiler The tiler module. * * @param encSpec The encoder specifications * * @param roiSc The ROI scaler module. * * @param ralloc The post compression rate allocator. * */ public HeaderEncoder(ImgData origsrc, boolean isorigsig[], ForwardWT dwt, Tiler tiler,J2KImageWriteParamJava wp, ROIScaler roiSc, PostCompRateAllocator ralloc) { if (origsrc.getNumComps() != isorigsig.length) { throw new IllegalArgumentException(); } this.origSrc = origsrc; this.isOrigSig = isorigsig; this.dwt = dwt; this.tiler = tiler; this.wp = wp; this.roiSc = roiSc; this.ralloc = ralloc; baos = new ByteArrayOutputStream(); hbuf = new DataOutputStream(baos); nComp = origsrc.getNumComps(); // enJJ2KMarkSeg = wp.getHjj2000_COM(); // otherCOMMarkSeg = wp.getHCOM(); } /** * Resets the contents of this HeaderEncoder to its initial state. It * erases all the data in the header buffer and reactualizes the * headerLength field of the bit stream writer. * */ public void reset() { baos.reset(); hbuf = new DataOutputStream(baos); } /** * Returns the byte-buffer used to store the codestream header. * * @return A byte array countaining codestream header * */ protected byte[] getBuffer(){ return baos.toByteArray(); } /** * Returns the length of the header. * * @return The length of the header in bytes * */ public int getLength() { return hbuf.size(); } /** * Writes the header to the specified BinaryDataOutput. * * @param out Where to write the header. * */ public void writeTo(BinaryDataOutput out) throws IOException { int i,len; byte buf[]; buf = getBuffer(); len = getLength(); for (i=0; iThe values can be overriden for an individual component by a COC * marker in either the main or the tile header. * * @param mh Flag indicating whether this marker belongs to the main * header * * @param tileIdx Tile index if the marker belongs to a tile-part header * * @see #writeCOC * */ protected void writeCOD(boolean mh, int tileIdx) throws IOException { AnWTFilter[][] filt; boolean precinctPartitionUsed; int tmp; int mrl=0,a=0; int ppx=0, ppy=0; Progression[] prog; if (mh) { mrl = ((Integer)wp.getDecompositionLevel().getDefault()).intValue(); // get default precinct size ppx = wp.getPrecinctPartition().getPPX(-1,-1,mrl); ppy = wp.getPrecinctPartition().getPPY(-1,-1,mrl); prog = (Progression[])(wp.getProgressionType().getDefault()); } else { mrl = ((Integer)wp.getDecompositionLevel().getTileDef(tileIdx)).intValue(); // get precinct size for specified tile ppx = wp.getPrecinctPartition().getPPX(tileIdx,-1,mrl); ppy = wp.getPrecinctPartition().getPPY(tileIdx,-1,mrl); prog = (Progression[])(wp.getProgressionType().getTileDef(tileIdx)); } if ( ppx != PRECINCT_PARTITION_DEF_SIZE || ppy != PRECINCT_PARTITION_DEF_SIZE ) { precinctPartitionUsed = true; } else { precinctPartitionUsed = false; } if ( precinctPartitionUsed ) { // If precinct partition is used we add one byte per resolution // level i.e. mrl+1 (+1 for resolution 0). a = mrl+1; } // Write COD marker hbuf.writeShort(COD); // Lcod (marker segment length (in bytes)) Basic : Lcod(2 // bytes)+Scod(1)+SGcod(4)+SPcod(5+a) where: // a=0 if no precinct partition is used // a=mrl+1 if precinct partition used int markSegLen = 12+a; hbuf.writeShort(markSegLen); // Scod (coding style parameter) tmp=0; if ( precinctPartitionUsed ) tmp=SCOX_PRECINCT_PARTITION; // Are SOP markers used ? if (mh) { if( ((String)wp.getSOP().getDefault().toString()) .equalsIgnoreCase("true") ) { tmp |= SCOX_USE_SOP; } } else { if ( ((String)wp.getSOP().getTileDef(tileIdx).toString()) .equalsIgnoreCase("true") ) { tmp |= SCOX_USE_SOP; } } // Are EPH markers used ? if(mh){ if ( ((String)wp.getEPH().getDefault().toString()) .equalsIgnoreCase("true") ) { tmp |= SCOX_USE_EPH; } } else{ if ( ((String)wp.getEPH().getTileDef(tileIdx).toString()) .equalsIgnoreCase("true") ) { tmp |= SCOX_USE_EPH; } } if (dwt.getCbULX()!=0) tmp |= SCOX_HOR_CB_PART; if (dwt.getCbULY()!=0) tmp |= SCOX_VER_CB_PART; hbuf.write(tmp); // SGcod // Progression order hbuf.write(prog[0].type); // Number of layers hbuf.writeShort(ralloc.getNumLayers()); // Multiple component transform // CSsiz (Color transform) String str = null; if(mh) str = (String)wp.getComponentTransformation().getDefault(); else str = (String)wp.getComponentTransformation().getTileDef(tileIdx); if(str.equals("none")) hbuf.write(0); else hbuf.write(1); // SPcod // Number of decomposition levels hbuf.write(mrl); // Code-block width and height if ( mh ) { // main header, get default values tmp = wp.getCodeBlockSize(). getCBlkWidth(ModuleSpec.SPEC_DEF,-1,-1); hbuf.write(MathUtil.log2(tmp)-2); tmp = wp.getCodeBlockSize(). getCBlkHeight(ModuleSpec.SPEC_DEF,-1,-1); hbuf.write(MathUtil.log2(tmp)-2); } else { // tile header, get tile default values tmp = wp.getCodeBlockSize(). getCBlkWidth(ModuleSpec.SPEC_TILE_DEF,tileIdx,-1); hbuf.write(MathUtil.log2(tmp)-2); tmp = wp.getCodeBlockSize(). getCBlkHeight(ModuleSpec.SPEC_TILE_DEF,tileIdx,-1); hbuf.write(MathUtil.log2(tmp)-2); } // Style of the code-block coding passes tmp = 0; if(mh){ // Main header // Selective arithmetic coding bypass ? if( ((String)wp.getBypass().getDefault()).equals("true")) { tmp |= OPT_BYPASS; } // MQ reset after each coding pass ? if( ((String)wp.getResetMQ().getDefault()).equals("true")) { tmp |= OPT_RESET_MQ; } // MQ termination after each arithmetically coded coding pass ? if( ((String)wp.getTerminateOnByte().getDefault()).equals("true") ) { tmp |= OPT_TERM_PASS; } // Vertically stripe-causal context mode ? if( ((String)wp.getCausalCXInfo().getDefault()).equals("true") ) { tmp |= OPT_VERT_STR_CAUSAL; } // Predictable termination ? if( ((String)wp.getMethodForMQTermination().getDefault()).equals("predict")){ tmp |= OPT_PRED_TERM; } // Error resilience segmentation symbol insertion ? if( ((String)wp.getCodeSegSymbol().getDefault()).equals("true")) { tmp |= OPT_SEG_SYMBOLS; } } else{ // Tile header // Selective arithmetic coding bypass ? if( ((String)wp.getBypass().getTileDef(tileIdx)).equals("true")) { tmp |= OPT_BYPASS; } // MQ reset after each coding pass ? if( ((String)wp.getResetMQ().getTileDef(tileIdx)).equals("true")) { tmp |= OPT_RESET_MQ; } // MQ termination after each arithmetically coded coding pass ? if( ((String)wp.getTerminateOnByte().getTileDef(tileIdx)).equals("true") ) { tmp |= OPT_TERM_PASS; } // Vertically stripe-causal context mode ? if( ((String)wp.getCausalCXInfo().getTileDef(tileIdx)).equals("true") ) { tmp |= OPT_VERT_STR_CAUSAL; } // Predictable termination ? if( ((String)wp.getMethodForMQTermination().getTileDef(tileIdx)).equals("predict")){ tmp |= OPT_PRED_TERM; } // Error resilience segmentation symbol insertion ? if( ((String)wp.getCodeSegSymbol().getTileDef(tileIdx)).equals("true")) { tmp |= OPT_SEG_SYMBOLS; } } hbuf.write(tmp); // Wavelet transform // Wavelet Filter if(mh){ filt=((AnWTFilter[][])wp.getFilters().getDefault()); hbuf.write(filt[0][0].getFilterType()); }else{ filt=((AnWTFilter[][])wp.getFilters().getTileDef(tileIdx)); hbuf.write(filt[0][0].getFilterType()); } // Precinct partition if ( precinctPartitionUsed ) { // Write the precinct size for each resolution level + 1 // (resolution 0) if precinct partition is used. Vector v[] = null; if ( mh ) { v = (Vector[])wp.getPrecinctPartition().getDefault(); } else { v = (Vector[])wp.getPrecinctPartition().getTileDef(tileIdx); } for (int r=mrl ; r>=0 ; r--) { if ( r>=v[1].size() ) { tmp = ((Integer)v[1].elementAt(v[1].size()-1)). intValue(); } else { tmp = ((Integer)v[1].elementAt(r)).intValue(); } int yExp = (MathUtil.log2(tmp)<< 4) & 0x00F0; if ( r>=v[0].size() ) { tmp = ((Integer)v[0].elementAt(v[0].size()-1)). intValue(); } else { tmp = ((Integer)v[0].elementAt(r)).intValue(); } int xExp = MathUtil.log2(tmp) & 0x000F; hbuf.write(yExp|xExp); } } } /** * Writes COC marker segment . It is a functional marker containing the * coding style for one component (coding style, decomposition, layering). * *

    Its values overrides any value previously set in COD in the main * header or in the tile header. * * @param mh Flag indicating whether the main header is to be written * * @param tileIdx Tile index * * @param compIdx index of the component which need use of the COC marker * segment. * * @see #writeCOD * */ protected void writeCOC(boolean mh, int tileIdx, int compIdx) throws IOException { AnWTFilter[][] filt; boolean precinctPartitionUsed; int tmp; int mrl=0,a=0; int ppx=0, ppy=0; Progression[] prog; if (mh) { mrl = ((Integer)wp.getDecompositionLevel().getCompDef(compIdx)).intValue(); // Get precinct size for specified component ppx = wp.getPrecinctPartition().getPPX(-1, compIdx, mrl); ppy = wp.getPrecinctPartition().getPPY(-1, compIdx, mrl); prog = (Progression[])(wp.getProgressionType().getCompDef(compIdx)); } else { mrl = ((Integer)wp.getDecompositionLevel().getTileCompVal(tileIdx,compIdx)). intValue(); // Get precinct size for specified component/tile ppx = wp.getPrecinctPartition().getPPX(tileIdx, compIdx, mrl); ppy = wp.getPrecinctPartition().getPPY(tileIdx, compIdx, mrl); prog = (Progression[])(wp.getProgressionType().getTileCompVal(tileIdx,compIdx)); } if ( ppx != Markers.PRECINCT_PARTITION_DEF_SIZE || ppy != Markers.PRECINCT_PARTITION_DEF_SIZE ) { precinctPartitionUsed = true; } else { precinctPartitionUsed = false; } if ( precinctPartitionUsed ) { // If precinct partition is used we add one byte per resolution // level i.e. mrl+1 (+1 for resolution 0). a = mrl+1; } // COC marker hbuf.writeShort(COC); // Lcoc (marker segment length (in bytes)) // Basic: Lcoc(2 bytes)+Scoc(1)+ Ccoc(1 or 2)+SPcod(5+a) int markSegLen = 8 + ((nComp < 257) ? 1 : 2)+a; // Rounded to the nearest even value greater or equals hbuf.writeShort(markSegLen); // Ccoc if(nComp < 257) { hbuf.write(compIdx); } else { hbuf.writeShort(compIdx); } // Scod (coding style parameter) tmp=0; if ( precinctPartitionUsed ) { tmp=SCOX_PRECINCT_PARTITION; } hbuf.write(tmp); // SPcoc // Number of decomposition levels hbuf.write(mrl); // Code-block width and height if ( mh ) { // main header, get component default values tmp = wp.getCodeBlockSize(). getCBlkWidth(ModuleSpec.SPEC_COMP_DEF, -1, compIdx); hbuf.write(MathUtil.log2(tmp)-2); tmp = wp.getCodeBlockSize(). getCBlkHeight(ModuleSpec.SPEC_COMP_DEF, -1, compIdx); hbuf.write(MathUtil.log2(tmp)-2); } else { // tile header, get tile component values tmp = wp.getCodeBlockSize(). getCBlkWidth(ModuleSpec.SPEC_TILE_COMP, tileIdx, compIdx); hbuf.write(MathUtil.log2(tmp)-2); tmp = wp.getCodeBlockSize(). getCBlkHeight(ModuleSpec.SPEC_TILE_COMP, tileIdx, compIdx); hbuf.write(MathUtil.log2(tmp)-2); } // Entropy coding mode options tmp = 0; if(mh){ // Main header // Lazy coding mode ? if( ((String)wp.getBypass().getCompDef(compIdx)).equals("true")) { tmp |= OPT_BYPASS; } // MQ reset after each coding pass ? if( ((String)wp.getResetMQ().getCompDef(compIdx)). equalsIgnoreCase("true")) { tmp |= OPT_RESET_MQ; } // MQ termination after each arithmetically coded coding pass ? if( ((String)wp.getTerminateOnByte().getCompDef(compIdx)).equals("true") ) { tmp |= OPT_TERM_PASS; } // Vertically stripe-causal context mode ? if( ((String)wp.getCausalCXInfo().getCompDef(compIdx)).equals("true") ) { tmp |= OPT_VERT_STR_CAUSAL; } // Predictable termination ? if( ((String)wp.getMethodForMQTermination().getCompDef(compIdx)).equals("predict")){ tmp |= OPT_PRED_TERM; } // Error resilience segmentation symbol insertion ? if( ((String)wp.getCodeSegSymbol().getCompDef(compIdx)).equals("true")) { tmp |= OPT_SEG_SYMBOLS; } } else{ // Tile Header if( ((String)wp.getBypass().getTileCompVal(tileIdx,compIdx)). equals("true")) { tmp |= OPT_BYPASS; } // MQ reset after each coding pass ? if( ((String)wp.getResetMQ().getTileCompVal(tileIdx,compIdx)). equals("true")) { tmp |= OPT_RESET_MQ; } // MQ termination after each arithmetically coded coding pass ? if( ((String)wp.getTerminateOnByte().getTileCompVal(tileIdx,compIdx)). equals("true") ) { tmp |= OPT_TERM_PASS; } // Vertically stripe-causal context mode ? if( ((String)wp.getCausalCXInfo().getTileCompVal(tileIdx,compIdx)). equals("true") ) { tmp |= OPT_VERT_STR_CAUSAL; } // Predictable termination ? if( ((String)wp.getMethodForMQTermination().getTileCompVal(tileIdx,compIdx)). equals("predict")){ tmp |= OPT_PRED_TERM; } // Error resilience segmentation symbol insertion ? if( ((String)wp.getCodeSegSymbol().getTileCompVal(tileIdx,compIdx)). equals("true")) { tmp |= OPT_SEG_SYMBOLS; } } hbuf.write(tmp); // Wavelet transform // Wavelet Filter if(mh){ filt=((AnWTFilter[][])wp.getFilters().getCompDef(compIdx)); hbuf.write(filt[0][0].getFilterType()); }else{ filt=((AnWTFilter[][])wp.getFilters().getTileCompVal(tileIdx,compIdx)); hbuf.write(filt[0][0].getFilterType()); } // Precinct partition if ( precinctPartitionUsed ) { // Write the precinct size for each resolution level + 1 // (resolution 0) if precinct partition is used. Vector v[] = null; if ( mh ) { v = (Vector[])wp.getPrecinctPartition().getCompDef(compIdx); } else { v = (Vector[])wp.getPrecinctPartition().getTileCompVal(tileIdx, compIdx); } for (int r=mrl ; r>=0 ; r--) { if ( r>=v[1].size() ) { tmp = ((Integer)v[1].elementAt(v[1].size()-1)). intValue(); } else { tmp = ((Integer)v[1].elementAt(r)).intValue(); } int yExp = (MathUtil.log2(tmp)<< 4) & 0x00F0; if ( r>=v[0].size() ) { tmp = ((Integer)v[0].elementAt(v[0].size()-1)). intValue(); } else { tmp = ((Integer)v[0].elementAt(r)).intValue(); } int xExp = MathUtil.log2(tmp) & 0x000F; hbuf.write(yExp|xExp); } } } /** * Writes QCD marker segment in main header. QCD is a functional marker * segment countaining the quantization default used for compressing all * the components in an image. The values can be overriden for an * individual component by a QCC marker in either the main or the tile * header. * */ protected void writeMainQCD() throws IOException{ float step; String qType = (String)wp.getQuantizationType().getDefault(); float baseStep = ((Float)wp.getQuantizationStep().getDefault()).floatValue(); int gb = ((Integer)wp.getGuardBits().getDefault()).intValue(); boolean isDerived = qType.equals("derived"); boolean isReversible = qType.equals("reversible"); int mrl = ((Integer)wp.getDecompositionLevel().getDefault()).intValue(); int nt = dwt.getNumTiles(); int nc = dwt.getNumComps(); int tmpI; int[] tcIdx = new int[2]; String tmpStr; boolean notFound = true; for(int t=0; t

  • SOC
  • SIZ
  • COD
  • COC (if * needed)
  • QCD
  • QCC (if needed)
  • POC (if * needed)
  • * */ public void encodeMainHeader() throws IOException { int i; // +---------------------------------+ // | SOC marker segment | // +---------------------------------+ writeSOC(); // +---------------------------------+ // | Image and tile SIZe (SIZ) | // +---------------------------------+ writeSIZ(); // +-------------------------------+ // | COding style Default (COD) | // +-------------------------------+ boolean isEresUsed = ((String)wp.getTerminateOnByte().getDefault()). equals("predict"); writeCOD(true,0); // +---------------------------------+ // | COding style Component (COC) | // +---------------------------------+ for (i= 0; i need COC writeCOC(true,0,i); } // +-------------------------------+ // | Quantization Default (QCD) | // +-------------------------------+ writeMainQCD(); // +-------------------------------+ // | Quantization Component (QCC) | // +-------------------------------+ // Write needed QCC markers for(i=0; i1) writePOC(true, 0); // +--------------------------+ // | Comment (COM) | // +--------------------------+ writeCOM(); } /** * Write a COM marker segment adding some comments to the codestream. * *

    This marker is currently written in main header and indicates the * JJ2000 encoder's version that has created the codestream. * */ private void writeCOM() throws IOException { // JJ2000 COM marker segment if(enJJ2KMarkSeg) { String str = "Created by: JJ2000 version "+JJ2KInfo.version; int markSegLen; // the marker segment length // COM marker hbuf.writeShort(COM); // Calculate length: Lcom(2) + Rcom (2) + string's length; markSegLen = 2 + 2 + str.length(); hbuf.writeShort(markSegLen); // Rcom hbuf.writeShort(1); // General use (IS 8859-15:1999(Latin) values) byte[] chars = str.getBytes(); for(int i=0; iMay be used in tile or main header. If used in main header, it * refers to a ROI of the whole image, regardless of tiling. When used in * tile header, only the particular tile is affected. * * @param tIdx The tile index * * @exception IOException If an I/O error occurs while reading from the * encoder header stream * */ private void writeRGN(int tIdx) throws IOException { int i; int markSegLen; // the marker length // Write one RGN marker per component for(i=0;i

  • SOT
  • COD (if * needed)
  • COC (if needed)
  • QCD (if needed)
  • QCC * (if needed)
  • RGN (if needed)
  • POC (if needed)
  • *
  • SOD
  • * * @param length The length of the current tile-part. * * @param tileIdx Index of the tile to write * */ public void encodeTilePartHeader(int tileLength,int tileIdx) throws IOException { int tmp; Point numTiles = ralloc.getNumTiles(null); ralloc.setTile(tileIdx%numTiles.x,tileIdx/numTiles.x); // +--------------------------+ // | SOT maker segment | // +--------------------------+ // SOT marker hbuf.writeByte(SOT>>8); hbuf.writeByte(SOT); // Lsot (10 bytes) hbuf.writeByte(0); hbuf.writeByte(10); // Isot if(tileIdx>65534){ throw new IllegalArgumentException("Trying to write a tile-part "+ "header whose tile index is too"+ " high"); } hbuf.writeByte(tileIdx>>8); hbuf.writeByte(tileIdx); // Psot tmp = tileLength; hbuf.writeByte(tmp>>24); hbuf.writeByte(tmp>>16); hbuf.writeByte(tmp>>8); hbuf.writeByte(tmp); // TPsot hbuf.writeByte(0); // Only one tile-part currently supported ! // TNsot hbuf.writeByte(1); // Only one tile-part currently supported ! // +--------------------------+ // | COD maker segment | // +--------------------------+ boolean isEresUsed = ((String)wp.getMethodForMQTermination().getDefault()). equals("predict"); boolean isEresUsedInTile = ((String)wp.getMethodForMQTermination().getTileDef(tileIdx)). equals("predict"); boolean tileCODwritten = false; if(wp.getFilters().isTileSpecified(tileIdx) || wp.getComponentTransformation().isTileSpecified(tileIdx) || wp.getDecompositionLevel().isTileSpecified(tileIdx) || wp.getBypass().isTileSpecified(tileIdx) || wp.getResetMQ().isTileSpecified(tileIdx) || wp.getTerminateOnByte().isTileSpecified(tileIdx) || wp.getCausalCXInfo().isTileSpecified(tileIdx) || wp.getPrecinctPartition().isTileSpecified(tileIdx) || wp.getSOP().isTileSpecified(tileIdx) || wp.getCodeSegSymbol().isTileSpecified(tileIdx) || wp.getProgressionType().isTileSpecified(tileIdx) || wp.getEPH().isTileSpecified(tileIdx) || wp.getCodeBlockSize().isTileSpecified(tileIdx) || ( isEresUsed != isEresUsedInTile ) ) { writeCOD(false,tileIdx); tileCODwritten = true; } // +--------------------------+ // | COC maker segment | // +--------------------------+ for(int c=0; c1) writePOC(false,tileIdx); } // +--------------------------+ // | SOD maker | // +--------------------------+ hbuf.writeByte(SOD>>8); hbuf.writeByte(SOD); } } jai-imageio-core-1.2/src/share/classes/jj2000/j2k/codestream/writer/BitOutputBuffer.java0000664000175100017510000002256410203036165030011 0ustar tilletille/* * $RCSfile: BitOutputBuffer.java,v $ * $Revision: 1.1 $ * $Date: 2005-02-11 05:02:02 $ * $State: Exp $ * * Class: BitOutputBuffer * * Description: * * * * COPYRIGHT: * * This software module was originally developed by Raphal Grosbois and * Diego Santa Cruz (Swiss Federal Institute of Technology-EPFL); Joel * Askelf (Ericsson Radio Systems AB); and Bertrand Berthelot, David * Bouchard, Flix Henry, Gerard Mozelle and Patrice Onno (Canon Research * Centre France S.A) in the course of development of the JPEG2000 * standard as specified by ISO/IEC 15444 (JPEG 2000 Standard). This * software module is an implementation of a part of the JPEG 2000 * Standard. Swiss Federal Institute of Technology-EPFL, Ericsson Radio * Systems AB and Canon Research Centre France S.A (collectively JJ2000 * Partners) agree not to assert against ISO/IEC and users of the JPEG * 2000 Standard (Users) any of their rights under the copyright, not * including other intellectual property rights, for this software module * with respect to the usage by ISO/IEC and Users of this software module * or modifications thereof for use in hardware or software products * claiming conformance to the JPEG 2000 Standard. Those intending to use * this software module in hardware or software products are advised that * their use may infringe existing patents. The original developers of * this software module, JJ2000 Partners and ISO/IEC assume no liability * for use of this software module or modifications thereof. No license * or right to this software module is granted for non JPEG 2000 Standard * conforming products. JJ2000 Partners have full right to use this * software module for his/her own purpose, assign or donate this * software module to any third party and to inhibit third parties from * using this software module for non JPEG 2000 Standard conforming * products. This copyright notice must be included in all copies or * derivative works of this software module. * * Copyright (c) 1999/2000 JJ2000 Partners. * */ package jj2000.j2k.codestream.writer; import jj2000.j2k.util.*; /** * This class implements a buffer for writing bits, with the required bit * stuffing policy for the packet headers. The bits are stored in a byte array * in the order in which they are written. The byte array is automatically * reallocated and enlarged whenever necessary. A BitOutputBuffer object may * be reused by calling its 'reset()' method. * *

    NOTE: The methods implemented in this class are intended to be used only * in writing packet heads, since a special bit stuffing procedure is used, as * required for the packet heads. * */ public class BitOutputBuffer { /** The buffer where we store the data */ byte buf[]; /** The position of the current byte to write */ int curbyte; /** The number of available bits in the current byte */ int avbits = 8; /** The increment size for the buffer, 16 bytes. This is the * number of bytes that are added to the buffer each time it is * needed to enlarge it.*/ // This must be always 6 or larger. public final static int SZ_INCR = 16; /** The initial size for the buffer, 32 bytes. */ public final static int SZ_INIT = 32; /** * Creates a new BitOutputBuffer width a buffer of length * 'SZ_INIT'. * */ public BitOutputBuffer() { buf = new byte[SZ_INIT]; } /** * Resets the buffer. This rewinds the current position to the start of * the buffer and sets all tha data to 0. Note that no new buffer is * allocated, so this will affect any data that was returned by the * 'getBuffer()' method. * */ public void reset() { int i; // Reinit pointers curbyte = 0; avbits = 8; ArrayUtil.byteArraySet(buf,(byte)0); } /** * Writes a bit to the buffer at the current position. The value 'bit' * must be either 0 or 1, otherwise it corrupts the bits that have been * already written. The buffer is enlarged, by 'SZ_INCR' bytes, if * necessary. * *

    This method is declared final to increase performance. * * @param bit The bit to write, 0 or 1. * */ public final void writeBit(int bit) { buf[curbyte] |= bit << --avbits; if (avbits > 0) { // There is still place in current byte for next bit return; } else { // End of current byte => goto next if (buf[curbyte] != (byte) 0xFF) { // We don't need bit stuffing avbits = 8; } else { // We need to stuff a bit (next MSBit is 0) avbits = 7; } curbyte++; if (curbyte == buf.length) { // We are at end of 'buf' => extend it byte oldbuf[] = buf; buf = new byte[oldbuf.length+SZ_INCR]; System.arraycopy(oldbuf,0,buf,0,oldbuf.length); } } } /** * Writes the n least significant bits of 'bits' to the buffer at the * current position. The least significant bit is written last. The 32-n * most significant bits of 'bits' must be 0, otherwise corruption of the * buffer will result. The buffer is enlarged, by 'SZ_INCR' bytes, if * necessary. * *

    This method is declared final to increase performance. * * @param bits The bits to write. * * @param n The number of LSBs in 'bits' to write. * */ public final void writeBits(int bits, int n) { // Check that we have enough place in 'buf' for n bits, and that we do // not fill last byte, taking into account possibly stuffed bits (max // 2) if (((buf.length-curbyte)<<3)-8+avbits <= n+2) { // Not enough place, extend it byte oldbuf[] = buf; buf = new byte[oldbuf.length+SZ_INCR]; System.arraycopy(oldbuf,0,buf,0,oldbuf.length); // SZ_INCR is always 6 or more, so it is enough to hold all the // new bits plus the ones to come after } // Now write the bits if (n >= avbits) { // Complete the current byte n -= avbits; buf[curbyte] |= bits >> n; if (buf[curbyte] != (byte) 0xFF) { // We don't need bit stuffing avbits = 8; } else { // We need to stuff a bit (next MSBit is 0) avbits = 7; } curbyte++; // Write whole bytes while (n >= avbits) { n -= avbits; buf[curbyte] |= (bits >> n) & (~(1 << avbits)); if (buf[curbyte] != (byte) 0xFF) { // We don't need bit // stuffing avbits = 8; } else { // We need to stuff a bit (next MSBit is 0) avbits = 7; } curbyte++; } } // Finish last byte (we know that now n < avbits) if (n > 0) { avbits -= n; buf[curbyte] |= (bits & ((1<This method is declared final to increase performance. * * @return The currebt length of the buffer in bytes. * */ public final int getLength() { if (avbits == 8) { // A integral number of bytes return curbyte; } else { // Some bits in last byte return curbyte+1; } } /** * Returns the byte buffer. This is the internal byte buffer so it should * not be modified. Only the first N elements have valid data, where N is * the value returned by 'getLength()' * *

    This method is declared final to increase performance. * * @return The internal byte buffer. * */ public final byte[] getBuffer() { return buf; } /** * Returns the byte buffer data in a new array. This is a copy of the * internal byte buffer. If 'data' is non-null it is used to return the * data. This array should be large enough to contain all the data, * otherwise a IndexOutOfBoundsException is thrown by the Java system. The * number of elements returned is what 'getLength()' returns. * * @param data If non-null this array is used to return the data, which * mus be large enough. Otherwise a new one is created and returned. * * @return The byte buffer data. * */ public byte[] toByteArray(byte data[]) { if (data == null) { data = new byte[(avbits==8)?curbyte:curbyte+1]; } System.arraycopy(buf,0,data,0,(avbits==8)?curbyte:curbyte+1); return data; } /** * Prints information about this object for debugging purposes * * @return Information about the object. * */ public String toString() { return "bits written = "+(curbyte*8+(8-avbits))+ ", curbyte = "+curbyte+", avbits = "+avbits; } } jai-imageio-core-1.2/src/share/classes/jj2000/j2k/codestream/writer/FileCodestreamWriter.java0000664000175100017510000003542510203036165031003 0ustar tilletille/* * $RCSfile: FileCodestreamWriter.java,v $ * $Revision: 1.1 $ * $Date: 2005-02-11 05:02:02 $ * $State: Exp $ * * Class: FileCodestreamWriter * * Description: Implementation of the bit stream writer for streams. * * * * COPYRIGHT: * * This software module was originally developed by Raphal Grosbois and * Diego Santa Cruz (Swiss Federal Institute of Technology-EPFL); Joel * Askelf (Ericsson Radio Systems AB); and Bertrand Berthelot, David * Bouchard, Flix Henry, Gerard Mozelle and Patrice Onno (Canon Research * Centre France S.A) in the course of development of the JPEG2000 * standard as specified by ISO/IEC 15444 (JPEG 2000 Standard). This * software module is an implementation of a part of the JPEG 2000 * Standard. Swiss Federal Institute of Technology-EPFL, Ericsson Radio * Systems AB and Canon Research Centre France S.A (collectively JJ2000 * Partners) agree not to assert against ISO/IEC and users of the JPEG * 2000 Standard (Users) any of their rights under the copyright, not * including other intellectual property rights, for this software module * with respect to the usage by ISO/IEC and Users of this software module * or modifications thereof for use in hardware or software products * claiming conformance to the JPEG 2000 Standard. Those intending to use * this software module in hardware or software products are advised that * their use may infringe existing patents. The original developers of * this software module, JJ2000 Partners and ISO/IEC assume no liability * for use of this software module or modifications thereof. No license * or right to this software module is granted for non JPEG 2000 Standard * conforming products. JJ2000 Partners have full right to use this * software module for his/her own purpose, assign or donate this * software module to any third party and to inhibit third parties from * using this software module for non JPEG 2000 Standard conforming * products. This copyright notice must be included in all copies or * derivative works of this software module. * * Copyright (c) 1999/2000 JJ2000 Partners. * */ package jj2000.j2k.codestream.writer; import jj2000.j2k.codestream.*; import java.io.*; /** * This class implements a CodestreamWriter for Java streams. The streams can * be files or network connections, or any other resource that presents itself * as a OutputStream. See the CodestreamWriter abstract class for more details * on the implementation of the CodestreamWriter abstract class. * *

    Before any packet data is written to the bit stream (even in simulation * mode) the complete header should be written to the HeaderEncoder object * supplied to the constructor, following the procedure explained in the * HeaderEncoder class. Otherwise incorrect estimates are given by * getMaxAvailableBytes() for rate allocation. * * @see CodestreamWriter * * @see HeaderEncoder * */ public class FileCodestreamWriter extends CodestreamWriter implements Markers { /** The upper limit for the value of the Nsop field of the SOP marker */ private final static int SOP_MARKER_LIMIT = 65535; /** Index of the current tile */ private int tileIdx = 0; /** The file to write */ private OutputStream out; /** The number of bytes already written to the bit stream, excluding the * header length, magic number and header length info. */ int ndata=0; /** The default buffer length, 1024 bytes */ public static int DEF_BUF_LEN = 1024; /** Array used to store the SOP markers values */ byte sopMarker[]; /** Array used to store the EPH markers values */ byte ephMarker[]; /** The packet index (when start of packet markers i.e. SOP markers) are * used. */ int packetIdx=0; /** Offset of end of last packet containing ROI information */ private int offLastROIPkt = 0; /** Length of last packets containing no ROI information */ private int lenLastNoROI = 0; /** * Opens the file 'file' for writing the bit stream, using the 'he' header * encoder. The magic number is written to the bit stream. Normally, the * header encoder must be empty (i.e. no data has been written to it * yet). A BufferedOutputStream is used on top of the file to increase * throughput, the length of the buffer is DEF_BUF_LEN. * * @param file The file where to write the bit stream * * @param mb The maximum number of bytes that can be written to the bit * stream. * * @exception IOException If an error occurs while trying to open the file * for writing or while writing the magic number. * */ public FileCodestreamWriter(File file, int mb) throws IOException { super(mb); out = new BufferedOutputStream(new FileOutputStream(file),DEF_BUF_LEN); initSOP_EPHArrays(); } /** * Opens the file named 'fname' for writing the bit stream, using the 'he' * header encoder. The magic number is written to the bit * stream. Normally, the header encoder must be empty (i.e. no data has * been written to it yet). A BufferedOutputStream is used on top of the * file to increase throughput, the length of the buffer is DEF_BUF_LEN. * * @param fname The name of file where to write the bit stream * * @param mb The maximum number of bytes that can be written to the bit * stream. * * @param encSpec The encoder's specifications * * @exception IOException If an error occurs while trying to open the file * for writing or while writing the magic number. * */ public FileCodestreamWriter(String fname, int mb) throws IOException { super(mb); out = new BufferedOutputStream(new FileOutputStream(fname), DEF_BUF_LEN); initSOP_EPHArrays(); } /** * Uses the output stream 'os' for writing the bit stream, using the 'he' * header encoder. The magic number is written to the bit * stream. Normally, the header encoder must be empty (i.e. no data has * been written to it yet). No BufferedOutputStream is used on top of the * output stream 'os'. * * @param os The output stream where to write the bit stream. * * @param mb The maximum number of bytes that can be written to the bit * stream. * * @exception IOException If an error occurs while writing the magic * number to the 'os' output stream. * */ public FileCodestreamWriter(OutputStream os, int mb) throws IOException { super(mb); out = os; initSOP_EPHArrays(); } /** * Returns the number of bytes remaining available in the bit stream. This * is the maximum allowed number of bytes minus the number of bytes that * have already been written to the bit stream. If more bytes have been * written to the bit stream than the maximum number of allowed bytes, * then a negative value is returned. * * @return The number of bytes remaining available in the bit stream. * */ public final int getMaxAvailableBytes() { return maxBytes-ndata; } /** * Returns the current length of the entire bit stream. * * @return the current length of the bit stream * */ public int getLength() { if (getMaxAvailableBytes() >= 0) { return ndata; } else { return maxBytes; } } /** * Writes a packet head to the bit stream and returns the number of bytes * used by this header. It returns the total number of bytes that the * packet head takes in the bit stream. If in simulation mode then no data * is written to the bit stream but the number of bytes is * calculated. This can be used for iterative rate allocation. * *

    If the length of the data that is to be written to the bit stream is * more than the space left (as returned by getMaxAvailableBytes()) only * the data that does not exceed the allowed length is written, the rest * is discarded. However the value returned by the method is the total * length of the packet, as if all of it was written to the bit stream. * *

    If the bit stream header has not been commited yet and 'sim' is * false, then the bit stream header is automatically commited (see * commitBitstreamHeader() method) before writting the packet. * * @param head The packet head data. * * @param hlen The number of bytes in the packet head. * * @param sim Simulation mode flag. If true nothing is written to the bit * stream, but the number of bytes that would be written is returned. * * @param sop Start of packet header marker flag. This flag indicates * whether or not SOP markers should be written. If true, SOP markers * should be written, if false, they should not. * * @param eph End of Packet Header marker flag. This flag indicates * whether or not EPH markers should be written. If true, EPH markers * should be written, if false, they should not. * * @return The number of bytes spent by the packet head. * * @exception IOException If an I/O error occurs while writing to the * output stream. * * @see #commitBitstreamHeader * */ public int writePacketHead(byte head[],int hlen,boolean sim, boolean sop, boolean eph) throws IOException{ int len = hlen + (sop?Markers.SOP_LENGTH:0) + (eph?Markers.EPH_LENGTH:0); // If not in simulation mode write the data if(!sim){ // Write the head bytes if(getMaxAvailableBytes() 0){ // Write Start Of Packet header markers if necessary if(sop){ // The first 4 bytes of the array have been filled in the // classe's constructor. sopMarker[4] = (byte)(packetIdx>>8); sopMarker[5] = (byte)(packetIdx); out.write(sopMarker, 0, Markers.SOP_LENGTH); packetIdx++; if(packetIdx>SOP_MARKER_LIMIT){ // Reset SOP value as we have reached its upper limit packetIdx = 0; } } out.write(head,0,hlen); // Update data length ndata += len; // Write End of Packet Header markers if necessary if(eph){ out.write(ephMarker,0,Markers.EPH_LENGTH); } // Deal with ROI Information lenLastNoROI += len; } } return len; } /** * Writes a packet body to the bit stream and returns the number of bytes * used by this body .If in simulation mode then no data is written to the * bit stream but the number of bytes is calculated. This can be used for * iterative rate allocation. * *

    If the length of the data that is to be written to the bit stream is * more than the space left (as returned by getMaxAvailableBytes()) only * the data that does not exceed the allowed length is written, the rest * is discarded. However the value returned by the method is the total * length of the packet body , as if all of it was written to the bit * stream. * * @param body The packet body data. * * @param blen The number of bytes in the packet body. * * @param sim Simulation mode flag. If true nothing is written to the bit * stream, but the number of bytes that would be written is returned. * * @param roiInPkt Whether or not this packet contains ROI information * * @param roiLen Number of byte to read in packet body to get all the ROI * information * * @return The number of bytes spent by the packet body. * * @exception IOException If an I/O error occurs while writing to the * output stream. * * @see #commitBitstreamHeader * */ public int writePacketBody(byte body[],int blen,boolean sim, boolean roiInPkt, int roiLen) throws IOException{ int len = blen; // If not in simulation mode write the data if (!sim) { // Write the body bytes len = blen; if(getMaxAvailableBytes() < len){ len = getMaxAvailableBytes(); } if(blen > 0){ out.write(body,0,len); } // Update data length ndata += len; // Deal with ROI information if(roiInPkt) { offLastROIPkt += lenLastNoROI + roiLen; lenLastNoROI = len-roiLen; } else { lenLastNoROI += len; } } return len; } /** * Writes the EOC marker and closes the underlying stream. * * @exception IOException If an error occurs while closing the underlying * stream. * */ public void close() throws IOException { // Write the EOC marker and close the codestream. out.write(EOC>>8); out.write(EOC); ndata += 2; // Add two to length of codestream for EOC marker out.close(); } /** * Gives the offset of the end of last packet containing ROI information * * @return End of last ROI packet * */ public int getOffLastROIPkt(){ return offLastROIPkt; } /** * Writes the header data in the codestream and actualize ndata with the * header length. The header is either a MainHeaderEncoder or a * TileHeaderEncoder. * * @param he The current header encoder. * * @exception IOException If an I/O error occurs while writing the data. * */ public void commitBitstreamHeader(HeaderEncoder he) throws IOException { // Actualize ndata ndata += he.getLength(); he.writeTo(out); // Write the header // Reset packet index used for SOP markers packetIdx = 0; // Deal with ROI information lenLastNoROI += he.getLength(); } /** * Performs the initialisation of the arrays that are used to store the * values used to write SOP and EPH markers * */ private void initSOP_EPHArrays() { // Allocate and set first values of SOP marker as they will not be // modified sopMarker = new byte[Markers.SOP_LENGTH]; sopMarker[0] = (byte)(Markers.SOP>>8); sopMarker[1] = (byte)Markers.SOP; sopMarker[2] = (byte)0x00; sopMarker[3] = (byte)0x04; // Allocate and set values of EPH marker as they will not be // modified ephMarker = new byte[Markers.EPH_LENGTH]; ephMarker[0] = (byte)(Markers.EPH>>8); ephMarker[1] = (byte)Markers.EPH; } } jai-imageio-core-1.2/src/share/classes/jj2000/j2k/codestream/writer/CodestreamWriter.java0000664000175100017510000002143210203036165030174 0ustar tilletille/* * $RCSfile: CodestreamWriter.java,v $ * $Revision: 1.1 $ * $Date: 2005-02-11 05:02:02 $ * $State: Exp $ * * Class: CodestreamWriter * * Description: Interface for writing bit streams * * * * COPYRIGHT: * * This software module was originally developed by Raphal Grosbois and * Diego Santa Cruz (Swiss Federal Institute of Technology-EPFL); Joel * Askelf (Ericsson Radio Systems AB); and Bertrand Berthelot, David * Bouchard, Flix Henry, Gerard Mozelle and Patrice Onno (Canon Research * Centre France S.A) in the course of development of the JPEG2000 * standard as specified by ISO/IEC 15444 (JPEG 2000 Standard). This * software module is an implementation of a part of the JPEG 2000 * Standard. Swiss Federal Institute of Technology-EPFL, Ericsson Radio * Systems AB and Canon Research Centre France S.A (collectively JJ2000 * Partners) agree not to assert against ISO/IEC and users of the JPEG * 2000 Standard (Users) any of their rights under the copyright, not * including other intellectual property rights, for this software module * with respect to the usage by ISO/IEC and Users of this software module * or modifications thereof for use in hardware or software products * claiming conformance to the JPEG 2000 Standard. Those intending to use * this software module in hardware or software products are advised that * their use may infringe existing patents. The original developers of * this software module, JJ2000 Partners and ISO/IEC assume no liability * for use of this software module or modifications thereof. No license * or right to this software module is granted for non JPEG 2000 Standard * conforming products. JJ2000 Partners have full right to use this * software module for his/her own purpose, assign or donate this * software module to any third party and to inhibit third parties from * using this software module for non JPEG 2000 Standard conforming * products. This copyright notice must be included in all copies or * derivative works of this software module. * * Copyright (c) 1999/2000 JJ2000 Partners. * */ package jj2000.j2k.codestream.writer; import java.io.*; /** * This is the abstract class for writing to a bit stream. Data is * written in packets, each packet having a head and a body. The * bit stream always has a maximum number of bytes that can be written * to it. After that many number of bytes no more data is written to * the bit stream but the number of bytes is counted so that the value * returned by getMaxAvailableBytes() is negative. If the number of * bytes is unlimited a ridicoulosly large value, such as * Integer.MAX_VALUE, is equivalent. * *

    Data may be written to the bit stream in sumulation mode. When in * simulation mode no data is written to the bit stream but the * resulting number of bytes is calculated and returned (although it * is not accounted in the bit stream). This can be used in rate * control loops. * *

    Implementing classes should write the header of the bit stream * before writing any packets. The bit stream header should be written * with the aid of the HeaderEncoder class. * * @see HeaderEncoder * */ public abstract class CodestreamWriter { /** The number of bytes already written to the bit stream */ protected int ndata=0; /** The maximum number of bytes that can be written to the * bit stream */ protected int maxBytes; /** * Allocates this object and initializes the maximum numner of * bytes. * * @param mb The maximum number of bytes that can be written to * the bit stream. * */ protected CodestreamWriter(int mb) { maxBytes = mb; } /** * Returns the number of bytes remaining available in the bit stream. This * is the maximum allowed number of bytes minus the number of bytes that * have already been written to the bit stream. If more bytes have been * written to the bit stream than the maximum number of allowed bytes, * then a negative value is returned. * * @return The number of bytes remaining available in the bit stream. * */ public abstract int getMaxAvailableBytes(); /** * Returns the current length of the entire bit stream. * * @return the current length of the bit stream * */ public abstract int getLength(); /** * Writes a packet head to the bit stream and returns the number of bytes * used by this header. It returns the total number of bytes that the * packet head takes in the bit stream. If in simulation mode then no data * is written to the bit stream but the number of bytes is * calculated. This can be used for iterative rate allocation. * *

    If the length of the data that is to be written to the bit stream is * more than the space left (as returned by getMaxAvailableBytes()) only * the data that does not exceed the allowed length is written, the rest * is discarded. However the value returned by the method is the total * length of the packet, as if all of it was written to the bit stream. * *

    If the bit stream header has not been commited yet and 'sim' is * false, then the bit stream header is automatically commited (see * commitBitstreamHeader() method) before writting the packet. * * @param head The packet head data. * * @param hlen The number of bytes in the packet head. * * @param sim Simulation mode flag. If true nothing is written to the bit * stream, but the number of bytes that would be written is returned. * * @param sop Start of packet header marker flag. This flag indicates * whether or not SOP markers should be written. If true, SOP markers * should be written, if false, they should not. * * @param eph End of Packet Header marker flag. This flag indicates * whether or not EPH markers should be written. If true, EPH markers * should be written, if false, they should not. * * @return The number of bytes spent by the packet head. * * @exception IOException If an I/O error occurs while writing to the * output stream. * * @see #commitBitstreamHeader * */ public abstract int writePacketHead(byte head[],int hlen,boolean sim, boolean sop, boolean eph) throws IOException; /** * Writes a packet body to the bit stream and returns the number of bytes * used by this body .If in simulation mode then no data is written to the * bit stream but the number of bytes is calculated. This can be used for * iterative rate allocation. * *

    If the length of the data that is to be written to the bit stream is * more than the space left (as returned by getMaxAvailableBytes()) only * the data that does not exceed the allowed length is written, the rest * is discarded. However the value returned by the method is the total * length of the packet body , as if all of it was written to the bit * stream. * * @param body The packet body data. * * @param blen The number of bytes in the packet body. * * @param sim Simulation mode flag. If true nothing is written to the bit * stream, but the number of bytes that would be written is returned. * * @param roiInPkt Whether or not there is ROI information in this packet * * @param roiLen Number of byte to read in packet body to get all the ROI * information * * @return The number of bytes spent by the packet body. * * @exception IOException If an I/O error occurs while writing to * the output stream. * * @see #commitBitstreamHeader * */ public abstract int writePacketBody(byte body[],int blen,boolean sim, boolean roiInPkt, int roiLen) throws IOException; /** * Closes the underlying resource (file, stream, network connection, * etc.). After a CodestreamWriter is closed no more data can be written * to it. * * @exception IOException If an I/O error occurs while closing the * resource. * */ public abstract void close() throws IOException; /** * Writes the header data to the bit stream, if it has not been already * done. In some implementations this method can be called only once, and * an IllegalArgumentException is thrown if called more than once. * * @exception IOException If an I/O error occurs while writing the data. * * @exception IllegalArgumentException If this method has already been * called. * */ public abstract void commitBitstreamHeader(HeaderEncoder he) throws IOException; /** * Gives the offset of the end of last packet containing ROI information * * @return End of last ROI packet * */ public abstract int getOffLastROIPkt(); } jai-imageio-core-1.2/src/share/classes/jj2000/j2k/codestream/Markers.java0000664000175100017510000001732510203036165025007 0ustar tilletille/* * $RCSfile: Markers.java,v $ * $Revision: 1.1 $ * $Date: 2005-02-11 05:02:00 $ * $State: Exp $ * * Class: Markers * * Description: Defines the values of the markers in JPEG 2000 codestream * * COPYRIGHT: * * This software module was originally developed by Raphal Grosbois and * Diego Santa Cruz (Swiss Federal Institute of Technology-EPFL); Joel * Askelf (Ericsson Radio Systems AB); and Bertrand Berthelot, David * Bouchard, Flix Henry, Gerard Mozelle and Patrice Onno (Canon Research * Centre France S.A) in the course of development of the JPEG2000 * standard as specified by ISO/IEC 15444 (JPEG 2000 Standard). This * software module is an implementation of a part of the JPEG 2000 * Standard. Swiss Federal Institute of Technology-EPFL, Ericsson Radio * Systems AB and Canon Research Centre France S.A (collectively JJ2000 * Partners) agree not to assert against ISO/IEC and users of the JPEG * 2000 Standard (Users) any of their rights under the copyright, not * including other intellectual property rights, for this software module * with respect to the usage by ISO/IEC and Users of this software module * or modifications thereof for use in hardware or software products * claiming conformance to the JPEG 2000 Standard. Those intending to use * this software module in hardware or software products are advised that * their use may infringe existing patents. The original developers of * this software module, JJ2000 Partners and ISO/IEC assume no liability * for use of this software module or modifications thereof. No license * or right to this software module is granted for non JPEG 2000 Standard * conforming products. JJ2000 Partners have full right to use this * software module for his/her own purpose, assign or donate this * software module to any third party and to inhibit third parties from * using this software module for non JPEG 2000 Standard conforming * products. This copyright notice must be included in all copies or * derivative works of this software module. * * Copyright (c) 1999/2000 JJ2000 Partners. * */ package jj2000.j2k.codestream; /** * This interface defines the values of the different markers in the JPEG 2000 * codestream. They are 16 bit values, always appearing in big-endian (most * significant byte first) and byte-aligned in the codestream. This interface * also defines some other constants such as bit-masks and bit-shifts. * */ public interface Markers { // ----> Delimiting markers and marker segments <---- /** Start of codestream (SOC): 0xFF4F */ public final static short SOC = (short)0xff4f; /** Start of tile-part (SOT): 0xFF90 */ public final static short SOT = (short)0xff90; /** Start of data (SOD): 0xFF93 */ public final static short SOD = (short)0xff93; /** End of codestream (EOC): 0xFFD9 */ public final static short EOC = (short)0xffd9; // ----> Fixed information marker segments <---- // ** SIZ marker ** /** SIZ marker (Image and tile size): 0xFF51 */ public final static short SIZ = (short)0xff51; /** No special capabilities (baseline) in codestream, in Rsiz field of SIZ * marker: 0x00. All flag bits are turned off */ public final static int RSIZ_BASELINE = 0x00; /** Error resilience marker flag bit in Rsiz field in SIZ marker: 0x01 */ public final static int RSIZ_ER_FLAG = 0x01; /** ROI present marker flag bit in Rsiz field in SIZ marker: 0x02 */ public final static int RSIZ_ROI = 0x02; /** Component bitdepth bits in Ssiz field in SIZ marker: 7 */ public final static int SSIZ_DEPTH_BITS = 7; /** The maximum number of component bitdepth */ public static final int MAX_COMP_BITDEPTH = 38; // ----> Functional marker segments <---- // ** COD/COC marker ** /** Coding style default (COD): 0xFF52 */ public final static short COD = (short)0xff52; /** Coding style component (COC): 0xFF53 */ public final static short COC = (short)0xff53; /** Precinct used flag */ public final static int SCOX_PRECINCT_PARTITION = 1; /** Use start of packet marker */ public final static int SCOX_USE_SOP = 2; /** Use end of packet header marker */ public final static int SCOX_USE_EPH = 4; /** Horizontal code-block partition origin is at x=1 */ public final static int SCOX_HOR_CB_PART = 8; /** Vertical code-block partition origin is at y=1 */ public final static int SCOX_VER_CB_PART = 16; /** The default size exponent of the precincts */ public final static int PRECINCT_PARTITION_DEF_SIZE = 0xffff; // ** RGN marker segment ** /** Region-of-interest (RGN): 0xFF5E */ public final static short RGN = (short)0xff5e; /** Implicit (i.e. max-shift) ROI flag for Srgn field in RGN marker segment: 0x00 */ public final static int SRGN_IMPLICIT = 0x00; // ** QCD/QCC markers ** /** Quantization default (QCD): 0xFF5C */ public final static short QCD = (short)0xff5c; /** Quantization component (QCC): 0xFF5D */ public final static short QCC = (short)0xff5d; /** Guard bits shift in SQCX field: 5 */ public final static int SQCX_GB_SHIFT = 5; /** Guard bits mask in SQCX field: 7 */ public final static int SQCX_GB_MSK = 7; /** No quantization (i.e. embedded reversible) flag for Sqcd or Sqcc * (Sqcx) fields: 0x00. */ public final static int SQCX_NO_QUANTIZATION = 0x00; /** Scalar derived (i.e. LL values only) quantization flag for Sqcd or * Sqcc (Sqcx) fields: 0x01. */ public final static int SQCX_SCALAR_DERIVED = 0x01; /** Scalar expounded (i.e. all values) quantization flag for Sqcd or Sqcc * (Sqcx) fields: 0x02. */ public final static int SQCX_SCALAR_EXPOUNDED = 0x02; /** Exponent shift in SPQCX when no quantization: 3 */ public final static int SQCX_EXP_SHIFT = 3; /** Exponent bitmask in SPQCX when no quantization: 3 */ public final static int SQCX_EXP_MASK = (1<<5)-1; /** The "SOP marker segments used" flag within Sers: 1 */ public final static int ERS_SOP = 1; /** The "segmentation symbols used" flag within Sers: 2 */ public final static int ERS_SEG_SYMBOLS = 2; // ** Progression order change ** public final static short POC = (short)0xff5f; // ----> Pointer marker segments <---- /** Tile-part lengths (TLM): 0xFF55 */ public final static short TLM = (short)0xff55; /** Packet length, main header (PLM): 0xFF57 */ public final static short PLM = (short)0xff57; /** Packet length, tile-part header (PLT): 0xFF58 */ public final static short PLT = (short)0xff58; /** Packed packet headers, main header (PPM): 0xFF60 */ public final static short PPM = (short)0xff60; /** Packed packet headers, tile-part header (PPT): 0xFF61 */ public final static short PPT = (short)0xff61; /** Maximum length of PPT marker segment */ public final static int MAX_LPPT = 65535; /** Maximum length of PPM marker segment */ public final static int MAX_LPPM = 65535; // ----> In bit stream markers and marker segments <---- /** Start pf packet (SOP): 0xFF91 */ public final static short SOP = (short)0xff91; /** Length of SOP marker (in bytes) */ public final static short SOP_LENGTH = 6; /** End of packet header (EPH): 0xFF92 */ public final static short EPH = (short)0xff92; /** Length of EPH marker (in bytes) */ public final static short EPH_LENGTH = 2; // ----> Informational marker segments <---- /** Component registration (CRG): 0xFF63 */ public final static short CRG = (short)0xff63; /** Comment (COM): 0xFF64 */ public final static short COM = (short)0xff64; /** General use registration value (COM): 0x0001 */ public final static short RCOM_GEN_USE = (short)0x0001; } jai-imageio-core-1.2/src/share/classes/jj2000/j2k/codestream/reader/0000775000175100017510000000000011650556205024003 5ustar tilletillejai-imageio-core-1.2/src/share/classes/jj2000/j2k/codestream/reader/PktDecoder.java0000664000175100017510000015420610203036165026671 0ustar tilletille/* * $RCSfile: PktDecoder.java,v $ * $Revision: 1.1 $ * $Date: 2005-02-11 05:02:01 $ * $State: Exp $ * * Class: PktDecoder * * Description: Reads packets heads and keeps location of * code-blocks' codewords * * * * COPYRIGHT: * * This software module was originally developed by Raphal Grosbois and * Diego Santa Cruz (Swiss Federal Institute of Technology-EPFL); Joel * Askelf (Ericsson Radio Systems AB); and Bertrand Berthelot, David * Bouchard, Flix Henry, Gerard Mozelle and Patrice Onno (Canon Research * Centre France S.A) in the course of development of the JPEG2000 * standard as specified by ISO/IEC 15444 (JPEG 2000 Standard). This * software module is an implementation of a part of the JPEG 2000 * Standard. Swiss Federal Institute of Technology-EPFL, Ericsson Radio * Systems AB and Canon Research Centre France S.A (collectively JJ2000 * Partners) agree not to assert against ISO/IEC and users of the JPEG * 2000 Standard (Users) any of their rights under the copyright, not * including other intellectual property rights, for this software module * with respect to the usage by ISO/IEC and Users of this software module * or modifications thereof for use in hardware or software products * claiming conformance to the JPEG 2000 Standard. Those intending to use * this software module in hardware or software products are advised that * their use may infringe existing patents. The original developers of * this software module, JJ2000 Partners and ISO/IEC assume no liability * for use of this software module or modifications thereof. No license * or right to this software module is granted for non JPEG 2000 Standard * conforming products. JJ2000 Partners have full right to use this * software module for his/her own purpose, assign or donate this * software module to any third party and to inhibit third parties from * using this software module for non JPEG 2000 Standard conforming * products. This copyright notice must be included in all copies or * derivative works of this software module. * * Copyright (c) 1999/2000 JJ2000 Partners. * */ package jj2000.j2k.codestream.reader; import java.awt.Point; import jj2000.j2k.wavelet.synthesis.*; import jj2000.j2k.codestream.*; import jj2000.j2k.entropy.*; import jj2000.j2k.wavelet.*; import jj2000.j2k.decoder.*; import jj2000.j2k.image.*; import jj2000.j2k.util.*; import jj2000.j2k.io.*; import java.util.*; import java.io.*; /** * This class is used to read packet's head and body. All the members must be * re-initialized at the beginning of each tile thanks to the restart() * method. * */ public class PktDecoder implements StdEntropyCoderOptions{ /** Reference to the codestream reader agent */ private BitstreamReaderAgent src; /** Flag indicating whether packed packet header was used for this tile*/ private boolean pph=false; /** The packed packet header if it was used */ private ByteArrayInputStream pphbais; /** Reference to decoder specifications */ private DecoderSpecs decSpec; /** Reference to the HeaderDecoder */ private HeaderDecoder hd; /** Initial value of the state variable associated with code-block * length. */ private final int INIT_LBLOCK = 3; /** The wrapper to read bits for the packet heads */ private PktHeaderBitReader bin; /** Reference to the stream where to read from */ private RandomAccessIO ehs; /** * Maximum number of precincts : * *

      *
    • 1st dim: component index.
    • *
    • 2nd dim: resolution level index.
    • *
    * */ private Point[][] numPrec; /** Index of the current tile */ private int tIdx; /** * Array containing the coordinates, width, height, indexes, ... of the * precincts in the current tile: * *
      *
    • 1st dim: component index.
    • *
    • 2nd dim: resolution level index.
    • *
    • 3rd dim: precinct index.
    • *
    * */ private PrecInfo[][][] ppinfo; /** * Lblock value used to read code size information in each packet head: * *
      *
    • 1st dim: component index.
    • *
    • 2nd dim: resolution level index.
    • *
    • 3rd dim: subband index.
    • *
    • 4th/5th dim: code-block index (vert. and horiz.).
    • *
    * */ private int[][][][][] lblock; /** * Tag tree used to read inclusion informations in packet's head: * *