Compare commits
88 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 5da934e11b | |||
| 51297ad496 | |||
| 80a534cd62 | |||
| 24130d466d | |||
| 7559686782 | |||
| b6988c37a7 | |||
| bbffb1d416 | |||
| c68de3bc92 | |||
| a12b6044c6 | |||
| 9a0e2d9659 | |||
| b904f8952f | |||
| 187c952b8e | |||
| ca86605923 | |||
| 8bc863298f | |||
| 3447d1782c | |||
| bf245fde5f | |||
| c0748dcfd7 | |||
| c293516201 | |||
| f6dae36b7e | |||
| a14b481e9e | |||
| d9c1a39c37 | |||
| e9d9f99bb0 | |||
| b9749b94b0 | |||
| 4996dff6e4 | |||
| b1a2244c7f | |||
| c6fe747ca3 | |||
| e1af4d7da9 | |||
| 33556cc0ec | |||
| eaf13b102f | |||
| 74718f1ffb | |||
| bd3700ea59 | |||
| 8fccd9445f | |||
| cf0ed8f95c | |||
| c12e4e5646 | |||
| 287b73c732 | |||
| 24271b8cad | |||
| 3e2f54ee7c | |||
| 2511b2d0cd | |||
| a15d54c92c | |||
| 47b7c4b16c | |||
| 9e1b01a7fd | |||
| 769acc8726 | |||
| 1ace3a6d5f | |||
| a06eb53cd2 | |||
| 1e1a640a6c | |||
| 2444bc5ad4 | |||
| 2e656a45f9 | |||
| 657928f4a5 | |||
| 08f7e070dc | |||
| b205226f0c | |||
| 821df11d90 | |||
| a62a838a0d | |||
| 75ff0f265f | |||
| 15c7cfe9a6 | |||
| 1286077b02 | |||
| 5757743db7 | |||
| fbaa13d48d | |||
| f12df442e9 | |||
| 0c0712ab30 | |||
| 9267842788 | |||
| bcffeb04ec | |||
| d1a1bab18c | |||
| 6b5e75a22b | |||
| 7384118357 | |||
| 4d833a50e5 | |||
| 57b0fdac0b | |||
| e6bd94025f | |||
| 330a0414f0 | |||
| 5cc201b46d | |||
| 7e55d7765d | |||
| 8f942922fd | |||
| db5635e844 | |||
| 8bc952ba66 | |||
| 96cb3a07f4 | |||
| cd6a6258b6 | |||
| a0fa2c08ac | |||
| 6642b1647a | |||
| 5315caf830 | |||
| 872523b0f0 | |||
| 7bf99fb496 | |||
| a1047edddb | |||
| e956176872 | |||
| 6d2947b080 | |||
| fb304d6c27 | |||
| 903289caa4 | |||
| aff31ebd1b | |||
| b6773f6983 | |||
| 0d28eb31d2 |
@@ -1,15 +1,13 @@
|
|||||||
## Latest
|
[](https://travis-ci.org/haraldk/TwelveMonkeys)
|
||||||
|
[](https://maven-badges.herokuapp.com/maven-central/com.twelvemonkeys.imageio/imageio)
|
||||||
Master branch build status: [](https://travis-ci.org/haraldk/TwelveMonkeys)
|
[](https://stackoverflow.com/questions/tagged/twelvemonkeys)
|
||||||
|
[](https://paypal.me/haraldk76/100)
|
||||||
Latest release is TwelveMonkeys ImageIO [3.4.3](https://search.maven.org/search?q=g:com.twelvemonkeys.imageio%20AND%20v:3.4.3) (Jan. 9th, 2020).
|
|
||||||
[Release notes](https://github.com/haraldk/TwelveMonkeys/releases/latest).
|
|
||||||
|
|
||||||
## About
|
## About
|
||||||
|
|
||||||
TwelveMonkeys ImageIO is a collection of plugins and extensions for Java's ImageIO.
|
TwelveMonkeys ImageIO is a collection of plugins and extensions for Java's ImageIO.
|
||||||
|
|
||||||
These plugins extends the number of image file formats supported in Java, using the javax.imageio.* package.
|
These plugins extend the number of image file formats supported in Java, using the `javax.imageio.*` package.
|
||||||
The main purpose of this project is to provide support for formats not covered by the JRE itself.
|
The main purpose of this project is to provide support for formats not covered by the JRE itself.
|
||||||
|
|
||||||
Support for formats is important, both to be able to read data found
|
Support for formats is important, both to be able to read data found
|
||||||
@@ -19,246 +17,58 @@ The goal is to create a set of efficient and robust ImageIO plug-ins, that can b
|
|||||||
|
|
||||||
----
|
----
|
||||||
|
|
||||||
## Features
|
## File formats supported
|
||||||
|
|
||||||
Mainstream format support
|
| Plugin | Format | Description | Read | Write | Metadata | Notes |
|
||||||
|
| ------ | -------- | ----------- |:----:|:-----:| -------- | ----- |
|
||||||
|
| Batik | **SVG** | Scalable Vector Graphics | âś” | - | - | Requires [Batik](https://xmlgraphics.apache.org/batik/)
|
||||||
|
| | WMF | MS Windows Metafile | âś” | - | - | Requires [Batik](https://xmlgraphics.apache.org/batik/)
|
||||||
|
| [BMP](https://github.com/haraldk/TwelveMonkeys/wiki/BMP-Plugin) | **BMP** | MS Windows and IBM OS/2 Device Independent Bitmap | âś” | âś” | Native & Standard |
|
||||||
|
| | CUR | MS Windows Cursor Format | âś” | - | - |
|
||||||
|
| | ICO | MS Windows Icon Format | âś” | âś” | - |
|
||||||
|
| [HDR](https://github.com/haraldk/TwelveMonkeys/wiki/HDR-Plugin) | HDR | Radiance High Dynamic Range RGBE Format | âś” | - | Standard |
|
||||||
|
| [ICNS](https://github.com/haraldk/TwelveMonkeys/wiki/ICNS-Plugin) | ICNS | Apple Icon Image | âś” | âś” | - |
|
||||||
|
| [IFF](https://github.com/haraldk/TwelveMonkeys/wiki/IFF-Plugin) | IFF | Commodore Amiga/Electronic Arts Interchange File Format | âś” | âś” | - |
|
||||||
|
| [JPEG](https://github.com/haraldk/TwelveMonkeys/wiki/JPEG-Plugin) | **JPEG** | Joint Photographers Expert Group | âś” | âś” | Native & Standard |
|
||||||
|
| [PCX](https://github.com/haraldk/TwelveMonkeys/wiki/PCX-Plugin) | PCX | ZSoft Paintbrush Format | âś” | - | Standard |
|
||||||
|
| | DCX | Multi-page PCX fax document | âś” | - | Standard |
|
||||||
|
| [PICT](https://github.com/haraldk/TwelveMonkeys/wiki/PICT-Plugin) | PICT | Apple Mac Paint Picture Format | âś” | - | - |
|
||||||
|
| [PNM](https://github.com/haraldk/TwelveMonkeys/wiki/PNM-Plugin) | PAM | NetPBM Portable Any Map | âś” | âś” | Standard |
|
||||||
|
| | PBM | NetPBM Portable Bit Map | âś” | - | Standard |
|
||||||
|
| | PGM | NetPBM Portable Grey Map | âś” | - | Standard |
|
||||||
|
| | PPM | NetPBM Portable Pix Map | âś” | âś” | Standard |
|
||||||
|
| | PFM | Portable Float Map | âś” | - | Standard |
|
||||||
|
| [PSD](https://github.com/haraldk/TwelveMonkeys/wiki/PSD-Plugin) | **PSD** | Adobe Photoshop Document | âś” | - | Native & Standard |
|
||||||
|
| | PSB | Adobe Photoshop Large Document | âś” | - | Native & Standard |
|
||||||
|
| [SGI](https://github.com/haraldk/TwelveMonkeys/wiki/SGI-Plugin) | SGI | Silicon Graphics Image Format | âś” | - | Standard |
|
||||||
|
| [TGA](https://github.com/haraldk/TwelveMonkeys/wiki/TGA-Plugin) | TGA | Truevision TGA Image Format | âś” | âś” | Standard |
|
||||||
|
|ThumbsDB| Thumbs.db| MS Windows Thumbs DB | âś” | - | - | OLE2 Compound Document based format only
|
||||||
|
| [TIFF](https://github.com/haraldk/TwelveMonkeys/wiki/TIFF-Plugin) | **TIFF** | Aldus/Adobe Tagged Image File Format | âś” | âś” | Native & Standard |
|
||||||
|
| | BigTIFF | | âś” | - | Native & Standard |
|
||||||
|
| [WebP](https://github.com/haraldk/TwelveMonkeys/wiki/WebP-Plugin) | **WebP** | Google WebP Format | âś” | - | Standard | In progress
|
||||||
|
| XWD | XWD | X11 Window Dump Format | âś” | - | Standard |
|
||||||
|
|
||||||
#### BMP - MS Windows/IBM OS/2 Device Independent Bitmap
|
|
||||||
|
|
||||||
* Read support for all known versions of the DIB/BMP format
|
|
||||||
* Indexed color, 1, 4 and 8 bit, including 4 and 8 bit RLE
|
|
||||||
* RGB, 16, 24 and 32 bit
|
|
||||||
* Embedded PNG and JPEG data
|
|
||||||
* Windows and OS/2 versions
|
|
||||||
* Native and standard metadata format
|
|
||||||
|
|
||||||
#### JPEG
|
|
||||||
|
|
||||||
* Read support for the following JPEG "flavors":
|
|
||||||
* All JFIF compliant JPEGs
|
|
||||||
* All Exif compliant JPEGs
|
|
||||||
* YCbCr JPEGs without JFIF segment (converted to RGB, using embedded ICC profile)
|
|
||||||
* CMYK JPEGs (converted to RGB by default or as CMYK, using embedded ICC profile)
|
|
||||||
* Adobe YCCK JPEGs (converted to RGB by default or as CMYK, using embedded ICC profile)
|
|
||||||
* JPEGs containing ICC profiles with interpretation other than 'Perceptual' or class other than 'Display'
|
|
||||||
* JPEGs containing ICC profiles that are incompatible with stream data, corrupted ICC profiles or corrupted `ICC_PROFILE` segments
|
|
||||||
* JPEGs using non-standard color spaces, unsupported by Java 2D
|
|
||||||
* JPEGs with APP14/Adobe segments with length other than 14 bytes
|
|
||||||
* 8 bit JPEGs with 16 bit DQT segments
|
|
||||||
* Issues warnings instead of throwing exceptions in cases of corrupted or non-conformant data where ever the image
|
|
||||||
data can still be read in a reasonable way
|
|
||||||
* Thumbnail support:
|
|
||||||
* JFIF thumbnails (even if stream contains "inconsistent metadata")
|
|
||||||
* JFXX thumbnails (JPEG, Indexed and RGB)
|
|
||||||
* EXIF thumbnails (JPEG, RGB and YCbCr)
|
|
||||||
* Metadata support:
|
|
||||||
* JPEG metadata in both standard and native formats (even if stream contains "inconsistent metadata")
|
|
||||||
* `javax_imageio_jpeg_image_1.0` format (currently as native format, may change in the future)
|
|
||||||
* Non-conforming combinations of JFIF, Exif and Adobe markers, using "unknown" segments in the
|
|
||||||
"MarkerSequence" tag for the unsupported segments (for `javax_imageio_jpeg_image_1.0` format)
|
|
||||||
* Extended write support:
|
|
||||||
* CMYK JPEGs
|
|
||||||
* YCCK JPEGs in progress
|
|
||||||
|
|
||||||
#### JPEG-2000
|
|
||||||
|
|
||||||
* Possibly coming in the future, pending some license issues.
|
|
||||||
|
|
||||||
If you are one of the authors, or know one of the authors and/or the current license holders of either the original
|
|
||||||
jj2000 package or the JAI ImageIO project, please contact me (I've tried to get in touch in various ways,
|
|
||||||
without success so far).
|
|
||||||
|
|
||||||
Alternatively, if you have or know of a JPEG-2000 implementation in Java with a suitable license, get in touch. :-)
|
|
||||||
|
|
||||||
#### PNM - NetPBM Portable Any Map
|
|
||||||
|
|
||||||
* Read support for the following file types:
|
|
||||||
* PBM in 'P1' (ASCII) and 'P4' (binary) formats, 1 bit per pixel
|
|
||||||
* PGM in 'P2' (ASCII) and 'P5' (binary) formats, up to 16/32 bits per pixel
|
|
||||||
* PPM in 'P3' (ASCII) and 'P6' (binary) formats, up to 16/32 bits per pixel component
|
|
||||||
* PAM in 'P7' (binary) format up to 32 bits per pixel component
|
|
||||||
* Limited support for PFM in 'Pf' (gray) and 'PF' (RGB) formats, 32 bits floating point
|
|
||||||
* Write support for the following formats:
|
|
||||||
* PPM in 'P6' (binary) format
|
|
||||||
* PAM in 'P7' (binary) format
|
|
||||||
* Standard metadata support
|
|
||||||
|
|
||||||
#### PSD - Adobe Photoshop Document
|
|
||||||
|
|
||||||
* Read support for the following file types:
|
|
||||||
* Monochrome, 1 channel, 1 bit
|
|
||||||
* Indexed, 1 channel, 8 bit
|
|
||||||
* Gray, 1 channel, 8, 16 and 32 bit
|
|
||||||
* Duotone, 1 channel, 8, 16 and 32 bit
|
|
||||||
* RGB, 3-4 channels, 8, 16 and 32 bit
|
|
||||||
* CMYK, 4-5 channels, 8, 16 and 32 bit
|
|
||||||
* Read support for the following compression types:
|
|
||||||
* Uncompressed
|
|
||||||
* RLE (PackBits)
|
|
||||||
* Layer support
|
|
||||||
* Image layers only, in all of the above types
|
|
||||||
* Thumbnail support
|
|
||||||
* JPEG
|
|
||||||
* RAW (RGB)
|
|
||||||
* Support for "Large Document Format" (PSB)
|
|
||||||
* Native and Standard metadata support
|
|
||||||
|
|
||||||
#### TIFF - Aldus/Adobe Tagged Image File Format
|
|
||||||
|
|
||||||
* Read support for the following "Baseline" TIFF file types:
|
|
||||||
* Class B (Bi-level), all relevant compression types, 1 bit per sample
|
|
||||||
* Class G (Gray), all relevant compression types, 2, 4, 8, 16 or 32 bits per sample, unsigned integer
|
|
||||||
* Class P (Palette/indexed color), all relevant compression types, 1, 2, 4, 8 or 16 bits per sample, unsigned integer
|
|
||||||
* Class R (RGB), all relevant compression types, 8 or 16 bits per sample, unsigned integer
|
|
||||||
* Read support for the following TIFF extensions:
|
|
||||||
* Tiling
|
|
||||||
* Class F (Facsimile), CCITT Modified Huffman RLE, T4 and T6 (type 2, 3 and 4) compressions.
|
|
||||||
* LZW Compression (type 5)
|
|
||||||
* "Old-style" JPEG Compression (type 6), as a best effort, as the spec is not well-defined
|
|
||||||
* JPEG Compression (type 7)
|
|
||||||
* ZLib (aka Adobe-style Deflate) Compression (type 8)
|
|
||||||
* Deflate Compression (type 32946)
|
|
||||||
* Horizontal differencing Predictor (type 2) for LZW, ZLib, Deflate and PackBits compression
|
|
||||||
* Alpha channel (ExtraSamples type 1/Associated Alpha and type 2/Unassociated Alpha)
|
|
||||||
* CMYK data (PhotometricInterpretation type 5/Separated)
|
|
||||||
* YCbCr data (PhotometricInterpretation type 6/YCbCr) for JPEG
|
|
||||||
* CIELab data in TIFF, ITU and ICC variants (PhotometricInterpretation type 9, 10 and 11)
|
|
||||||
* Planar data (PlanarConfiguration type 2/Planar)
|
|
||||||
* ICC profiles (ICCProfile)
|
|
||||||
* BitsPerSample values up to 16 for most PhotometricInterpretations
|
|
||||||
* Multiple images (pages) in one file
|
|
||||||
* Write support for most "Baseline" TIFF options
|
|
||||||
* Uncompressed, PackBits, ZLib and Deflate
|
|
||||||
* Additional support for CCITT T4 and and T6 compressions.
|
|
||||||
* Additional support for LZW and JPEG (type 7) compressions
|
|
||||||
* Horizontal differencing Predictor (type 2) for LZW, ZLib, Deflate
|
|
||||||
* Native and Standard metadata support
|
|
||||||
|
|
||||||
Legacy formats
|
|
||||||
|
|
||||||
#### HDR - Radiance High Dynamic Range RGBE Format
|
|
||||||
|
|
||||||
* Read support for the most common RGBE (.hdr) format
|
|
||||||
* Samples are converted to 32 bit floating point (`float`) and normalized using a global tone mapper by default.
|
|
||||||
* Support for custom global tone mappers
|
|
||||||
* Alternatively, use a "null-tone mapper", for unnormalized data (allows local tone mapping)
|
|
||||||
* Unconverted RGBE samples accessible using `readRaster`
|
|
||||||
* Standard metadata support
|
|
||||||
|
|
||||||
#### IFF - Commodore Amiga/Electronic Arts Interchange File Format
|
|
||||||
|
|
||||||
* Legacy format, allows reading popular image format from the Commodore Amiga computer.
|
|
||||||
* Read support for the following file types:
|
|
||||||
* ILBM Indexed color, 1-8 interleaved bit planes, including 6 bit EHB
|
|
||||||
* ILBM Gray, 8 bit interleaved bit planes
|
|
||||||
* ILBM RGB, 24 and 32 bit interleaved bit planes
|
|
||||||
* ILBM HAM6 and HAM8
|
|
||||||
* PBM Indexed color, 1-8 bit,
|
|
||||||
* PBM Gray, 8 bit
|
|
||||||
* PBM RGB, 24 and 32 bit
|
|
||||||
* PBM HAM6 and HAM8
|
|
||||||
* Write support
|
|
||||||
* ILBM Indexed color, 1-8 bits per sample, 8 bit gray, 24 and 32 bit true color.
|
|
||||||
* Support for the following compression types (read/write):
|
|
||||||
* Uncompressed
|
|
||||||
* RLE (PackBits)
|
|
||||||
|
|
||||||
#### PCX - ZSoft Paintbrush Format
|
|
||||||
|
|
||||||
* Read support for the following file types:
|
|
||||||
* Indexed color, 1, 2, 4 or 8 bits per pixel, bit planes or interleaved
|
|
||||||
* Grayscale, 8 bits per pixel
|
|
||||||
* Color (RGB), 8 bits per pixel component
|
|
||||||
* Read support for DCX (multi-page) fax format, containing any of the above types
|
|
||||||
* Support for the following compression types:
|
|
||||||
* Uncompressed (experimental)
|
|
||||||
* RLE compressed
|
|
||||||
* Standard metadata support
|
|
||||||
|
|
||||||
#### PICT - Apple Mac Paint Picture Format
|
|
||||||
|
|
||||||
* Legacy format, especially useful for reading OS X clipboard data.
|
|
||||||
* Read support for the following file types:
|
|
||||||
* QuickDraw (format support is not complete, but supports most OS X clipboard data as well as RGB pixel data)
|
|
||||||
* QuickDraw bitmap
|
|
||||||
* QuickDraw pixmap
|
|
||||||
* QuickTime stills
|
|
||||||
* Write support for RGB pixel data:
|
|
||||||
* QuickDraw pixmap
|
|
||||||
|
|
||||||
#### SGI - Silicon Graphics Image Format
|
|
||||||
|
|
||||||
* Read support for the following file types:
|
|
||||||
* 1, 2, 3 or 4 channel image data
|
|
||||||
* 8 or 16 bits per pixel component
|
|
||||||
* Support for the following compression types:
|
|
||||||
* Uncompressed
|
|
||||||
* RLE compressed
|
|
||||||
* Standard metadata support
|
|
||||||
|
|
||||||
#### TGA - Truevision TGA Image Format
|
|
||||||
|
|
||||||
* Read support for the following file types:
|
|
||||||
* ColorMapped
|
|
||||||
* Monochrome
|
|
||||||
* TrueColor
|
|
||||||
* Support for the following compression types:
|
|
||||||
* Uncompressed
|
|
||||||
* RLE compressed
|
|
||||||
* Standard metadata support
|
|
||||||
* Write support
|
|
||||||
|
|
||||||
Icon/other formats
|
|
||||||
|
|
||||||
#### ICNS - Apple Icon Image
|
|
||||||
|
|
||||||
* Read support for the following icon types:
|
|
||||||
* All known "native" icon types
|
|
||||||
* Large PNG encoded icons
|
|
||||||
* Large JPEG 2000 encoded icons (requires JPEG 2000 ImageIO plugin or fallback to `sips` command line tool)
|
|
||||||
* Write support for PNG encoded icons
|
|
||||||
|
|
||||||
#### ICO & CUR - MS Windows Icon and Cursor Formats
|
|
||||||
|
|
||||||
* Read support for the following file types:
|
|
||||||
* ICO Indexed color, 1, 4 and 8 bit
|
|
||||||
* ICO RGB, 16, 24 and 32 bit
|
|
||||||
* CUR Indexed color, 1, 4 and 8 bit
|
|
||||||
* CUR RGB, 16, 24 and 32 bit
|
|
||||||
* Write support
|
|
||||||
* *3.1* Note: These formats are now part of the BMP plugin
|
|
||||||
|
|
||||||
#### Thumbs.db - MS Windows Thumbs DB
|
|
||||||
|
|
||||||
* Read support
|
|
||||||
|
|
||||||
Other formats, using 3rd party libraries
|
|
||||||
|
|
||||||
#### SVG - Scalable Vector Graphics
|
|
||||||
|
|
||||||
* Read-only support using Batik
|
|
||||||
|
|
||||||
#### WMF - MS Windows MetaFile
|
|
||||||
|
|
||||||
* Limited read-only support using Batik
|
|
||||||
|
|
||||||
**Important note on using Batik:** *Please read [The Apache™ XML Graphics Project - Security](http://xmlgraphics.apache.org/security.html), and make sure you use
|
|
||||||
either version 1.6.1, 1.7.1 or 1.8+.*
|
|
||||||
|
|
||||||
|
**Important note on using Batik:** *Please read [The Apache™ XML Graphics Project - Security](http://xmlgraphics.apache.org/security.html),
|
||||||
|
and make sure you use either version 1.6.1, 1.7.1, 1.8+ or later.*
|
||||||
|
|
||||||
## Basic usage
|
## Basic usage
|
||||||
|
|
||||||
Most of the time, all you need to do is simply include the plugins in your project and write:
|
Most of the time, all you need to do is simply include the plugins in your project and write:
|
||||||
|
|
||||||
BufferedImage image = ImageIO.read(file);
|
```java
|
||||||
|
BufferedImage image = ImageIO.read(file);
|
||||||
|
```
|
||||||
|
|
||||||
This will load the first image of the file, entirely into memory.
|
This will load the first image of the file, entirely into memory.
|
||||||
|
|
||||||
The basic and simplest form of writing is:
|
The basic and simplest form of writing is:
|
||||||
|
|
||||||
if (!ImageIO.write(image, format, file)) {
|
```java
|
||||||
// Handle image not written case
|
if (!ImageIO.write(image, format, file)) {
|
||||||
}
|
// Handle image not written case
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
This will write the entire image into a single file, using the default settings for the given format.
|
This will write the entire image into a single file, using the default settings for the given format.
|
||||||
|
|
||||||
@@ -269,50 +79,50 @@ The plugins are discovered automatically at run time. See the [FAQ](#faq) for mo
|
|||||||
If you need more control of read parameters and the reading process, the common idiom for reading is something like:
|
If you need more control of read parameters and the reading process, the common idiom for reading is something like:
|
||||||
|
|
||||||
```java
|
```java
|
||||||
// Create input stream
|
// Create input stream
|
||||||
ImageInputStream input = ImageIO.createImageInputStream(file);
|
ImageInputStream input = ImageIO.createImageInputStream(file);
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Get the reader
|
||||||
|
Iterator<ImageReader> readers = ImageIO.getImageReaders(input);
|
||||||
|
|
||||||
|
if (!readers.hasNext()) {
|
||||||
|
throw new IllegalArgumentException("No reader for: " + file);
|
||||||
|
}
|
||||||
|
|
||||||
|
ImageReader reader = readers.next();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Get the reader
|
reader.setInput(input);
|
||||||
Iterator<ImageReader> readers = ImageIO.getImageReaders(input);
|
|
||||||
|
|
||||||
if (!readers.hasNext()) {
|
// Optionally, listen for read warnings, progress, etc.
|
||||||
throw new IllegalArgumentException("No reader for: " + file);
|
reader.addIIOReadWarningListener(...);
|
||||||
}
|
reader.addIIOReadProgressListener(...);
|
||||||
|
|
||||||
ImageReader reader = readers.next();
|
ImageReadParam param = reader.getDefaultReadParam();
|
||||||
|
|
||||||
try {
|
// Optionally, control read settings like sub sampling, source region or destination etc.
|
||||||
reader.setInput(input);
|
param.setSourceSubsampling(...);
|
||||||
|
param.setSourceRegion(...);
|
||||||
|
param.setDestination(...);
|
||||||
|
// ...
|
||||||
|
|
||||||
// Optionally, listen for read warnings, progress, etc.
|
// Finally read the image, using settings from param
|
||||||
reader.addIIOReadWarningListener(...);
|
BufferedImage image = reader.read(0, param);
|
||||||
reader.addIIOReadProgressListener(...);
|
|
||||||
|
|
||||||
ImageReadParam param = reader.getDefaultReadParam();
|
// Optionally, read thumbnails, meta data, etc...
|
||||||
|
int numThumbs = reader.getNumThumbnails(0);
|
||||||
// Optionally, control read settings like sub sampling, source region or destination etc.
|
// ...
|
||||||
param.setSourceSubsampling(...);
|
|
||||||
param.setSourceRegion(...);
|
|
||||||
param.setDestination(...);
|
|
||||||
// ...
|
|
||||||
|
|
||||||
// Finally read the image, using settings from param
|
|
||||||
BufferedImage image = reader.read(0, param);
|
|
||||||
|
|
||||||
// Optionally, read thumbnails, meta data, etc...
|
|
||||||
int numThumbs = reader.getNumThumbnails(0);
|
|
||||||
// ...
|
|
||||||
}
|
|
||||||
finally {
|
|
||||||
// Dispose reader in finally block to avoid memory leaks
|
|
||||||
reader.dispose();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
// Close stream in finally block to avoid resource leaks
|
// Dispose reader in finally block to avoid memory leaks
|
||||||
input.close();
|
reader.dispose();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
// Close stream in finally block to avoid resource leaks
|
||||||
|
input.close();
|
||||||
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Query the reader for source image dimensions using `reader.getWidth(n)` and `reader.getHeight(n)` without reading the
|
Query the reader for source image dimensions using `reader.getWidth(n)` and `reader.getHeight(n)` without reading the
|
||||||
@@ -324,86 +134,62 @@ It's also possible to read multiple images from the same file in a loop, using `
|
|||||||
If you need more control of write parameters and the writing process, the common idiom for writing is something like:
|
If you need more control of write parameters and the writing process, the common idiom for writing is something like:
|
||||||
|
|
||||||
```java
|
```java
|
||||||
// Get the writer
|
// Get the writer
|
||||||
Iterator<ImageWriter> writers = ImageIO.getImageWritersByFormatName(format);
|
Iterator<ImageWriter> writers = ImageIO.getImageWritersByFormatName(format);
|
||||||
|
|
||||||
if (!writers.hasNext()) {
|
if (!writers.hasNext()) {
|
||||||
throw new IllegalArgumentException("No writer for: " + format);
|
throw new IllegalArgumentException("No writer for: " + format);
|
||||||
}
|
}
|
||||||
|
|
||||||
ImageWriter writer = writers.next();
|
ImageWriter writer = writers.next();
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Create output stream
|
||||||
|
ImageOutputStream output = ImageIO.createImageOutputStream(file);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Create output stream
|
writer.setOutput(output);
|
||||||
ImageOutputStream output = ImageIO.createImageOutputStream(file);
|
|
||||||
|
|
||||||
try {
|
// Optionally, listen to progress, warnings, etc.
|
||||||
writer.setOutput(output);
|
|
||||||
|
|
||||||
// Optionally, listen to progress, warnings, etc.
|
ImageWriteParam param = writer.getDefaultWriteParam();
|
||||||
|
|
||||||
ImageWriteParam param = writer.getDefaultWriteParam();
|
// Optionally, control format specific settings of param (requires casting), or
|
||||||
|
// control generic write settings like sub sampling, source region, output type etc.
|
||||||
|
|
||||||
// Optionally, control format specific settings of param (requires casting), or
|
// Optionally, provide thumbnails and image/stream metadata
|
||||||
// control generic write settings like sub sampling, source region, output type etc.
|
writer.write(..., new IIOImage(..., image, ...), param);
|
||||||
|
|
||||||
// Optionally, provide thumbnails and image/stream metadata
|
|
||||||
writer.write(..., new IIOImage(..., image, ...), param);
|
|
||||||
}
|
|
||||||
finally {
|
|
||||||
// Close stream in finally block to avoid resource leaks
|
|
||||||
output.close();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
// Dispose writer in finally block to avoid memory leaks
|
// Close stream in finally block to avoid resource leaks
|
||||||
writer.dispose();
|
output.close();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
// Dispose writer in finally block to avoid memory leaks
|
||||||
|
writer.dispose();
|
||||||
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
For more advanced usage, and information on how to use the ImageIO API, I suggest you read the
|
For more advanced usage, and information on how to use the ImageIO API, I suggest you read the
|
||||||
[Java Image I/O API Guide](http://docs.oracle.com/javase/7/docs/technotes/guides/imageio/spec/imageio_guideTOC.fm.html)
|
[Java Image I/O API Guide](http://docs.oracle.com/javase/7/docs/technotes/guides/imageio/spec/imageio_guideTOC.fm.html)
|
||||||
from Oracle.
|
from Oracle.
|
||||||
|
|
||||||
|
#### Adobe Clipping Path support
|
||||||
|
|
||||||
#### Deploying the plugins in a web app
|
```java
|
||||||
|
import com.twelvemonkeys.imageio.path.Paths;
|
||||||
|
|
||||||
Because the `ImageIO` plugin registry (the `IIORegistry`) is "VM global", it doesn't by default work well with
|
...
|
||||||
servlet contexts. This is especially evident if you load plugins from the `WEB-INF/lib` or `classes` folder.
|
|
||||||
Unless you add `ImageIO.scanForPlugins()` somewhere in your code, the plugins might never be available at all.
|
|
||||||
|
|
||||||
In addition, servlet contexts dynamically loads and unloads classes (using a new class loader per context).
|
try (ImageInputStream stream = ImageIO.createImageInputStream(new File("image_with_path.jpg")) {
|
||||||
If you restart your application, old classes will by default remain in memory forever (because the next time
|
BufferedImage image = Paths.readClipped(stream);
|
||||||
`scanForPlugins` is called, it's another `ClassLoader` that scans/loads classes, and thus they will be new instances
|
|
||||||
in the registry). If a read is attempted using one of the remaining "old" readers, weird exceptions
|
|
||||||
(like `NullPointerException`s when accessing `static final` initialized fields or `NoClassDefFoundError`s
|
|
||||||
for uninitialized inner classes) may occur.
|
|
||||||
|
|
||||||
To work around both the discovery problem and the resource leak,
|
// Do something with the clipped image...
|
||||||
it is *strongly recommended* to use the `IIOProviderContextListener` that implements
|
}
|
||||||
dynamic loading and unloading of ImageIO plugins for web applications.
|
|
||||||
|
|
||||||
```xml
|
|
||||||
<web-app ...>
|
|
||||||
|
|
||||||
...
|
|
||||||
|
|
||||||
<listener>
|
|
||||||
<display-name>ImageIO service provider loader/unloader</display-name>
|
|
||||||
<listener-class>com.twelvemonkeys.servlet.image.IIOProviderContextListener</listener-class>
|
|
||||||
</listener>
|
|
||||||
|
|
||||||
...
|
|
||||||
|
|
||||||
</web-app>
|
|
||||||
```
|
```
|
||||||
|
See [Adobe Clipping Path support on the Wiki](https://github.com/haraldk/TwelveMonkeys/wiki/Photoshop-Clipping-Path-support) for more details and example code.
|
||||||
|
|
||||||
Loading plugins from `WEB-INF/lib` without the context listener installed is unsupported and will not work correctly.
|
|
||||||
|
|
||||||
The context listener has no dependencies to the TwelveMonkeys ImageIO plugins, and may be used with JAI ImageIO
|
|
||||||
or other ImageIO plugins as well.
|
|
||||||
|
|
||||||
Another safe option, is to place the JAR files in the application server's shared or common lib folder.
|
|
||||||
|
|
||||||
#### Using the ResampleOp
|
#### Using the ResampleOp
|
||||||
|
|
||||||
@@ -411,15 +197,15 @@ The library comes with a resampling (image resizing) operation, that contains ma
|
|||||||
to provide excellent results at reasonable speed.
|
to provide excellent results at reasonable speed.
|
||||||
|
|
||||||
```java
|
```java
|
||||||
import com.twelvemonkeys.image.ResampleOp;
|
import com.twelvemonkeys.image.ResampleOp;
|
||||||
|
|
||||||
...
|
...
|
||||||
|
|
||||||
BufferedImage input = ...; // Image to resample
|
BufferedImage input = ...; // Image to resample
|
||||||
int width, height = ...; // new width/height
|
int width, height = ...; // new width/height
|
||||||
|
|
||||||
BufferedImageOp resampler = new ResampleOp(width, height, ResampleOp.FILTER_LANCZOS); // A good default filter, see class documentation for more info
|
BufferedImageOp resampler = new ResampleOp(width, height, ResampleOp.FILTER_LANCZOS); // A good default filter, see class documentation for more info
|
||||||
BufferedImage output = resampler.filter(input, null);
|
BufferedImage output = resampler.filter(input, null);
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Using the DiffusionDither
|
#### Using the DiffusionDither
|
||||||
@@ -428,14 +214,14 @@ The library comes with a dithering operation, that can be used to convert `Buffe
|
|||||||
Floyd-Steinberg error-diffusion dither.
|
Floyd-Steinberg error-diffusion dither.
|
||||||
|
|
||||||
```java
|
```java
|
||||||
import com.twelvemonkeys.image.DiffusionDither;
|
import com.twelvemonkeys.image.DiffusionDither;
|
||||||
|
|
||||||
...
|
...
|
||||||
|
|
||||||
BufferedImage input = ...; // Image to dither
|
BufferedImage input = ...; // Image to dither
|
||||||
|
|
||||||
BufferedImageOp ditherer = new DiffusionDither();
|
BufferedImageOp ditherer = new DiffusionDither();
|
||||||
BufferedImage output = ditherer.filter(input, null);
|
BufferedImage output = ditherer.filter(input, null);
|
||||||
```
|
```
|
||||||
|
|
||||||
## Building
|
## Building
|
||||||
@@ -473,10 +259,10 @@ The ImageIO registry and service lookup mechanism will make sure the plugins are
|
|||||||
To verify that the JPEG plugin is installed and used at run-time, you could use the following code:
|
To verify that the JPEG plugin is installed and used at run-time, you could use the following code:
|
||||||
|
|
||||||
```java
|
```java
|
||||||
Iterator<ImageReader> readers = ImageIO.getImageReadersByFormatName("JPEG");
|
Iterator<ImageReader> readers = ImageIO.getImageReadersByFormatName("JPEG");
|
||||||
while (readers.hasNext()) {
|
while (readers.hasNext()) {
|
||||||
System.out.println("reader: " + readers.next());
|
System.out.println("reader: " + readers.next());
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
The first line should print:
|
The first line should print:
|
||||||
@@ -488,82 +274,144 @@ The first line should print:
|
|||||||
To depend on the JPEG and TIFF plugin using Maven, add the following to your POM:
|
To depend on the JPEG and TIFF plugin using Maven, add the following to your POM:
|
||||||
|
|
||||||
```xml
|
```xml
|
||||||
|
...
|
||||||
|
<dependencies>
|
||||||
...
|
...
|
||||||
<dependencies>
|
<dependency>
|
||||||
...
|
<groupId>com.twelvemonkeys.imageio</groupId>
|
||||||
<dependency>
|
<artifactId>imageio-jpeg</artifactId>
|
||||||
<groupId>com.twelvemonkeys.imageio</groupId>
|
<version>3.6.1</version>
|
||||||
<artifactId>imageio-jpeg</artifactId>
|
</dependency>
|
||||||
<version>3.4.3</version>
|
<dependency>
|
||||||
</dependency>
|
<groupId>com.twelvemonkeys.imageio</groupId>
|
||||||
<dependency>
|
<artifactId>imageio-tiff</artifactId>
|
||||||
<groupId>com.twelvemonkeys.imageio</groupId>
|
<version>3.6.1</version>
|
||||||
<artifactId>imageio-tiff</artifactId>
|
</dependency>
|
||||||
<version>3.4.3</version>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
Optional dependency. Needed only if you deploy `ImageIO` plugins as part of a web app.
|
Optional dependency. Needed only if you deploy `ImageIO` plugins as part of a web app.
|
||||||
Make sure you add the `IIOProviderContextListener` to your `web.xml`, see above.
|
Make sure you add the `IIOProviderContextListener` to your `web.xml`, see above.
|
||||||
-->
|
-->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.twelvemonkeys.servlet</groupId>
|
<groupId>com.twelvemonkeys.servlet</groupId>
|
||||||
<artifactId>servlet</artifactId>
|
<artifactId>servlet</artifactId>
|
||||||
<version>3.4.3</version>
|
<version>3.6.1</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Manual dependency example
|
#### Manual dependency example
|
||||||
|
|
||||||
To depend on the JPEG and TIFF plugin in your IDE or program, add all of the following JARs to your class path:
|
To depend on the JPEG and TIFF plugin in your IDE or program, add all of the following JARs to your class path:
|
||||||
|
|
||||||
twelvemonkeys-common-lang-3.4.3.jar
|
twelvemonkeys-common-lang-3.6.1.jar
|
||||||
twelvemonkeys-common-io-3.4.3.jar
|
twelvemonkeys-common-io-3.6.1.jar
|
||||||
twelvemonkeys-common-image-3.4.3.jar
|
twelvemonkeys-common-image-3.6.1.jar
|
||||||
twelvemonkeys-imageio-core-3.4.3.jar
|
twelvemonkeys-imageio-core-3.6.1.jar
|
||||||
twelvemonkeys-imageio-metadata-3.4.3.jar
|
twelvemonkeys-imageio-metadata-3.6.1.jar
|
||||||
twelvemonkeys-imageio-jpeg-3.4.3.jar
|
twelvemonkeys-imageio-jpeg-3.6.1.jar
|
||||||
twelvemonkeys-imageio-tiff-3.4.3.jar
|
twelvemonkeys-imageio-tiff-3.6.1.jar
|
||||||
|
|
||||||
|
#### Deploying the plugins in a web app
|
||||||
|
|
||||||
|
Because the `ImageIO` plugin registry (the `IIORegistry`) is "VM global", it doesn't by default work well with
|
||||||
|
servlet contexts. This is especially evident if you load plugins from the `WEB-INF/lib` or `classes` folder.
|
||||||
|
Unless you add `ImageIO.scanForPlugins()` somewhere in your code, the plugins might never be available at all.
|
||||||
|
|
||||||
|
In addition, servlet contexts dynamically loads and unloads classes (using a new class loader per context).
|
||||||
|
If you restart your application, old classes will by default remain in memory forever (because the next time
|
||||||
|
`scanForPlugins` is called, it's another `ClassLoader` that scans/loads classes, and thus they will be new instances
|
||||||
|
in the registry). If a read is attempted using one of the remaining "old" readers, weird exceptions
|
||||||
|
(like `NullPointerException`s when accessing `static final` initialized fields or `NoClassDefFoundError`s
|
||||||
|
for uninitialized inner classes) may occur.
|
||||||
|
|
||||||
|
To work around both the discovery problem and the resource leak,
|
||||||
|
it is *strongly recommended* to use the `IIOProviderContextListener` that implements
|
||||||
|
dynamic loading and unloading of ImageIO plugins for web applications.
|
||||||
|
|
||||||
|
```xml
|
||||||
|
<web-app ...>
|
||||||
|
|
||||||
|
...
|
||||||
|
|
||||||
|
<listener>
|
||||||
|
<display-name>ImageIO service provider loader/unloader</display-name>
|
||||||
|
<listener-class>com.twelvemonkeys.servlet.image.IIOProviderContextListener</listener-class>
|
||||||
|
</listener>
|
||||||
|
|
||||||
|
...
|
||||||
|
|
||||||
|
</web-app>
|
||||||
|
```
|
||||||
|
|
||||||
|
Loading plugins from `WEB-INF/lib` without the context listener installed is unsupported and will not work correctly.
|
||||||
|
|
||||||
|
The context listener has no dependencies to the TwelveMonkeys ImageIO plugins, and may be used with JAI ImageIO
|
||||||
|
or other ImageIO plugins as well.
|
||||||
|
|
||||||
|
Another safe option, is to place the JAR files in the application server's shared or common lib folder.
|
||||||
|
|
||||||
|
#### Including the plugins in a "fat" JAR
|
||||||
|
|
||||||
|
The recommended way to use the plugins, is just to include the JARs as-is in your project, through a Maven dependency or similar.
|
||||||
|
Re-packaging is not necessary to use the library, and not recommended.
|
||||||
|
|
||||||
|
However, if you like to create a "fat"
|
||||||
|
JAR, or otherwise like to re-package the JARs for some reason, it's important to remember that automatic discovery of
|
||||||
|
the plugins by ImageIO depends on the
|
||||||
|
[Service Provider Interface (SPI)](https://docs.oracle.com/javase/tutorial/sound/SPI-intro.html) mechanism.
|
||||||
|
In short, each JAR contains a special folder, named `META-INF/services` containing one or more files,
|
||||||
|
typically `javax.imageio.spi.ImageReaderSpi` and `javax.imageio.spi.ImageWriterSpi`.
|
||||||
|
These files exist *with the same name in every JAR*,
|
||||||
|
so if you simply unpack everything to a single folder or create a JAR, files will be overwritten and behavior be
|
||||||
|
unspecified (most likely you will end up with a single plugin being installed).
|
||||||
|
|
||||||
|
The solution is to make sure all files with the same name, are merged to a single file,
|
||||||
|
containing all the SPI information of each type. If using the Maven Shade plugin, you should use the
|
||||||
|
[ServicesResourceTransformer](https://maven.apache.org/plugins/maven-shade-plugin/examples/resource-transformers.html#ServicesResourceTransformer)
|
||||||
|
to properly merge these files. You may also want to use the
|
||||||
|
[ManifestResourceTransforme](https://maven.apache.org/plugins/maven-shade-plugin/examples/resource-transformers.html#ManifestResourceTransformer)
|
||||||
|
to get the correct vendor name, version info etc.
|
||||||
|
Other "fat" JAR bundlers will probably have similar mechanisms to merge entries with the same name.
|
||||||
|
|
||||||
### Links to prebuilt binaries
|
### Links to prebuilt binaries
|
||||||
|
|
||||||
##### Latest version (3.4.3)
|
##### Latest version (3.6.1)
|
||||||
|
|
||||||
Requires Java 7 or later.
|
Requires Java 7 or later.
|
||||||
|
|
||||||
Common dependencies
|
Common dependencies
|
||||||
* [common-lang-3.4.3.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/common/common-lang/3.4.3/common-lang-3.4.3.jar)
|
* [common-lang-3.6.1.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/common/common-lang/3.6.1/common-lang-3.6.1.jar)
|
||||||
* [common-io-3.4.3.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/common/common-io/3.4.3/common-io-3.4.3.jar)
|
* [common-io-3.6.1.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/common/common-io/3.6.1/common-io-3.6.1.jar)
|
||||||
* [common-image-3.4.3.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/common/common-image/3.4.3/common-image-3.4.3.jar)
|
* [common-image-3.6.1.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/common/common-image/3.6.1/common-image-3.6.1.jar)
|
||||||
|
|
||||||
ImageIO dependencies
|
ImageIO dependencies
|
||||||
* [imageio-core-3.4.3.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-core/3.4.3/imageio-core-3.4.3.jar)
|
* [imageio-core-3.6.1.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-core/3.6.1/imageio-core-3.6.1.jar)
|
||||||
* [imageio-metadata-3.4.3.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-metadata/3.4.3/imageio-metadata-3.4.3.jar)
|
* [imageio-metadata-3.6.1.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-metadata/3.6.1/imageio-metadata-3.6.1.jar)
|
||||||
|
|
||||||
ImageIO plugins
|
ImageIO plugins
|
||||||
* [imageio-bmp-3.4.3.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-bmp/3.4.3/imageio-bmp-3.4.3.jar)
|
* [imageio-bmp-3.6.1.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-bmp/3.6.1/imageio-bmp-3.6.1.jar)
|
||||||
* [imageio-jpeg-3.4.3.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-jpeg/3.4.3/imageio-jpeg-3.4.3.jar)
|
* [imageio-jpeg-3.6.1.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-jpeg/3.6.1/imageio-jpeg-3.6.1.jar)
|
||||||
* [imageio-tiff-3.4.3.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-tiff/3.4.3/imageio-tiff-3.4.3.jar)
|
* [imageio-tiff-3.6.1.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-tiff/3.6.1/imageio-tiff-3.6.1.jar)
|
||||||
* [imageio-pnm-3.4.3.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-pnm/3.4.3/imageio-pnm-3.4.3.jar)
|
* [imageio-pnm-3.6.1.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-pnm/3.6.1/imageio-pnm-3.6.1.jar)
|
||||||
* [imageio-psd-3.4.3.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-psd/3.4.3/imageio-psd-3.4.3.jar)
|
* [imageio-psd-3.6.1.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-psd/3.6.1/imageio-psd-3.6.1.jar)
|
||||||
* [imageio-hdr-3.4.3.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-hdr/3.4.3/imageio-hdr-3.4.3.jar)
|
* [imageio-hdr-3.6.1.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-hdr/3.6.1/imageio-hdr-3.6.1.jar)
|
||||||
* [imageio-iff-3.4.3.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-iff/3.4.3/imageio-iff-3.4.3.jar)
|
* [imageio-iff-3.6.1.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-iff/3.6.1/imageio-iff-3.6.1.jar)
|
||||||
* [imageio-pcx-3.4.3.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-pcx/3.4.3/imageio-pcx-3.4.3.jar)
|
* [imageio-pcx-3.6.1.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-pcx/3.6.1/imageio-pcx-3.6.1.jar)
|
||||||
* [imageio-pict-3.4.3.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-pict/3.4.3/imageio-pict-3.4.3.jar)
|
* [imageio-pict-3.6.1.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-pict/3.6.1/imageio-pict-3.6.1.jar)
|
||||||
* [imageio-sgi-3.4.3.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-sgi/3.4.3/imageio-sgi-3.4.3.jar)
|
* [imageio-sgi-3.6.1.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-sgi/3.6.1/imageio-sgi-3.6.1.jar)
|
||||||
* [imageio-tga-3.4.3.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-tga/3.4.3/imageio-tga-3.4.3.jar)
|
* [imageio-tga-3.6.1.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-tga/3.6.1/imageio-tga-3.6.1.jar)
|
||||||
* [imageio-icns-3.4.3.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-icns/3.4.3/imageio-icns-3.4.3.jar)
|
* [imageio-icns-3.6.1.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-icns/3.6.1/imageio-icns-3.6.1.jar)
|
||||||
* [imageio-thumbsdb-3.4.3.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-thumbsdb/3.4.3/imageio-thumbsdb-3.4.3.jar)
|
* [imageio-thumbsdb-3.6.1.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-thumbsdb/3.6.1/imageio-thumbsdb-3.6.1.jar)
|
||||||
|
|
||||||
ImageIO plugins requiring 3rd party libs
|
ImageIO plugins requiring 3rd party libs
|
||||||
* [imageio-batik-3.4.3.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-batik/3.4.3/imageio-batik-3.4.3.jar)
|
* [imageio-batik-3.6.1.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-batik/3.6.1/imageio-batik-3.6.1.jar)
|
||||||
|
|
||||||
Photoshop Path support for ImageIO
|
Photoshop Path support for ImageIO
|
||||||
* [imageio-clippath-3.4.3.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-clippath/3.4.3/imageio-clippath-3.4.3.jar)
|
* [imageio-clippath-3.6.1.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-clippath/3.6.1/imageio-clippath-3.6.1.jar)
|
||||||
|
|
||||||
Servlet support
|
Servlet support
|
||||||
* [servlet-3.4.3.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/servlet/servlet/3.4.3/servlet-3.4.3.jar)
|
* [servlet-3.6.1.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/servlet/servlet/3.6.1/servlet-3.6.1.jar)
|
||||||
|
|
||||||
##### Old version (3.0.x)
|
##### Old version (3.0.x)
|
||||||
|
|
||||||
@@ -600,7 +448,7 @@ Servlet support
|
|||||||
|
|
||||||
The project is distributed under the OSI approved [BSD license](http://opensource.org/licenses/BSD-3-Clause):
|
The project is distributed under the OSI approved [BSD license](http://opensource.org/licenses/BSD-3-Clause):
|
||||||
|
|
||||||
Copyright (c) 2008-2018, Harald Kuhr
|
Copyright (c) 2008-2020, Harald Kuhr
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>com.twelvemonkeys</groupId>
|
<groupId>com.twelvemonkeys</groupId>
|
||||||
<artifactId>twelvemonkeys</artifactId>
|
<artifactId>twelvemonkeys</artifactId>
|
||||||
<version>3.5</version>
|
<version>3.6.2</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<groupId>com.twelvemonkeys.bom</groupId>
|
<groupId>com.twelvemonkeys.bom</groupId>
|
||||||
@@ -123,6 +123,11 @@
|
|||||||
<artifactId>imageio-tiff</artifactId>
|
<artifactId>imageio-tiff</artifactId>
|
||||||
<version>${project.version}</version>
|
<version>${project.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.twelvemonkeys.imageio</groupId>
|
||||||
|
<artifactId>imageio-xwd</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<!-- ImageIO 3rd party dependent plugins -->
|
<!-- ImageIO 3rd party dependent plugins -->
|
||||||
<dependency>
|
<dependency>
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>com.twelvemonkeys.common</groupId>
|
<groupId>com.twelvemonkeys.common</groupId>
|
||||||
<artifactId>common</artifactId>
|
<artifactId>common</artifactId>
|
||||||
<version>3.5</version>
|
<version>3.6.2</version>
|
||||||
</parent>
|
</parent>
|
||||||
<artifactId>common-image</artifactId>
|
<artifactId>common-image</artifactId>
|
||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>com.twelvemonkeys.common</groupId>
|
<groupId>com.twelvemonkeys.common</groupId>
|
||||||
<artifactId>common</artifactId>
|
<artifactId>common</artifactId>
|
||||||
<version>3.5</version>
|
<version>3.6.2</version>
|
||||||
</parent>
|
</parent>
|
||||||
<artifactId>common-io</artifactId>
|
<artifactId>common-io</artifactId>
|
||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ public final class FastByteArrayOutputStream extends ByteArrayOutputStream {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void write(byte pBytes[], int pOffset, int pLength) {
|
public void write(byte[] pBytes, int pOffset, int pLength) {
|
||||||
if ((pOffset < 0) || (pOffset > pBytes.length) || (pLength < 0) ||
|
if ((pOffset < 0) || (pOffset > pBytes.length) || (pLength < 0) ||
|
||||||
((pOffset + pLength) > pBytes.length) || ((pOffset + pLength) < 0)) {
|
((pOffset + pLength) > pBytes.length) || ((pOffset + pLength) < 0)) {
|
||||||
throw new IndexOutOfBoundsException();
|
throw new IndexOutOfBoundsException();
|
||||||
@@ -98,7 +98,7 @@ public final class FastByteArrayOutputStream extends ByteArrayOutputStream {
|
|||||||
private void growIfNeeded(int pNewCount) {
|
private void growIfNeeded(int pNewCount) {
|
||||||
if (pNewCount > buf.length) {
|
if (pNewCount > buf.length) {
|
||||||
int newSize = Math.max(Math.min(buf.length << 1, buf.length + maxGrowSize), pNewCount);
|
int newSize = Math.max(Math.min(buf.length << 1, buf.length + maxGrowSize), pNewCount);
|
||||||
byte newBuf[] = new byte[newSize];
|
byte[] newBuf = new byte[newSize];
|
||||||
System.arraycopy(buf, 0, newBuf, 0, count);
|
System.arraycopy(buf, 0, newBuf, 0, count);
|
||||||
buf = newBuf;
|
buf = newBuf;
|
||||||
}
|
}
|
||||||
@@ -113,7 +113,7 @@ public final class FastByteArrayOutputStream extends ByteArrayOutputStream {
|
|||||||
// Non-synchronized version of toByteArray
|
// Non-synchronized version of toByteArray
|
||||||
@Override
|
@Override
|
||||||
public byte[] toByteArray() {
|
public byte[] toByteArray() {
|
||||||
byte newBuf[] = new byte[count];
|
byte[] newBuf = new byte[count];
|
||||||
System.arraycopy(buf, 0, newBuf, 0, count);
|
System.arraycopy(buf, 0, newBuf, 0, count);
|
||||||
|
|
||||||
return newBuf;
|
return newBuf;
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>com.twelvemonkeys.common</groupId>
|
<groupId>com.twelvemonkeys.common</groupId>
|
||||||
<artifactId>common</artifactId>
|
<artifactId>common</artifactId>
|
||||||
<version>3.5</version>
|
<version>3.6.2</version>
|
||||||
</parent>
|
</parent>
|
||||||
<artifactId>common-lang</artifactId>
|
<artifactId>common-lang</artifactId>
|
||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
|
|||||||
@@ -129,8 +129,7 @@ public class Time {
|
|||||||
* @see #toString(String)
|
* @see #toString(String)
|
||||||
*/
|
*/
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "" + getMinutes() + ":"
|
return getMinutes() + ":" + (getSeconds() < 10 ? "0" : "") + getSeconds();
|
||||||
+ (getSeconds() < 10 ? "0" : "") + getSeconds();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -44,12 +44,12 @@ import java.util.Vector;
|
|||||||
* The format is expressed in a string as follows:
|
* The format is expressed in a string as follows:
|
||||||
* <DL>
|
* <DL>
|
||||||
* <DD>m (or any multiple of m's)
|
* <DD>m (or any multiple of m's)
|
||||||
* <DT>the minutes part (padded with 0's, if number has less digits than
|
* <DT>the minutes part (padded with 0's, if number has less digits than
|
||||||
* the number of m's)
|
* the number of m's)
|
||||||
* m -> 0,1,...,59,60,61,...
|
* m -> 0,1,...,59,60,61,...
|
||||||
* mm -> 00,01,...,59,60,61,...
|
* mm -> 00,01,...,59,60,61,...
|
||||||
* <DD>s or ss
|
* <DD>s or ss
|
||||||
* <DT>the seconds part (padded with 0's, if number has less digits than
|
* <DT>the seconds part (padded with 0's, if number has less digits than
|
||||||
* the number of s's)
|
* the number of s's)
|
||||||
* s -> 0,1,...,59
|
* s -> 0,1,...,59
|
||||||
* ss -> 00,01,...,59
|
* ss -> 00,01,...,59
|
||||||
@@ -62,7 +62,7 @@ import java.util.Vector;
|
|||||||
* <P>
|
* <P>
|
||||||
* Known bugs:
|
* Known bugs:
|
||||||
* <P>
|
* <P>
|
||||||
* The last character in the formatString is not escaped, while it should be.
|
* The last character in the formatString is not escaped, while it should be.
|
||||||
* The first character after an escaped character is escaped while is shouldn't
|
* The first character after an escaped character is escaped while is shouldn't
|
||||||
* be.
|
* be.
|
||||||
* <P>
|
* <P>
|
||||||
@@ -81,15 +81,15 @@ public class TimeFormat extends Format {
|
|||||||
final static String SECOND = "s";
|
final static String SECOND = "s";
|
||||||
final static String TIME = "S";
|
final static String TIME = "S";
|
||||||
final static String ESCAPE = "\\";
|
final static String ESCAPE = "\\";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The default time format
|
* The default time format
|
||||||
*/
|
*/
|
||||||
|
|
||||||
private final static TimeFormat DEFAULT_FORMAT = new TimeFormat("m:ss");
|
private final static TimeFormat DEFAULT_FORMAT = new TimeFormat("m:ss");
|
||||||
protected String formatString = null;
|
protected String formatString = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Main method for testing ONLY
|
* Main method for testing ONLY
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -122,7 +122,7 @@ public class TimeFormat extends Format {
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
time = new Time();
|
time = new Time();
|
||||||
|
|
||||||
System.out.println("Time is \"" + out.format(time) +
|
System.out.println("Time is \"" + out.format(time) +
|
||||||
"\" according to format \"" + out.formatString + "\"");
|
"\" according to format \"" + out.formatString + "\"");
|
||||||
}
|
}
|
||||||
@@ -147,18 +147,18 @@ public class TimeFormat extends Format {
|
|||||||
String previous = null;
|
String previous = null;
|
||||||
String current = null;
|
String current = null;
|
||||||
int previousCount = 0;
|
int previousCount = 0;
|
||||||
|
|
||||||
while (tok.hasMoreElements()) {
|
while (tok.hasMoreElements()) {
|
||||||
current = tok.nextToken();
|
current = tok.nextToken();
|
||||||
|
|
||||||
if (previous != null && previous.equals(ESCAPE)) {
|
if (previous != null && previous.equals(ESCAPE)) {
|
||||||
// Handle escaping of s, S or m
|
// Handle escaping of s, S or m
|
||||||
current = ((current != null) ? current : "")
|
current = ((current != null) ? current : "")
|
||||||
+ (tok.hasMoreElements() ? tok.nextToken() : "");
|
+ (tok.hasMoreElements() ? tok.nextToken() : "");
|
||||||
previous = null;
|
previous = null;
|
||||||
previousCount = 0;
|
previousCount = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Skip over first,
|
// Skip over first,
|
||||||
// or if current is the same, increase count, and try again
|
// or if current is the same, increase count, and try again
|
||||||
if (previous == null || previous.equals(current)) {
|
if (previous == null || previous.equals(current)) {
|
||||||
@@ -173,12 +173,12 @@ public class TimeFormat extends Format {
|
|||||||
formatter.add(new SecondsFormatter(previousCount));
|
formatter.add(new SecondsFormatter(previousCount));
|
||||||
else if (previous.equals(TIME))
|
else if (previous.equals(TIME))
|
||||||
formatter.add(new SecondsFormatter(-1));
|
formatter.add(new SecondsFormatter(-1));
|
||||||
else
|
else
|
||||||
formatter.add(new TextFormatter(previous));
|
formatter.add(new TextFormatter(previous));
|
||||||
|
|
||||||
previousCount = 1;
|
previousCount = 1;
|
||||||
previous = current;
|
previous = current;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -197,7 +197,7 @@ public class TimeFormat extends Format {
|
|||||||
// Debug
|
// Debug
|
||||||
/*
|
/*
|
||||||
for (int i = 0; i < formatter.size(); i++) {
|
for (int i = 0; i < formatter.size(); i++) {
|
||||||
System.out.println("Formatter " + formatter.get(i).getClass()
|
System.out.println("Formatter " + formatter.get(i).getClass()
|
||||||
+ ": length=" + ((TimeFormatter) formatter.get(i)).digits);
|
+ ": length=" + ((TimeFormatter) formatter.get(i)).digits);
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
@@ -206,7 +206,7 @@ public class TimeFormat extends Format {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* DUMMY IMPLEMENTATION!!
|
* DUMMY IMPLEMENTATION!!
|
||||||
* Not locale specific.
|
* Not locale specific.
|
||||||
*/
|
*/
|
||||||
@@ -259,9 +259,9 @@ public class TimeFormat extends Format {
|
|||||||
/** DUMMY IMPLEMENTATION!! */
|
/** DUMMY IMPLEMENTATION!! */
|
||||||
public Object parseObject(String pStr, ParsePosition pStatus) {
|
public Object parseObject(String pStr, ParsePosition pStatus) {
|
||||||
Time t = parse(pStr);
|
Time t = parse(pStr);
|
||||||
|
|
||||||
pStatus.setIndex(pStr.length()); // Not 100%
|
pStatus.setIndex(pStr.length()); // Not 100%
|
||||||
|
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -270,7 +270,7 @@ public class TimeFormat extends Format {
|
|||||||
* <p>
|
* <p>
|
||||||
* Will bug on some formats. It's safest to always use delimiters between
|
* Will bug on some formats. It's safest to always use delimiters between
|
||||||
* the minutes (m) and seconds (s) part.
|
* the minutes (m) and seconds (s) part.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public Time parse(String pStr) {
|
public Time parse(String pStr) {
|
||||||
Time time = new Time();
|
Time time = new Time();
|
||||||
@@ -286,7 +286,7 @@ public class TimeFormat extends Format {
|
|||||||
&& (pos + skip < pStr.length()) ; i++) {
|
&& (pos + skip < pStr.length()) ; i++) {
|
||||||
// Go to next offset
|
// Go to next offset
|
||||||
pos += skip;
|
pos += skip;
|
||||||
|
|
||||||
if (formatter[i] instanceof MinutesFormatter) {
|
if (formatter[i] instanceof MinutesFormatter) {
|
||||||
// Parse MINUTES
|
// Parse MINUTES
|
||||||
if ((i + 1) < formatter.length
|
if ((i + 1) < formatter.length
|
||||||
@@ -327,9 +327,9 @@ public class TimeFormat extends Format {
|
|||||||
else {
|
else {
|
||||||
// Cannot possibly know how long?
|
// Cannot possibly know how long?
|
||||||
skip = 0;
|
skip = 0;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get seconds
|
// Get seconds
|
||||||
sec = Integer.parseInt(pStr.substring(pos, skip));
|
sec = Integer.parseInt(pStr.substring(pos, skip));
|
||||||
// System.out.println("Only seconds: " + sec);
|
// System.out.println("Only seconds: " + sec);
|
||||||
@@ -343,7 +343,7 @@ public class TimeFormat extends Format {
|
|||||||
&& formatter[i + 1] instanceof TextFormatter) {
|
&& formatter[i + 1] instanceof TextFormatter) {
|
||||||
// Skip until next format element
|
// Skip until next format element
|
||||||
skip = pStr.indexOf(((TextFormatter) formatter[i + 1]).text, pos);
|
skip = pStr.indexOf(((TextFormatter) formatter[i + 1]).text, pos);
|
||||||
|
|
||||||
}
|
}
|
||||||
else if ((i + 1) >= formatter.length) {
|
else if ((i + 1) >= formatter.length) {
|
||||||
// Skip until end of string
|
// Skip until end of string
|
||||||
@@ -359,7 +359,7 @@ public class TimeFormat extends Format {
|
|||||||
else if (formatter[i] instanceof TextFormatter) {
|
else if (formatter[i] instanceof TextFormatter) {
|
||||||
skip = formatter[i].digits;
|
skip = formatter[i].digits;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the minutes part if we should
|
// Set the minutes part if we should
|
||||||
@@ -390,7 +390,7 @@ class SecondsFormatter extends TimeFormatter {
|
|||||||
SecondsFormatter(int pDigits) {
|
SecondsFormatter(int pDigits) {
|
||||||
digits = pDigits;
|
digits = pDigits;
|
||||||
}
|
}
|
||||||
|
|
||||||
String format(Time t) {
|
String format(Time t) {
|
||||||
// Negative number of digits, means all seconds, no padding
|
// Negative number of digits, means all seconds, no padding
|
||||||
if (digits < 0) {
|
if (digits < 0) {
|
||||||
@@ -404,7 +404,7 @@ class SecondsFormatter extends TimeFormatter {
|
|||||||
|
|
||||||
// Else return it with leading 0's
|
// Else return it with leading 0's
|
||||||
//return StringUtil.formatNumber(t.getSeconds(), digits);
|
//return StringUtil.formatNumber(t.getSeconds(), digits);
|
||||||
return StringUtil.pad("" + t.getSeconds(), digits, "0", true);
|
return StringUtil.pad(String.valueOf(t.getSeconds()), digits, "0", true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -425,7 +425,7 @@ class MinutesFormatter extends TimeFormatter {
|
|||||||
|
|
||||||
// Else return it with leading 0's
|
// Else return it with leading 0's
|
||||||
//return StringUtil.formatNumber(t.getMinutes(), digits);
|
//return StringUtil.formatNumber(t.getMinutes(), digits);
|
||||||
return StringUtil.pad("" + t.getMinutes(), digits, "0", true);
|
return StringUtil.pad(String.valueOf(t.getMinutes()), digits, "0", true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1117,18 +1117,19 @@ public abstract class CollectionAbstractTest extends ObjectAbstractTest {
|
|||||||
/**
|
/**
|
||||||
* Tests {@link Collection#toArray(Object[])}.
|
* Tests {@link Collection#toArray(Object[])}.
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings({"SuspiciousToArrayCall", "RedundantCast"})
|
||||||
@Test
|
@Test
|
||||||
public void testCollectionToArray2() {
|
public void testCollectionToArray2() {
|
||||||
resetEmpty();
|
resetEmpty();
|
||||||
Object[] a = new Object[] { new Object(), null, null };
|
Object[] a = new Object[] { new Object(), null, null };
|
||||||
Object[] array = collection.toArray(a);
|
Object[] array = collection.toArray(a);
|
||||||
assertArrayEquals("Given array shouldn't shrink", array, a);
|
assertArrayEquals("Given array shouldn't shrink", array, a);
|
||||||
assertEquals("Last element should be set to null", a[0], null);
|
assertNull("Last element should be set to null", a[0]);
|
||||||
verifyAll();
|
verifyAll();
|
||||||
|
|
||||||
resetFull();
|
resetFull();
|
||||||
try {
|
try {
|
||||||
array = collection.toArray(new Void[0]);
|
collection.toArray(new Void[0]);
|
||||||
fail("toArray(new Void[0]) should raise ArrayStore");
|
fail("toArray(new Void[0]) should raise ArrayStore");
|
||||||
} catch (ArrayStoreException e) {
|
} catch (ArrayStoreException e) {
|
||||||
// expected
|
// expected
|
||||||
@@ -1136,7 +1137,7 @@ public abstract class CollectionAbstractTest extends ObjectAbstractTest {
|
|||||||
verifyAll();
|
verifyAll();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
array = collection.toArray(null);
|
collection.toArray((Object[]) null);
|
||||||
fail("toArray(null) should raise NPE");
|
fail("toArray(null) should raise NPE");
|
||||||
} catch (NullPointerException e) {
|
} catch (NullPointerException e) {
|
||||||
// expected
|
// expected
|
||||||
@@ -1150,13 +1151,13 @@ public abstract class CollectionAbstractTest extends ObjectAbstractTest {
|
|||||||
|
|
||||||
// Figure out if they're all the same class
|
// Figure out if they're all the same class
|
||||||
// TODO: It'd be nicer to detect a common superclass
|
// TODO: It'd be nicer to detect a common superclass
|
||||||
HashSet classes = new HashSet();
|
HashSet<Class<?>> classes = new HashSet<>();
|
||||||
for (int i = 0; i < array.length; i++) {
|
for (int i = 0; i < array.length; i++) {
|
||||||
classes.add((array[i] == null) ? null : array[i].getClass());
|
classes.add((array[i] == null) ? null : array[i].getClass());
|
||||||
}
|
}
|
||||||
if (classes.size() > 1) return;
|
if (classes.size() > 1) return;
|
||||||
|
|
||||||
Class cl = (Class)classes.iterator().next();
|
Class<?> cl = (Class<?>)classes.iterator().next();
|
||||||
if (Map.Entry.class.isAssignableFrom(cl)) { // check needed for protective cases like Predicated/Unmod map entrySet
|
if (Map.Entry.class.isAssignableFrom(cl)) { // check needed for protective cases like Predicated/Unmod map entrySet
|
||||||
cl = Map.Entry.class;
|
cl = Map.Entry.class;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -250,12 +250,12 @@ public class CollectionUtilTest {
|
|||||||
assertCorrectListIterator(new ArrayList<String>(Arrays.asList(new String[] {"foo", "bar", "baz", "boo"})).subList(1, 3).listIterator(0), new String[] {"bar", "baz"}, true, true);
|
assertCorrectListIterator(new ArrayList<String>(Arrays.asList(new String[] {"foo", "bar", "baz", "boo"})).subList(1, 3).listIterator(0), new String[] {"bar", "baz"}, true, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void assertCorrectListIterator(ListIterator<String> iterator, final Object[] elements) {
|
private static void assertCorrectListIterator(ListIterator<String> iterator, final Object[] elements) {
|
||||||
assertCorrectListIterator(iterator, elements, false, false);
|
assertCorrectListIterator(iterator, elements, false, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE: The test is can only test list iterators with a starting index == 0
|
// NOTE: The test is can only test list iterators with a starting index == 0
|
||||||
private void assertCorrectListIterator(ListIterator<String> iterator, final Object[] elements, boolean skipRemove, boolean skipAdd) {
|
private static void assertCorrectListIterator(ListIterator<String> iterator, final Object[] elements, boolean skipRemove, boolean skipAdd) {
|
||||||
// Index is now "before 0"
|
// Index is now "before 0"
|
||||||
assertEquals(-1, iterator.previousIndex());
|
assertEquals(-1, iterator.previousIndex());
|
||||||
assertEquals(0, iterator.nextIndex());
|
assertEquals(0, iterator.nextIndex());
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>com.twelvemonkeys</groupId>
|
<groupId>com.twelvemonkeys</groupId>
|
||||||
<artifactId>twelvemonkeys</artifactId>
|
<artifactId>twelvemonkeys</artifactId>
|
||||||
<version>3.5</version>
|
<version>3.6.2</version>
|
||||||
</parent>
|
</parent>
|
||||||
<groupId>com.twelvemonkeys.common</groupId>
|
<groupId>com.twelvemonkeys.common</groupId>
|
||||||
<artifactId>common</artifactId>
|
<artifactId>common</artifactId>
|
||||||
@@ -47,7 +47,7 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>junit</groupId>
|
<groupId>junit</groupId>
|
||||||
<artifactId>junit</artifactId>
|
<artifactId>junit</artifactId>
|
||||||
<version>4.7</version>
|
<version>4.13.1</version>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>com.twelvemonkeys</groupId>
|
<groupId>com.twelvemonkeys</groupId>
|
||||||
<artifactId>twelvemonkeys</artifactId>
|
<artifactId>twelvemonkeys</artifactId>
|
||||||
<version>3.5</version>
|
<version>3.6.2</version>
|
||||||
</parent>
|
</parent>
|
||||||
<groupId>com.twelvemonkeys.contrib</groupId>
|
<groupId>com.twelvemonkeys.contrib</groupId>
|
||||||
<artifactId>contrib</artifactId>
|
<artifactId>contrib</artifactId>
|
||||||
@@ -65,7 +65,7 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>junit</groupId>
|
<groupId>junit</groupId>
|
||||||
<artifactId>junit</artifactId>
|
<artifactId>junit</artifactId>
|
||||||
<version>4.7</version>
|
<version>4.13.1</version>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|||||||
@@ -0,0 +1,152 @@
|
|||||||
|
package com.twelvemonkeys.contrib.exif;
|
||||||
|
|
||||||
|
import com.twelvemonkeys.image.ImageUtil;
|
||||||
|
import com.twelvemonkeys.imageio.ImageReaderBase;
|
||||||
|
import org.w3c.dom.NodeList;
|
||||||
|
|
||||||
|
import javax.imageio.IIOImage;
|
||||||
|
import javax.imageio.ImageIO;
|
||||||
|
import javax.imageio.ImageReader;
|
||||||
|
import javax.imageio.metadata.IIOMetadata;
|
||||||
|
import javax.imageio.metadata.IIOMetadataFormatImpl;
|
||||||
|
import javax.imageio.metadata.IIOMetadataNode;
|
||||||
|
import javax.imageio.stream.ImageInputStream;
|
||||||
|
import java.awt.image.BufferedImage;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.util.Iterator;
|
||||||
|
|
||||||
|
import static com.twelvemonkeys.contrib.tiff.TIFFUtilities.applyOrientation;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* EXIFUtilities.
|
||||||
|
*
|
||||||
|
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||||
|
* @version : EXIFUtilities.java,v 1.0 23/06/2020
|
||||||
|
*/
|
||||||
|
public class EXIFUtilities {
|
||||||
|
/**
|
||||||
|
* Reads image and metadata, applies Exif orientation to image, and returns everything as an {@code IIOImage}.
|
||||||
|
*
|
||||||
|
* @param input a {@code URL}
|
||||||
|
* @return an {@code IIOImage} containing the correctly oriented image and metadata including rotation info.
|
||||||
|
* @throws IOException if an error occurs during reading.
|
||||||
|
*/
|
||||||
|
public static IIOImage readWithOrientation(final URL input) throws IOException {
|
||||||
|
try (ImageInputStream stream = ImageIO.createImageInputStream(input)) {
|
||||||
|
return readWithOrientation(stream);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads image and metadata, applies Exif orientation to image, and returns everything as an {@code IIOImage}.
|
||||||
|
*
|
||||||
|
* @param input an {@code InputStream}
|
||||||
|
* @return an {@code IIOImage} containing the correctly oriented image and metadata including rotation info.
|
||||||
|
* @throws IOException if an error occurs during reading.
|
||||||
|
*/
|
||||||
|
public static IIOImage readWithOrientation(final InputStream input) throws IOException {
|
||||||
|
try (ImageInputStream stream = ImageIO.createImageInputStream(input)) {
|
||||||
|
return readWithOrientation(stream);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads image and metadata, applies Exif orientation to image, and returns everything as an {@code IIOImage}.
|
||||||
|
*
|
||||||
|
* @param input a {@code File}
|
||||||
|
* @return an {@code IIOImage} containing the correctly oriented image and metadata including rotation info.
|
||||||
|
* @throws IOException if an error occurs during reading.
|
||||||
|
*/
|
||||||
|
public static IIOImage readWithOrientation(final File input) throws IOException {
|
||||||
|
try (ImageInputStream stream = ImageIO.createImageInputStream(input)) {
|
||||||
|
return readWithOrientation(stream);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads image and metadata, applies Exif orientation to image, and returns everything as an {@code IIOImage}.
|
||||||
|
*
|
||||||
|
* @param input an {@code ImageInputStream}
|
||||||
|
* @return an {@code IIOImage} containing the correctly oriented image and metadata including rotation info.
|
||||||
|
* @throws IOException if an error occurs during reading.
|
||||||
|
*/
|
||||||
|
public static IIOImage readWithOrientation(final ImageInputStream input) throws IOException {
|
||||||
|
Iterator<ImageReader> readers = ImageIO.getImageReaders(input);
|
||||||
|
if (!readers.hasNext()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
ImageReader reader = readers.next();
|
||||||
|
try {
|
||||||
|
reader.setInput(input, true, false);
|
||||||
|
IIOImage image = reader.readAll(0, reader.getDefaultReadParam());
|
||||||
|
|
||||||
|
BufferedImage bufferedImage = ImageUtil.toBuffered(image.getRenderedImage());
|
||||||
|
image.setRenderedImage(applyOrientation(bufferedImage, findImageOrientation(image.getMetadata()).value()));
|
||||||
|
|
||||||
|
return image;
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
reader.dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finds the {@code ImageOrientation} tag, if any, and returns an {@link Orientation} based on its
|
||||||
|
* {@code value} attribute.
|
||||||
|
* If no match is found or the tag is not present, {@code Normal} (the default orientation) is returned.
|
||||||
|
*
|
||||||
|
* @param metadata an {@code IIOMetadata} object
|
||||||
|
* @return the {@code Orientation} matching the {@code value} attribute of the {@code ImageOrientation} tag,
|
||||||
|
* or {@code Normal}, never {@code null}.
|
||||||
|
* @see Orientation
|
||||||
|
* @see <a href="https://docs.oracle.com/javase/7/docs/api/javax/imageio/metadata/doc-files/standard_metadata.html">Standard (Plug-in Neutral) Metadata Format Specification</a>
|
||||||
|
*/
|
||||||
|
public static Orientation findImageOrientation(final IIOMetadata metadata) {
|
||||||
|
if (metadata != null) {
|
||||||
|
IIOMetadataNode root = (IIOMetadataNode) metadata.getAsTree(IIOMetadataFormatImpl.standardMetadataFormatName);
|
||||||
|
NodeList imageOrientations = root.getElementsByTagName("ImageOrientation");
|
||||||
|
|
||||||
|
if (imageOrientations != null && imageOrientations.getLength() > 0) {
|
||||||
|
IIOMetadataNode imageOrientation = (IIOMetadataNode) imageOrientations.item(0);
|
||||||
|
return Orientation.fromMetadataOrientation(imageOrientation.getAttribute("value"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Orientation.Normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args) throws IOException {
|
||||||
|
for (String arg : args) {
|
||||||
|
File input = new File(arg);
|
||||||
|
|
||||||
|
// Read everything (similar to ImageReader.readAll(0, null)), but applies the correct image orientation
|
||||||
|
IIOImage image = readWithOrientation(input);
|
||||||
|
|
||||||
|
// Finds the orientation as defined by the javax_imageio_1.0 format
|
||||||
|
Orientation orientation = findImageOrientation(image.getMetadata());
|
||||||
|
|
||||||
|
// Retrieve the image as a BufferedImage. The image is already rotated by the readWithOrientation method
|
||||||
|
// In this case it will already be a BufferedImage, so using a cast will also do
|
||||||
|
// (i.e.: BufferedImage bufferedImage = (BufferedImage) image.getRenderedImage())
|
||||||
|
BufferedImage bufferedImage = ImageUtil.toBuffered(image.getRenderedImage());
|
||||||
|
|
||||||
|
// Demo purpose only, show image with orientation details in title
|
||||||
|
DisplayHelper.showIt(bufferedImage, input.getName() + ": " + orientation.name() + "/" + orientation.value());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Don't do this... :-) Provided for convenience/demo only!
|
||||||
|
static abstract class DisplayHelper extends ImageReaderBase {
|
||||||
|
private DisplayHelper() {
|
||||||
|
super(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static void showIt(BufferedImage image, String title) {
|
||||||
|
ImageReaderBase.showIt(image, title);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,63 @@
|
|||||||
|
package com.twelvemonkeys.contrib.exif;
|
||||||
|
|
||||||
|
import com.twelvemonkeys.contrib.tiff.TIFFUtilities;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Orientation.
|
||||||
|
*
|
||||||
|
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||||
|
* @version : Orientation.java,v 1.0 10/07/2020 harald.kuhr
|
||||||
|
*/
|
||||||
|
public enum Orientation {
|
||||||
|
Normal(TIFFUtilities.TIFFBaseline.ORIENTATION_TOPLEFT),
|
||||||
|
FlipH(TIFFUtilities.TIFFExtension.ORIENTATION_TOPRIGHT),
|
||||||
|
Rotate180(TIFFUtilities.TIFFExtension.ORIENTATION_BOTRIGHT),
|
||||||
|
FlipV(TIFFUtilities.TIFFExtension.ORIENTATION_BOTLEFT),
|
||||||
|
FlipVRotate90(TIFFUtilities.TIFFExtension.ORIENTATION_LEFTTOP),
|
||||||
|
Rotate270(TIFFUtilities.TIFFExtension.ORIENTATION_RIGHTTOP),
|
||||||
|
FlipHRotate90(TIFFUtilities.TIFFExtension.ORIENTATION_RIGHTBOT),
|
||||||
|
Rotate90(TIFFUtilities.TIFFExtension.ORIENTATION_LEFTBOT);
|
||||||
|
|
||||||
|
// name as defined in javax.imageio metadata
|
||||||
|
private final int value; // value as defined in TIFF spec
|
||||||
|
|
||||||
|
Orientation(int value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int value() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Orientation fromMetadataOrientation(final String orientationName) {
|
||||||
|
if (orientationName != null) {
|
||||||
|
try {
|
||||||
|
return valueOf(orientationName);
|
||||||
|
}
|
||||||
|
catch (IllegalArgumentException e) {
|
||||||
|
// Not found, try ignore case match, as some metadata implementations are known to return "normal" etc.
|
||||||
|
String lowerCaseName = orientationName.toLowerCase();
|
||||||
|
|
||||||
|
for (Orientation orientation : values()) {
|
||||||
|
if (orientation.name().toLowerCase().equals(lowerCaseName)) {
|
||||||
|
return orientation;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Metadata does not have other orientations, default to Normal
|
||||||
|
return Normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Orientation fromTIFFOrientation(final int tiffOrientation) {
|
||||||
|
for (Orientation orientation : values()) {
|
||||||
|
if (orientation.value() == tiffOrientation) {
|
||||||
|
return orientation;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// No other TIFF orientations possible, default to Normal
|
||||||
|
return Normal;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -200,11 +200,10 @@ public final class TIFFUtilities {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static List<TIFFPage> getPages(ImageInputStream imageInput) throws IOException {
|
public static List<TIFFPage> getPages(ImageInputStream imageInput) throws IOException {
|
||||||
ArrayList<TIFFPage> pages = new ArrayList<TIFFPage>();
|
|
||||||
|
|
||||||
CompoundDirectory IFDs = (CompoundDirectory) new TIFFReader().read(imageInput);
|
CompoundDirectory IFDs = (CompoundDirectory) new TIFFReader().read(imageInput);
|
||||||
|
|
||||||
int pageCount = IFDs.directoryCount();
|
final int pageCount = IFDs.directoryCount();
|
||||||
|
List<TIFFPage> pages = new ArrayList<>(pageCount);
|
||||||
for (int pageIndex = 0; pageIndex < pageCount; pageIndex++) {
|
for (int pageIndex = 0; pageIndex < pageCount; pageIndex++) {
|
||||||
pages.add(new TIFFPage(IFDs.getDirectory(pageIndex), imageInput));
|
pages.add(new TIFFPage(IFDs.getDirectory(pageIndex), imageInput));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,75 @@
|
|||||||
|
package com.twelvemonkeys.contrib.exif;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import static com.twelvemonkeys.contrib.exif.Orientation.*;
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* OrientationTest.
|
||||||
|
*
|
||||||
|
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||||
|
* @author last modified by : harald.kuhr$
|
||||||
|
* @version : OrientationTest.java,v 1.0 10/07/2020 harald.kuhr Exp$
|
||||||
|
*/
|
||||||
|
public class OrientationTest {
|
||||||
|
@Test
|
||||||
|
public void testFromMetadataOrientationNull() {
|
||||||
|
assertEquals(Normal, Orientation.fromMetadataOrientation(null));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testFromMetadataOrientation() {
|
||||||
|
assertEquals(Normal, Orientation.fromMetadataOrientation("Normal"));
|
||||||
|
assertEquals(Rotate90, Orientation.fromMetadataOrientation("Rotate90"));
|
||||||
|
assertEquals(Rotate180, Orientation.fromMetadataOrientation("Rotate180"));
|
||||||
|
assertEquals(Rotate270, Orientation.fromMetadataOrientation("Rotate270"));
|
||||||
|
assertEquals(FlipH, Orientation.fromMetadataOrientation("FlipH"));
|
||||||
|
assertEquals(FlipV, Orientation.fromMetadataOrientation("FlipV"));
|
||||||
|
assertEquals(FlipHRotate90, Orientation.fromMetadataOrientation("FlipHRotate90"));
|
||||||
|
assertEquals(FlipVRotate90, Orientation.fromMetadataOrientation("FlipVRotate90"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testFromMetadataOrientationIgnoreCase() {
|
||||||
|
assertEquals(Normal, Orientation.fromMetadataOrientation("normal"));
|
||||||
|
assertEquals(Rotate90, Orientation.fromMetadataOrientation("rotate90"));
|
||||||
|
assertEquals(Rotate180, Orientation.fromMetadataOrientation("ROTATE180"));
|
||||||
|
assertEquals(Rotate270, Orientation.fromMetadataOrientation("ROTATE270"));
|
||||||
|
assertEquals(FlipH, Orientation.fromMetadataOrientation("FLIPH"));
|
||||||
|
assertEquals(FlipV, Orientation.fromMetadataOrientation("flipv"));
|
||||||
|
assertEquals(FlipHRotate90, Orientation.fromMetadataOrientation("FLIPhrotate90"));
|
||||||
|
assertEquals(FlipVRotate90, Orientation.fromMetadataOrientation("fLiPVRotAte90"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testFromMetadataOrientationUnknown() {
|
||||||
|
assertEquals(Normal, Orientation.fromMetadataOrientation("foo"));
|
||||||
|
assertEquals(Normal, Orientation.fromMetadataOrientation("90"));
|
||||||
|
assertEquals(Normal, Orientation.fromMetadataOrientation("randomStringWithNumbers180"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testFromTIFFOrientation() {
|
||||||
|
assertEquals(Normal, Orientation.fromTIFFOrientation(1));
|
||||||
|
assertEquals(FlipH, Orientation.fromTIFFOrientation(2));
|
||||||
|
assertEquals(Rotate180, Orientation.fromTIFFOrientation(3));
|
||||||
|
assertEquals(FlipV, Orientation.fromTIFFOrientation(4));
|
||||||
|
assertEquals(FlipVRotate90, Orientation.fromTIFFOrientation(5));
|
||||||
|
assertEquals(Rotate270, Orientation.fromTIFFOrientation(6));
|
||||||
|
assertEquals(FlipHRotate90, Orientation.fromTIFFOrientation(7));
|
||||||
|
assertEquals(Rotate90, Orientation.fromTIFFOrientation(8));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testFromTIFFOrientationUnknown() {
|
||||||
|
assertEquals(Normal, Orientation.fromTIFFOrientation(-1));
|
||||||
|
assertEquals(Normal, Orientation.fromTIFFOrientation(0));
|
||||||
|
assertEquals(Normal, Orientation.fromTIFFOrientation(9));
|
||||||
|
for (int i = 10; i < 1024; i++) {
|
||||||
|
assertEquals(Normal, Orientation.fromTIFFOrientation(i));
|
||||||
|
}
|
||||||
|
assertEquals(Normal, Orientation.fromTIFFOrientation(Integer.MAX_VALUE));
|
||||||
|
assertEquals(Normal, Orientation.fromTIFFOrientation(Integer.MIN_VALUE));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,7 +4,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>com.twelvemonkeys.imageio</groupId>
|
<groupId>com.twelvemonkeys.imageio</groupId>
|
||||||
<artifactId>imageio</artifactId>
|
<artifactId>imageio</artifactId>
|
||||||
<version>3.5</version>
|
<version>3.6.2</version>
|
||||||
</parent>
|
</parent>
|
||||||
<artifactId>imageio-batik</artifactId>
|
<artifactId>imageio-batik</artifactId>
|
||||||
<name>TwelveMonkeys :: ImageIO :: Batik Plugin</name>
|
<name>TwelveMonkeys :: ImageIO :: Batik Plugin</name>
|
||||||
@@ -14,6 +14,21 @@
|
|||||||
See the <a href="http://xmlgraphics.apache.org/batik/">Batik Home page</a>
|
See the <a href="http://xmlgraphics.apache.org/batik/">Batik Home page</a>
|
||||||
for more information.]]>
|
for more information.]]>
|
||||||
</description>
|
</description>
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-surefire-plugin</artifactId>
|
||||||
|
<configuration>
|
||||||
|
<systemPropertyVariables>
|
||||||
|
<com.twelvemonkeys.imageio.plugins.svg.allowexternalresources>
|
||||||
|
true
|
||||||
|
</com.twelvemonkeys.imageio.plugins.svg.allowexternalresources>
|
||||||
|
</systemPropertyVariables>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<dependency>
|
<dependency>
|
||||||
@@ -24,6 +39,7 @@
|
|||||||
<groupId>com.twelvemonkeys.imageio</groupId>
|
<groupId>com.twelvemonkeys.imageio</groupId>
|
||||||
<artifactId>imageio-core</artifactId>
|
<artifactId>imageio-core</artifactId>
|
||||||
<type>test-jar</type>
|
<type>test-jar</type>
|
||||||
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
@@ -88,6 +104,6 @@
|
|||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<batik.version>1.9</batik.version>
|
<batik.version>1.12</batik.version>
|
||||||
</properties>
|
</properties>
|
||||||
</project>
|
</project>
|
||||||
|
|||||||
@@ -33,9 +33,11 @@ package com.twelvemonkeys.imageio.plugins.svg;
|
|||||||
import com.twelvemonkeys.image.ImageUtil;
|
import com.twelvemonkeys.image.ImageUtil;
|
||||||
import com.twelvemonkeys.imageio.ImageReaderBase;
|
import com.twelvemonkeys.imageio.ImageReaderBase;
|
||||||
import com.twelvemonkeys.imageio.util.IIOUtil;
|
import com.twelvemonkeys.imageio.util.IIOUtil;
|
||||||
|
import com.twelvemonkeys.lang.StringUtil;
|
||||||
import org.apache.batik.anim.dom.SVGDOMImplementation;
|
import org.apache.batik.anim.dom.SVGDOMImplementation;
|
||||||
import org.apache.batik.anim.dom.SVGOMDocument;
|
import org.apache.batik.anim.dom.SVGOMDocument;
|
||||||
import org.apache.batik.bridge.*;
|
import org.apache.batik.bridge.*;
|
||||||
|
import org.apache.batik.css.parser.CSSLexicalUnit;
|
||||||
import org.apache.batik.dom.util.DOMUtilities;
|
import org.apache.batik.dom.util.DOMUtilities;
|
||||||
import org.apache.batik.ext.awt.image.GraphicsUtil;
|
import org.apache.batik.ext.awt.image.GraphicsUtil;
|
||||||
import org.apache.batik.gvt.CanvasGraphicsNode;
|
import org.apache.batik.gvt.CanvasGraphicsNode;
|
||||||
@@ -47,6 +49,7 @@ import org.apache.batik.transcoder.*;
|
|||||||
import org.apache.batik.transcoder.image.ImageTranscoder;
|
import org.apache.batik.transcoder.image.ImageTranscoder;
|
||||||
import org.apache.batik.util.ParsedURL;
|
import org.apache.batik.util.ParsedURL;
|
||||||
import org.apache.batik.util.SVGConstants;
|
import org.apache.batik.util.SVGConstants;
|
||||||
|
import org.apache.batik.xml.LexicalUnits;
|
||||||
import org.w3c.dom.DOMImplementation;
|
import org.w3c.dom.DOMImplementation;
|
||||||
import org.w3c.dom.Document;
|
import org.w3c.dom.Document;
|
||||||
import org.w3c.dom.svg.SVGSVGElement;
|
import org.w3c.dom.svg.SVGSVGElement;
|
||||||
@@ -76,7 +79,12 @@ import java.util.Map;
|
|||||||
* @see <A href="http://www.mail-archive.com/batik-dev@xml.apache.org/msg00992.html">batik-dev</A>
|
* @see <A href="http://www.mail-archive.com/batik-dev@xml.apache.org/msg00992.html">batik-dev</A>
|
||||||
*/
|
*/
|
||||||
public class SVGImageReader extends ImageReaderBase {
|
public class SVGImageReader extends ImageReaderBase {
|
||||||
|
|
||||||
|
final static boolean DEFAULT_ALLOW_EXTERNAL_RESOURCES =
|
||||||
|
"true".equalsIgnoreCase(System.getProperty("com.twelvemonkeys.imageio.plugins.svg.allowexternalresources"));
|
||||||
|
|
||||||
private Rasterizer rasterizer;
|
private Rasterizer rasterizer;
|
||||||
|
private boolean allowExternalResources = DEFAULT_ALLOW_EXTERNAL_RESOURCES;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates an {@code SVGImageReader}.
|
* Creates an {@code SVGImageReader}.
|
||||||
@@ -113,6 +121,9 @@ public class SVGImageReader extends ImageReaderBase {
|
|||||||
if (pParam instanceof SVGReadParam) {
|
if (pParam instanceof SVGReadParam) {
|
||||||
SVGReadParam svgParam = (SVGReadParam) pParam;
|
SVGReadParam svgParam = (SVGReadParam) pParam;
|
||||||
|
|
||||||
|
// set the external-resource-resolution preference
|
||||||
|
allowExternalResources = svgParam.isAllowExternalResources();
|
||||||
|
|
||||||
// Get the base URI
|
// Get the base URI
|
||||||
// This must be done before converting the params to hints
|
// This must be done before converting the params to hints
|
||||||
String baseURI = svgParam.getBaseURI();
|
String baseURI = svgParam.getBaseURI();
|
||||||
@@ -324,24 +335,54 @@ public class SVGImageReader extends ImageReaderBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ----
|
// ----
|
||||||
|
SVGSVGElement rootElement = svgDoc.getRootElement();
|
||||||
|
|
||||||
// get the 'width' and 'height' attributes of the SVG document
|
// get the 'width' and 'height' attributes of the SVG document
|
||||||
Dimension2D docSize = ctx.getDocumentSize();
|
UnitProcessor.Context uctx
|
||||||
if (docSize != null) {
|
= UnitProcessor.createContext(ctx, rootElement);
|
||||||
defaultWidth = (float) docSize.getWidth();
|
String widthStr = rootElement.getAttributeNS(null, SVGConstants.SVG_WIDTH_ATTRIBUTE);
|
||||||
defaultHeight = (float) docSize.getHeight();
|
String heightStr = rootElement.getAttributeNS(null, SVGConstants.SVG_HEIGHT_ATTRIBUTE);
|
||||||
|
if (!StringUtil.isEmpty(widthStr)) {
|
||||||
|
defaultWidth = UnitProcessor.svgToUserSpace(widthStr, SVGConstants.SVG_WIDTH_ATTRIBUTE, UnitProcessor.HORIZONTAL_LENGTH, uctx);
|
||||||
}
|
}
|
||||||
else {
|
if(!StringUtil.isEmpty(heightStr)){
|
||||||
defaultWidth = 200;
|
defaultHeight = UnitProcessor.svgToUserSpace(heightStr, SVGConstants.SVG_HEIGHT_ATTRIBUTE, UnitProcessor.VERTICAL_LENGTH, uctx);
|
||||||
defaultHeight = 200;
|
|
||||||
}
|
}
|
||||||
SVGSVGElement rootElement = svgDoc.getRootElement();
|
|
||||||
String viewBoxStr = rootElement.getAttributeNS
|
boolean hasWidth = defaultWidth > 0.0;
|
||||||
(null, SVGConstants.SVG_VIEW_BOX_ATTRIBUTE);
|
boolean hasHeight = defaultHeight > 0.0;
|
||||||
if (viewBoxStr.length() != 0) {
|
|
||||||
float[] rect = ViewBox.parseViewBoxAttribute(rootElement, viewBoxStr, null);
|
if (!hasWidth || !hasHeight) {
|
||||||
defaultWidth = rect[2];
|
String viewBoxStr = rootElement.getAttributeNS
|
||||||
defaultHeight = rect[3];
|
(null, SVGConstants.SVG_VIEW_BOX_ATTRIBUTE);
|
||||||
|
if (viewBoxStr.length() != 0) {
|
||||||
|
float[] rect = ViewBox.parseViewBoxAttribute(rootElement, viewBoxStr, null);
|
||||||
|
// if one dimension is given, calculate other by aspect ratio in viewBox
|
||||||
|
// or use viewBox if no dimension is given
|
||||||
|
if (hasWidth) {
|
||||||
|
defaultHeight = defaultWidth * rect[3] / rect[2];
|
||||||
|
}
|
||||||
|
else if (hasHeight) {
|
||||||
|
defaultWidth = defaultHeight * rect[2] / rect[3];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
defaultWidth = rect[2];
|
||||||
|
defaultHeight = rect[3];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (hasHeight) {
|
||||||
|
defaultWidth = defaultHeight;
|
||||||
|
}
|
||||||
|
else if (hasWidth) {
|
||||||
|
defaultHeight = defaultWidth;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// fallback to batik default sizes
|
||||||
|
defaultWidth = 400;
|
||||||
|
defaultHeight = 400;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hack to work around exception above
|
// Hack to work around exception above
|
||||||
@@ -608,6 +649,14 @@ public class SVGImageReader extends ImageReaderBase {
|
|||||||
public void displayMessage(String message) {
|
public void displayMessage(String message) {
|
||||||
processWarningOccurred(message.replaceAll("[\\r\\n]+", " "));
|
processWarningOccurred(message.replaceAll("[\\r\\n]+", " "));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ExternalResourceSecurity getExternalResourceSecurity(ParsedURL resourceURL, ParsedURL docURL) {
|
||||||
|
if (allowExternalResources) {
|
||||||
|
return super.getExternalResourceSecurity(resourceURL, docURL);
|
||||||
|
}
|
||||||
|
return new NoLoadExternalResourceSecurity();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,6 +41,11 @@ import java.awt.*;
|
|||||||
public class SVGReadParam extends ImageReadParam {
|
public class SVGReadParam extends ImageReadParam {
|
||||||
private Paint background;
|
private Paint background;
|
||||||
private String baseURI;
|
private String baseURI;
|
||||||
|
private boolean allowExternalResources = SVGImageReader.DEFAULT_ALLOW_EXTERNAL_RESOURCES;
|
||||||
|
|
||||||
|
public SVGReadParam() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
public Paint getBackgroundColor() {
|
public Paint getBackgroundColor() {
|
||||||
return background;
|
return background;
|
||||||
@@ -58,6 +63,14 @@ public class SVGReadParam extends ImageReadParam {
|
|||||||
baseURI = pBaseURI;
|
baseURI = pBaseURI;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setAllowExternalResources(boolean allow) {
|
||||||
|
allowExternalResources = allow;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isAllowExternalResources() {
|
||||||
|
return allowExternalResources;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean canSetSourceRenderSize() {
|
public boolean canSetSourceRenderSize() {
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -31,6 +31,7 @@
|
|||||||
package com.twelvemonkeys.imageio.plugins.svg;
|
package com.twelvemonkeys.imageio.plugins.svg;
|
||||||
|
|
||||||
import com.twelvemonkeys.imageio.util.ImageReaderAbstractTest;
|
import com.twelvemonkeys.imageio.util.ImageReaderAbstractTest;
|
||||||
|
|
||||||
import org.junit.Ignore;
|
import org.junit.Ignore;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
@@ -44,12 +45,10 @@ import javax.imageio.stream.ImageInputStream;
|
|||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.awt.image.BufferedImage;
|
import java.awt.image.BufferedImage;
|
||||||
import java.awt.image.ImagingOpException;
|
import java.awt.image.ImagingOpException;
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.net.URISyntaxException;
|
import java.net.URISyntaxException;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.nio.Buffer;
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -67,30 +66,25 @@ import static org.mockito.Mockito.*;
|
|||||||
* @version $Id: SVGImageReaderTest.java,v 1.0 Apr 1, 2008 10:39:17 PM haraldk Exp$
|
* @version $Id: SVGImageReaderTest.java,v 1.0 Apr 1, 2008 10:39:17 PM haraldk Exp$
|
||||||
*/
|
*/
|
||||||
public class SVGImageReaderTest extends ImageReaderAbstractTest<SVGImageReader> {
|
public class SVGImageReaderTest extends ImageReaderAbstractTest<SVGImageReader> {
|
||||||
private SVGImageReaderSpi provider = new SVGImageReaderSpi();
|
|
||||||
|
@Override
|
||||||
|
protected ImageReaderSpi createProvider() {
|
||||||
|
return new SVGImageReaderSpi();
|
||||||
|
}
|
||||||
|
|
||||||
protected List<TestData> getTestData() {
|
protected List<TestData> getTestData() {
|
||||||
return Arrays.asList(
|
return Arrays.asList(
|
||||||
new TestData(getClassLoaderResource("/svg/batikLogo.svg"), new Dimension(450, 500)),
|
new TestData(getClassLoaderResource("/svg/batikLogo.svg"), new Dimension(450, 500)),
|
||||||
new TestData(getClassLoaderResource("/svg/red-square.svg"), new Dimension(100, 100)),
|
new TestData(getClassLoaderResource("/svg/red-square.svg"), new Dimension(100, 100)),
|
||||||
new TestData(getClassLoaderResource("/svg/blue-square.svg"), new Dimension(100, 100)),
|
new TestData(getClassLoaderResource("/svg/blue-square.svg"), new Dimension(100, 100)),
|
||||||
new TestData(getClassLoaderResource("/svg/Android_robot.svg"), new Dimension(294, 345))
|
new TestData(getClassLoaderResource("/svg/Android_robot.svg"), new Dimension(294, 345)),
|
||||||
|
new TestData(getClassLoaderResource("/svg/sizes/w50h50.svg"), new Dimension(50, 50)),
|
||||||
|
new TestData(getClassLoaderResource("/svg/sizes/w50_1to2.svg"), new Dimension(25, 50)),
|
||||||
|
new TestData(getClassLoaderResource("/svg/sizes/h50_1to2.svg"), new Dimension(50, 100)),
|
||||||
|
new TestData(getClassLoaderResource("/svg/sizes/w50noview.svg"), new Dimension(50, 50))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected ImageReaderSpi createProvider() {
|
|
||||||
return provider;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected SVGImageReader createReader() {
|
|
||||||
return new SVGImageReader(createProvider());
|
|
||||||
}
|
|
||||||
|
|
||||||
protected Class<SVGImageReader> getReaderClass() {
|
|
||||||
return SVGImageReader.class;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected List<String> getFormatNames() {
|
protected List<String> getFormatNames() {
|
||||||
return Collections.singletonList("svg");
|
return Collections.singletonList("svg");
|
||||||
}
|
}
|
||||||
@@ -107,8 +101,6 @@ public class SVGImageReaderTest extends ImageReaderAbstractTest<SVGImageReader>
|
|||||||
public void testScaleViewBox() throws IOException {
|
public void testScaleViewBox() throws IOException {
|
||||||
URL svgUrl = getClassLoaderResource("/svg/quadrants.svg");
|
URL svgUrl = getClassLoaderResource("/svg/quadrants.svg");
|
||||||
|
|
||||||
File tmpDir = new File(System.getProperty("java.io.tmpdir"));
|
|
||||||
|
|
||||||
SVGImageReader reader = createReader();
|
SVGImageReader reader = createReader();
|
||||||
SVGReadParam param = new SVGReadParam();
|
SVGReadParam param = new SVGReadParam();
|
||||||
|
|
||||||
@@ -156,11 +148,11 @@ public class SVGImageReaderTest extends ImageReaderAbstractTest<SVGImageReader>
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Override
|
@Override
|
||||||
public void testReadWithSizeParam() {
|
public void testReadWithSizeParam() throws IOException {
|
||||||
try {
|
try {
|
||||||
super.testReadWithSizeParam();
|
super.testReadWithSizeParam();
|
||||||
}
|
}
|
||||||
catch (AssertionError failure) {
|
catch (AssertionError | IOException failure) {
|
||||||
Throwable cause = failure;
|
Throwable cause = failure;
|
||||||
|
|
||||||
while (cause.getCause() != null) {
|
while (cause.getCause() != null) {
|
||||||
@@ -224,6 +216,7 @@ public class SVGImageReaderTest extends ImageReaderAbstractTest<SVGImageReader>
|
|||||||
reader.addIIOReadWarningListener(listener);
|
reader.addIIOReadWarningListener(listener);
|
||||||
|
|
||||||
SVGReadParam param = reader.getDefaultReadParam();
|
SVGReadParam param = reader.getDefaultReadParam();
|
||||||
|
param.setAllowExternalResources(true);
|
||||||
param.setBaseURI(resource.toURI().toASCIIString());
|
param.setBaseURI(resource.toURI().toASCIIString());
|
||||||
BufferedImage image = reader.read(0, param);
|
BufferedImage image = reader.read(0, param);
|
||||||
|
|
||||||
@@ -244,6 +237,8 @@ public class SVGImageReaderTest extends ImageReaderAbstractTest<SVGImageReader>
|
|||||||
// Asking for metadata, width, height etc, before attempting to read using a param,
|
// Asking for metadata, width, height etc, before attempting to read using a param,
|
||||||
// will cause the document to be parsed without a base URI.
|
// will cause the document to be parsed without a base URI.
|
||||||
// This will work, but may not use the CSS...
|
// This will work, but may not use the CSS...
|
||||||
|
// since the param is not available before the read operation is invoked,
|
||||||
|
// this test-case MUST use the system-property for backwards compatibility
|
||||||
URL resource = getClassLoaderResource("/svg/barChart.svg");
|
URL resource = getClassLoaderResource("/svg/barChart.svg");
|
||||||
|
|
||||||
SVGImageReader reader = createReader();
|
SVGImageReader reader = createReader();
|
||||||
@@ -282,18 +277,17 @@ public class SVGImageReaderTest extends ImageReaderAbstractTest<SVGImageReader>
|
|||||||
public void testEmbeddedNoBaseURI() throws IOException {
|
public void testEmbeddedNoBaseURI() throws IOException {
|
||||||
// With no base URI, we will throw an exception, about the missing embedded resource
|
// With no base URI, we will throw an exception, about the missing embedded resource
|
||||||
URL resource = getClassLoaderResource("/svg/barChart.svg");
|
URL resource = getClassLoaderResource("/svg/barChart.svg");
|
||||||
|
|
||||||
SVGImageReader reader = createReader();
|
SVGImageReader reader = createReader();
|
||||||
|
|
||||||
TestData data = new TestData(resource, (Dimension) null);
|
TestData data = new TestData(resource, (Dimension) null);
|
||||||
try (ImageInputStream stream = data.getInputStream()) {
|
try (ImageInputStream stream = data.getInputStream()) {
|
||||||
reader.setInput(stream);
|
reader.setInput(stream);
|
||||||
|
|
||||||
BufferedImage image = reader.read(0);
|
SVGReadParam params = reader.getDefaultReadParam();
|
||||||
|
params.setAllowExternalResources(true);
|
||||||
|
reader.read(0, params);
|
||||||
|
|
||||||
assertNotNull(image);
|
fail("reader.read should've thrown an exception, but didn't");
|
||||||
assertEquals(450, image.getWidth());
|
|
||||||
assertEquals(500, image.getHeight());
|
|
||||||
}
|
}
|
||||||
catch (IIOException allowed) {
|
catch (IIOException allowed) {
|
||||||
assertTrue(allowed.getMessage().contains("batikLogo.svg")); // The embedded resource we don't find
|
assertTrue(allowed.getMessage().contains("batikLogo.svg")); // The embedded resource we don't find
|
||||||
@@ -302,4 +296,28 @@ public class SVGImageReaderTest extends ImageReaderAbstractTest<SVGImageReader>
|
|||||||
reader.dispose();
|
reader.dispose();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
@Test(expected = SecurityException.class)
|
||||||
|
public void testDisallowedExternalResources() throws URISyntaxException, IOException {
|
||||||
|
// system-property set to true in surefire-plugin-settings in the pom
|
||||||
|
URL resource = getClassLoaderResource("/svg/barChart.svg");
|
||||||
|
SVGImageReader reader = createReader();
|
||||||
|
|
||||||
|
TestData data = new TestData(resource, (Dimension) null);
|
||||||
|
try (ImageInputStream stream = data.getInputStream()) {
|
||||||
|
reader.setInput(stream);
|
||||||
|
|
||||||
|
SVGReadParam param = reader.getDefaultReadParam();
|
||||||
|
param.setBaseURI(resource.toURI().toASCIIString());
|
||||||
|
param.setAllowExternalResources(false);
|
||||||
|
// even when the system-property is set to true,
|
||||||
|
// `reader.read` for `/svg/barChart.svg` should raise
|
||||||
|
// a SecurityException when External Resources are blocked
|
||||||
|
// because the API invocation gets preference
|
||||||
|
reader.read(0, param);
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
reader.dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -31,6 +31,7 @@
|
|||||||
package com.twelvemonkeys.imageio.plugins.wmf;
|
package com.twelvemonkeys.imageio.plugins.wmf;
|
||||||
|
|
||||||
import com.twelvemonkeys.imageio.util.ImageReaderAbstractTest;
|
import com.twelvemonkeys.imageio.util.ImageReaderAbstractTest;
|
||||||
|
|
||||||
import org.junit.Ignore;
|
import org.junit.Ignore;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
@@ -49,7 +50,10 @@ import java.util.List;
|
|||||||
* @version $Id: WMFImageReaderTest.java,v 1.0 Apr 1, 2008 10:39:17 PM haraldk Exp$
|
* @version $Id: WMFImageReaderTest.java,v 1.0 Apr 1, 2008 10:39:17 PM haraldk Exp$
|
||||||
*/
|
*/
|
||||||
public class WMFImageReaderTest extends ImageReaderAbstractTest<WMFImageReader> {
|
public class WMFImageReaderTest extends ImageReaderAbstractTest<WMFImageReader> {
|
||||||
private WMFImageReaderSpi provider = new WMFImageReaderSpi();
|
@Override
|
||||||
|
protected ImageReaderSpi createProvider() {
|
||||||
|
return new WMFImageReaderSpi();
|
||||||
|
}
|
||||||
|
|
||||||
protected List<TestData> getTestData() {
|
protected List<TestData> getTestData() {
|
||||||
return Collections.singletonList(
|
return Collections.singletonList(
|
||||||
@@ -57,27 +61,17 @@ public class WMFImageReaderTest extends ImageReaderAbstractTest<WMFImageReader>
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected ImageReaderSpi createProvider() {
|
|
||||||
return provider;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected WMFImageReader createReader() {
|
|
||||||
return new WMFImageReader(createProvider());
|
|
||||||
}
|
|
||||||
|
|
||||||
protected Class<WMFImageReader> getReaderClass() {
|
|
||||||
return WMFImageReader.class;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected List<String> getFormatNames() {
|
protected List<String> getFormatNames() {
|
||||||
return Collections.singletonList("wmf");
|
return Collections.singletonList("wmf");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
protected List<String> getSuffixes() {
|
protected List<String> getSuffixes() {
|
||||||
return Arrays.asList("wmf", "emf");
|
return Arrays.asList("wmf", "emf");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
protected List<String> getMIMETypes() {
|
protected List<String> getMIMETypes() {
|
||||||
return Arrays.asList("image/x-wmf", "application/x-msmetafile");
|
return Arrays.asList("image/x-wmf", "application/x-msmetafile");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="50" viewBox="0 0 100 200" version="1.1">
|
||||||
|
<g id="layer1">
|
||||||
|
<rect id="rect2985" width="50" height="50" x="0" y="0"
|
||||||
|
style="color:#000000;fill:#0000ff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 427 B |
@@ -0,0 +1,7 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" height="50" viewBox="0 0 100 200" version="1.1">
|
||||||
|
<g id="layer1">
|
||||||
|
<rect id="rect2985" width="50" height="50" x="0" y="0"
|
||||||
|
style="color:#000000;fill:#0000ff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 428 B |
@@ -0,0 +1,7 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="50" height="50" viewBox="0 0 100 200" version="1.1">
|
||||||
|
<g id="layer1">
|
||||||
|
<rect id="rect2985" width="50" height="50" x="0" y="0"
|
||||||
|
style="color:#000000;fill:#0000ff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 439 B |
@@ -0,0 +1,7 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="50" version="1.1">
|
||||||
|
<g id="layer1">
|
||||||
|
<rect id="rect2985" width="50" height="50" x="0" y="0"
|
||||||
|
style="color:#000000;fill:#0000ff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 405 B |
@@ -4,7 +4,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>com.twelvemonkeys.imageio</groupId>
|
<groupId>com.twelvemonkeys.imageio</groupId>
|
||||||
<artifactId>imageio</artifactId>
|
<artifactId>imageio</artifactId>
|
||||||
<version>3.5</version>
|
<version>3.6.2</version>
|
||||||
</parent>
|
</parent>
|
||||||
<artifactId>imageio-bmp</artifactId>
|
<artifactId>imageio-bmp</artifactId>
|
||||||
<name>TwelveMonkeys :: ImageIO :: BMP plugin</name>
|
<name>TwelveMonkeys :: ImageIO :: BMP plugin</name>
|
||||||
@@ -19,6 +19,7 @@
|
|||||||
<groupId>com.twelvemonkeys.imageio</groupId>
|
<groupId>com.twelvemonkeys.imageio</groupId>
|
||||||
<artifactId>imageio-core</artifactId>
|
<artifactId>imageio-core</artifactId>
|
||||||
<type>test-jar</type>
|
<type>test-jar</type>
|
||||||
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
</project>
|
</project>
|
||||||
|
|||||||
@@ -30,22 +30,6 @@
|
|||||||
|
|
||||||
package com.twelvemonkeys.imageio.plugins.bmp;
|
package com.twelvemonkeys.imageio.plugins.bmp;
|
||||||
|
|
||||||
import com.twelvemonkeys.imageio.ImageReaderBase;
|
|
||||||
import com.twelvemonkeys.imageio.stream.SubImageInputStream;
|
|
||||||
import com.twelvemonkeys.imageio.util.IIOUtil;
|
|
||||||
import com.twelvemonkeys.imageio.util.ImageTypeSpecifiers;
|
|
||||||
import com.twelvemonkeys.imageio.util.ProgressListenerBase;
|
|
||||||
import com.twelvemonkeys.io.LittleEndianDataInputStream;
|
|
||||||
import com.twelvemonkeys.io.enc.DecoderStream;
|
|
||||||
import com.twelvemonkeys.xml.XMLSerializer;
|
|
||||||
|
|
||||||
import javax.imageio.*;
|
|
||||||
import javax.imageio.event.IIOReadUpdateListener;
|
|
||||||
import javax.imageio.event.IIOReadWarningListener;
|
|
||||||
import javax.imageio.metadata.IIOMetadata;
|
|
||||||
import javax.imageio.metadata.IIOMetadataFormatImpl;
|
|
||||||
import javax.imageio.spi.ImageReaderSpi;
|
|
||||||
import javax.imageio.stream.ImageInputStream;
|
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.awt.color.ColorSpace;
|
import java.awt.color.ColorSpace;
|
||||||
import java.awt.image.*;
|
import java.awt.image.*;
|
||||||
@@ -56,6 +40,27 @@ import java.nio.ByteOrder;
|
|||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
|
||||||
|
import javax.imageio.IIOException;
|
||||||
|
import javax.imageio.ImageIO;
|
||||||
|
import javax.imageio.ImageReadParam;
|
||||||
|
import javax.imageio.ImageReader;
|
||||||
|
import javax.imageio.ImageTypeSpecifier;
|
||||||
|
import javax.imageio.event.IIOReadUpdateListener;
|
||||||
|
import javax.imageio.event.IIOReadWarningListener;
|
||||||
|
import javax.imageio.metadata.IIOMetadata;
|
||||||
|
import javax.imageio.metadata.IIOMetadataFormatImpl;
|
||||||
|
import javax.imageio.spi.ImageReaderSpi;
|
||||||
|
import javax.imageio.stream.ImageInputStream;
|
||||||
|
|
||||||
|
import com.twelvemonkeys.imageio.ImageReaderBase;
|
||||||
|
import com.twelvemonkeys.imageio.stream.SubImageInputStream;
|
||||||
|
import com.twelvemonkeys.imageio.util.IIOUtil;
|
||||||
|
import com.twelvemonkeys.imageio.util.ImageTypeSpecifiers;
|
||||||
|
import com.twelvemonkeys.imageio.util.ProgressListenerBase;
|
||||||
|
import com.twelvemonkeys.io.LittleEndianDataInputStream;
|
||||||
|
import com.twelvemonkeys.io.enc.DecoderStream;
|
||||||
|
import com.twelvemonkeys.xml.XMLSerializer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ImageReader for Microsoft Windows Bitmap (BMP) format.
|
* ImageReader for Microsoft Windows Bitmap (BMP) format.
|
||||||
*
|
*
|
||||||
@@ -125,6 +130,10 @@ public final class BMPImageReader extends ImageReaderBase {
|
|||||||
|
|
||||||
// Read DIB header
|
// Read DIB header
|
||||||
header = DIBHeader.read(imageInput);
|
header = DIBHeader.read(imageInput);
|
||||||
|
|
||||||
|
if (pixelOffset < header.size + DIB.BMP_FILE_HEADER_SIZE) {
|
||||||
|
throw new IIOException("Invalid pixel offset: " + pixelOffset);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -207,50 +216,55 @@ public final class BMPImageReader extends ImageReaderBase {
|
|||||||
throw new IIOException("Multiple planes not supported");
|
throw new IIOException("Multiple planes not supported");
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (header.getBitCount()) {
|
try {
|
||||||
case 1:
|
switch (header.getBitCount()) {
|
||||||
case 2:
|
case 1:
|
||||||
case 4:
|
case 2:
|
||||||
case 8:
|
case 4:
|
||||||
return ImageTypeSpecifiers.createFromIndexColorModel(readColorMap());
|
case 8:
|
||||||
|
return ImageTypeSpecifiers.createFromIndexColorModel(readColorMap());
|
||||||
|
|
||||||
case 16:
|
case 16:
|
||||||
if (header.hasMasks()) {
|
if (header.hasMasks()) {
|
||||||
return ImageTypeSpecifiers.createPacked(
|
return ImageTypeSpecifiers.createPacked(
|
||||||
ColorSpace.getInstance(ColorSpace.CS_sRGB),
|
ColorSpace.getInstance(ColorSpace.CS_sRGB),
|
||||||
header.masks[0], header.masks[1], header.masks[2], header.masks[3],
|
header.masks[0], header.masks[1], header.masks[2], header.masks[3],
|
||||||
DataBuffer.TYPE_USHORT, false
|
DataBuffer.TYPE_USHORT, false
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Default if no mask is 555
|
// Default if no mask is 555
|
||||||
return ImageTypeSpecifiers.createFromBufferedImageType(BufferedImage.TYPE_USHORT_555_RGB);
|
return ImageTypeSpecifiers.createFromBufferedImageType(BufferedImage.TYPE_USHORT_555_RGB);
|
||||||
|
|
||||||
case 24:
|
case 24:
|
||||||
if (header.getCompression() != DIB.COMPRESSION_RGB) {
|
if (header.getCompression() != DIB.COMPRESSION_RGB) {
|
||||||
throw new IIOException("Unsupported compression for RGB: " + header.getCompression());
|
throw new IIOException("Unsupported compression for RGB: " + header.getCompression());
|
||||||
}
|
}
|
||||||
|
|
||||||
return ImageTypeSpecifiers.createFromBufferedImageType(BufferedImage.TYPE_3BYTE_BGR);
|
return ImageTypeSpecifiers.createFromBufferedImageType(BufferedImage.TYPE_3BYTE_BGR);
|
||||||
|
|
||||||
case 32:
|
case 32:
|
||||||
if (header.hasMasks()) {
|
if (header.hasMasks()) {
|
||||||
return ImageTypeSpecifiers.createPacked(
|
return ImageTypeSpecifiers.createPacked(
|
||||||
ColorSpace.getInstance(ColorSpace.CS_sRGB),
|
ColorSpace.getInstance(ColorSpace.CS_sRGB),
|
||||||
header.masks[0], header.masks[1], header.masks[2], header.masks[3],
|
header.masks[0], header.masks[1], header.masks[2], header.masks[3],
|
||||||
DataBuffer.TYPE_INT, false
|
DataBuffer.TYPE_INT, false
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Default if no mask
|
// Default if no mask
|
||||||
return ImageTypeSpecifiers.createFromBufferedImageType(BufferedImage.TYPE_INT_RGB);
|
return ImageTypeSpecifiers.createFromBufferedImageType(BufferedImage.TYPE_INT_RGB);
|
||||||
|
|
||||||
case 0:
|
case 0:
|
||||||
if (header.getCompression() == DIB.COMPRESSION_JPEG || header.getCompression() == DIB.COMPRESSION_PNG) {
|
if (header.getCompression() == DIB.COMPRESSION_JPEG || header.getCompression() == DIB.COMPRESSION_PNG) {
|
||||||
return initReaderDelegate(header.getCompression()).getRawImageType(0);
|
return initReaderDelegate(header.getCompression()).getRawImageType(0);
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
throw new IIOException("Unsupported bit count: " + header.getBitCount());
|
throw new IIOException("Unsupported bit count: " + header.getBitCount());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (IllegalArgumentException e) {
|
||||||
|
throw new IIOException(e.getMessage(), e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -33,9 +33,13 @@ package com.twelvemonkeys.imageio.plugins.bmp;
|
|||||||
import com.twelvemonkeys.imageio.spi.ImageWriterSpiBase;
|
import com.twelvemonkeys.imageio.spi.ImageWriterSpiBase;
|
||||||
|
|
||||||
import javax.imageio.ImageTypeSpecifier;
|
import javax.imageio.ImageTypeSpecifier;
|
||||||
import java.io.IOException;
|
import javax.imageio.spi.ImageWriterSpi;
|
||||||
|
import javax.imageio.spi.ServiceRegistry;
|
||||||
|
import java.awt.image.BufferedImage;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
|
||||||
|
import static com.twelvemonkeys.imageio.util.IIOUtil.lookupProviderByName;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* BMPImageWriterSpi
|
* BMPImageWriterSpi
|
||||||
*/
|
*/
|
||||||
@@ -45,17 +49,28 @@ public final class BMPImageWriterSpi extends ImageWriterSpiBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean canEncodeImage(final ImageTypeSpecifier type) {
|
public void onRegistration(ServiceRegistry registry, Class<?> category) {
|
||||||
return true;
|
// Make sure we register BEHIND the built-in BMP writer
|
||||||
|
ImageWriterSpi sunSpi = lookupProviderByName(registry, "com.sun.imageio.plugins.bmp.BMPImageWriterSpi", ImageWriterSpi.class);
|
||||||
|
|
||||||
|
if (sunSpi != null && sunSpi.getVendorName() != null) {
|
||||||
|
registry.setOrdering((Class<ImageWriterSpi>) category, sunSpi, this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BMPImageWriter createWriterInstance(final Object extension) throws IOException {
|
public boolean canEncodeImage(final ImageTypeSpecifier type) {
|
||||||
|
// TODO: Support more types, as time permits.
|
||||||
|
return type.getBufferedImageType() == BufferedImage.TYPE_4BYTE_ABGR;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BMPImageWriter createWriterInstance(final Object extension) {
|
||||||
return new BMPImageWriter(this);
|
return new BMPImageWriter(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getDescription(final Locale locale) {
|
public String getDescription(final Locale locale) {
|
||||||
return "Windows Device Independent Bitmap Format (BMP) Reader";
|
return "Windows Device Independent Bitmap Format (BMP) Writer";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ import javax.imageio.metadata.IIOMetadataNode;
|
|||||||
* BMPMetadata.
|
* BMPMetadata.
|
||||||
*/
|
*/
|
||||||
final class BMPMetadata extends AbstractMetadata {
|
final class BMPMetadata extends AbstractMetadata {
|
||||||
/** We return metadata in the exact same form as the JRE built-in, to be compatible with the DIBImageWriter. */
|
/** We return metadata in the exact same form as the JRE built-in, to be compatible with the BMPImageWriter. */
|
||||||
public static final String nativeMetadataFormatName = "javax_imageio_bmp_1.0";
|
public static final String nativeMetadataFormatName = "javax_imageio_bmp_1.0";
|
||||||
|
|
||||||
private final DIBHeader header;
|
private final DIBHeader header;
|
||||||
|
|||||||
@@ -29,9 +29,10 @@
|
|||||||
*/
|
*/
|
||||||
package com.twelvemonkeys.imageio.plugins.bmp;
|
package com.twelvemonkeys.imageio.plugins.bmp;
|
||||||
|
|
||||||
import com.twelvemonkeys.lang.Validate;
|
import static com.twelvemonkeys.lang.Validate.notNull;
|
||||||
|
|
||||||
import java.awt.image.BufferedImage;
|
import java.awt.image.BufferedImage;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Describes a bitmap structure.
|
* Describes a bitmap structure.
|
||||||
@@ -47,14 +48,11 @@ abstract class BitmapDescriptor {
|
|||||||
protected BitmapMask mask;
|
protected BitmapMask mask;
|
||||||
|
|
||||||
public BitmapDescriptor(final DirectoryEntry pEntry, final DIBHeader pHeader) {
|
public BitmapDescriptor(final DirectoryEntry pEntry, final DIBHeader pHeader) {
|
||||||
Validate.notNull(pEntry, "entry");
|
entry = notNull(pEntry, "entry");;
|
||||||
Validate.notNull(pHeader, "header");
|
header = notNull(pHeader, "header");
|
||||||
|
|
||||||
entry = pEntry;
|
|
||||||
header = pHeader;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract public BufferedImage getImage();
|
abstract public BufferedImage getImage() throws IOException;
|
||||||
|
|
||||||
public final int getWidth() {
|
public final int getWidth() {
|
||||||
return entry.getWidth();
|
return entry.getWidth();
|
||||||
|
|||||||
@@ -163,6 +163,7 @@ class BitmapIndexed extends BitmapDescriptor {
|
|||||||
return transparent;
|
return transparent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public BufferedImage getImage() {
|
public BufferedImage getImage() {
|
||||||
if (image == null) {
|
if (image == null) {
|
||||||
image = createImageIndexed();
|
image = createImageIndexed();
|
||||||
|
|||||||
@@ -46,6 +46,7 @@ class BitmapRGB extends BitmapDescriptor {
|
|||||||
super(pEntry, pHeader);
|
super(pEntry, pHeader);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public BufferedImage getImage() {
|
public BufferedImage getImage() {
|
||||||
// Test is mask != null rather than hasMask(), as 32 bit (w/alpha)
|
// Test is mask != null rather than hasMask(), as 32 bit (w/alpha)
|
||||||
// might still have bitmask, but we don't read or use it.
|
// might still have bitmask, but we don't read or use it.
|
||||||
|
|||||||
@@ -31,6 +31,9 @@
|
|||||||
package com.twelvemonkeys.imageio.plugins.bmp;
|
package com.twelvemonkeys.imageio.plugins.bmp;
|
||||||
|
|
||||||
import java.awt.image.BufferedImage;
|
import java.awt.image.BufferedImage;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import javax.imageio.IIOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents bitmap structures we can't read.
|
* Represents bitmap structures we can't read.
|
||||||
@@ -42,13 +45,14 @@ import java.awt.image.BufferedImage;
|
|||||||
class BitmapUnsupported extends BitmapDescriptor {
|
class BitmapUnsupported extends BitmapDescriptor {
|
||||||
private String message;
|
private String message;
|
||||||
|
|
||||||
public BitmapUnsupported(final DirectoryEntry pEntry, final String pMessage) {
|
public BitmapUnsupported(final DirectoryEntry pEntry, DIBHeader header, final String pMessage) {
|
||||||
super(pEntry, null);
|
super(pEntry, header);
|
||||||
|
|
||||||
message = pMessage;
|
message = pMessage;
|
||||||
}
|
}
|
||||||
|
|
||||||
public BufferedImage getImage() {
|
@Override
|
||||||
throw new IllegalStateException(message);
|
public BufferedImage getImage() throws IOException {
|
||||||
|
throw new IIOException(message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,11 +30,12 @@
|
|||||||
|
|
||||||
package com.twelvemonkeys.imageio.plugins.bmp;
|
package com.twelvemonkeys.imageio.plugins.bmp;
|
||||||
|
|
||||||
import javax.imageio.IIOException;
|
|
||||||
import java.io.DataInput;
|
import java.io.DataInput;
|
||||||
import java.io.DataOutput;
|
import java.io.DataOutput;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import javax.imageio.IIOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents the DIB (Device Independent Bitmap) Information header structure.
|
* Represents the DIB (Device Independent Bitmap) Information header structure.
|
||||||
*
|
*
|
||||||
@@ -213,7 +214,7 @@ abstract class DIBHeader {
|
|||||||
|
|
||||||
// NOTE: Unlike all other headers, width and height are unsigned SHORT values (16 bit)!
|
// NOTE: Unlike all other headers, width and height are unsigned SHORT values (16 bit)!
|
||||||
width = pStream.readUnsignedShort();
|
width = pStream.readUnsignedShort();
|
||||||
height = pStream.readUnsignedShort();
|
height = pStream.readShort();
|
||||||
|
|
||||||
if (height < 0) {
|
if (height < 0) {
|
||||||
height = -height;
|
height = -height;
|
||||||
@@ -240,6 +241,7 @@ abstract class DIBHeader {
|
|||||||
* @see <a href="http://www.fileformat.info/format/os2bmp/egff.htm">OS/2 Bitmap File Format Summary</a>
|
* @see <a href="http://www.fileformat.info/format/os2bmp/egff.htm">OS/2 Bitmap File Format Summary</a>
|
||||||
*/
|
*/
|
||||||
static final class BitmapCoreHeaderV2 extends DIBHeader {
|
static final class BitmapCoreHeaderV2 extends DIBHeader {
|
||||||
|
@SuppressWarnings("unused")
|
||||||
protected void read(final int pSize, final DataInput pStream) throws IOException {
|
protected void read(final int pSize, final DataInput pStream) throws IOException {
|
||||||
if (pSize != DIB.OS2_V2_HEADER_SIZE && pSize != DIB.OS2_V2_HEADER_16_SIZE) {
|
if (pSize != DIB.OS2_V2_HEADER_SIZE && pSize != DIB.OS2_V2_HEADER_16_SIZE) {
|
||||||
throw new IIOException(String.format("Size: %s !=: %s", pSize, DIB.OS2_V2_HEADER_SIZE));
|
throw new IIOException(String.format("Size: %s !=: %s", pSize, DIB.OS2_V2_HEADER_SIZE));
|
||||||
|
|||||||
@@ -30,16 +30,6 @@
|
|||||||
|
|
||||||
package com.twelvemonkeys.imageio.plugins.bmp;
|
package com.twelvemonkeys.imageio.plugins.bmp;
|
||||||
|
|
||||||
import com.twelvemonkeys.image.ImageUtil;
|
|
||||||
import com.twelvemonkeys.imageio.ImageReaderBase;
|
|
||||||
import com.twelvemonkeys.imageio.stream.SubImageInputStream;
|
|
||||||
import com.twelvemonkeys.imageio.util.ImageTypeSpecifiers;
|
|
||||||
import com.twelvemonkeys.util.WeakWeakMap;
|
|
||||||
|
|
||||||
import javax.imageio.*;
|
|
||||||
import javax.imageio.spi.ImageReaderSpi;
|
|
||||||
import javax.imageio.stream.ImageInputStream;
|
|
||||||
import javax.swing.*;
|
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.awt.color.ColorSpace;
|
import java.awt.color.ColorSpace;
|
||||||
import java.awt.event.WindowAdapter;
|
import java.awt.event.WindowAdapter;
|
||||||
@@ -48,8 +38,26 @@ import java.awt.image.*;
|
|||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.ByteOrder;
|
import java.nio.ByteOrder;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.*;
|
import java.util.Map;
|
||||||
|
import java.util.WeakHashMap;
|
||||||
|
|
||||||
|
import javax.imageio.IIOException;
|
||||||
|
import javax.imageio.ImageIO;
|
||||||
|
import javax.imageio.ImageReadParam;
|
||||||
|
import javax.imageio.ImageReader;
|
||||||
|
import javax.imageio.ImageTypeSpecifier;
|
||||||
|
import javax.imageio.spi.ImageReaderSpi;
|
||||||
|
import javax.imageio.stream.ImageInputStream;
|
||||||
|
import javax.swing.*;
|
||||||
|
|
||||||
|
import com.twelvemonkeys.image.ImageUtil;
|
||||||
|
import com.twelvemonkeys.imageio.ImageReaderBase;
|
||||||
|
import com.twelvemonkeys.imageio.stream.SubImageInputStream;
|
||||||
|
import com.twelvemonkeys.imageio.util.ImageTypeSpecifiers;
|
||||||
|
import com.twelvemonkeys.util.WeakWeakMap;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ImageReader for Microsoft Windows ICO (icon) format.
|
* ImageReader for Microsoft Windows ICO (icon) format.
|
||||||
@@ -84,7 +92,7 @@ abstract class DIBImageReader extends ImageReaderBase {
|
|||||||
|
|
||||||
protected void resetMembers() {
|
protected void resetMembers() {
|
||||||
directory = null;
|
directory = null;
|
||||||
|
|
||||||
headers.clear();
|
headers.clear();
|
||||||
descriptors.clear();
|
descriptors.clear();
|
||||||
|
|
||||||
@@ -287,7 +295,7 @@ abstract class DIBImageReader extends ImageReaderBase {
|
|||||||
|
|
||||||
// TODO: Support this, it's already in the BMP reader, spec allows RLE4 and RLE8
|
// TODO: Support this, it's already in the BMP reader, spec allows RLE4 and RLE8
|
||||||
if (header.getCompression() != DIB.COMPRESSION_RGB) {
|
if (header.getCompression() != DIB.COMPRESSION_RGB) {
|
||||||
descriptor = new BitmapUnsupported(pEntry, String.format("Unsupported compression: %d", header.getCompression()));
|
descriptor = new BitmapUnsupported(pEntry, header, String.format("Unsupported compression: %d", header.getCompression()));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
int bitCount = header.getBitCount();
|
int bitCount = header.getBitCount();
|
||||||
@@ -315,7 +323,7 @@ abstract class DIBImageReader extends ImageReaderBase {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
descriptor = new BitmapUnsupported(pEntry, String.format("Unsupported bit count %d", bitCount));
|
descriptor = new BitmapUnsupported(pEntry, header, String.format("Unsupported bit count %d", bitCount));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -355,7 +363,7 @@ abstract class DIBImageReader extends ImageReaderBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void readBitmapIndexed1(final BitmapIndexed pBitmap, final boolean pAsMask) throws IOException {
|
private void readBitmapIndexed1(final BitmapIndexed pBitmap, final boolean pAsMask) throws IOException {
|
||||||
int width = adjustToPadding(pBitmap.getWidth() >> 3);
|
int width = adjustToPadding((pBitmap.getWidth() + 7) >> 3);
|
||||||
byte[] row = new byte[width];
|
byte[] row = new byte[width];
|
||||||
|
|
||||||
for (int y = 0; y < pBitmap.getHeight(); y++) {
|
for (int y = 0; y < pBitmap.getHeight(); y++) {
|
||||||
@@ -389,7 +397,7 @@ abstract class DIBImageReader extends ImageReaderBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void readBitmapIndexed4(final BitmapIndexed pBitmap) throws IOException {
|
private void readBitmapIndexed4(final BitmapIndexed pBitmap) throws IOException {
|
||||||
int width = adjustToPadding(pBitmap.getWidth() >> 1);
|
int width = adjustToPadding((pBitmap.getWidth() + 1) >> 1);
|
||||||
byte[] row = new byte[width];
|
byte[] row = new byte[width];
|
||||||
|
|
||||||
for (int y = 0; y < pBitmap.getHeight(); y++) {
|
for (int y = 0; y < pBitmap.getHeight(); y++) {
|
||||||
@@ -457,13 +465,12 @@ abstract class DIBImageReader extends ImageReaderBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void readBitmap16(final BitmapDescriptor pBitmap) throws IOException {
|
private void readBitmap16(final BitmapDescriptor pBitmap) throws IOException {
|
||||||
// TODO: No idea if this actually works..
|
|
||||||
short[] pixels = new short[pBitmap.getWidth() * pBitmap.getHeight()];
|
short[] pixels = new short[pBitmap.getWidth() * pBitmap.getHeight()];
|
||||||
|
|
||||||
// TODO: Support TYPE_USHORT_565 and the RGB 444/ARGB 4444 layouts
|
// TODO: Support TYPE_USHORT_565 and the RGB 444/ARGB 4444 layouts
|
||||||
// Will create TYPE_USHORT_555
|
// Will create TYPE_USHORT_555
|
||||||
DirectColorModel cm = new DirectColorModel(16, 0x7C00, 0x03E0, 0x001F);
|
DirectColorModel cm = new DirectColorModel(16, 0x7C00, 0x03E0, 0x001F);
|
||||||
DataBuffer buffer = new DataBufferShort(pixels, pixels.length);
|
DataBuffer buffer = new DataBufferUShort(pixels, pixels.length);
|
||||||
WritableRaster raster = Raster.createPackedRaster(
|
WritableRaster raster = Raster.createPackedRaster(
|
||||||
buffer, pBitmap.getWidth(), pBitmap.getHeight(), pBitmap.getWidth(), cm.getMasks(), null
|
buffer, pBitmap.getWidth(), pBitmap.getHeight(), pBitmap.getWidth(), cm.getMasks(), null
|
||||||
);
|
);
|
||||||
@@ -551,7 +558,7 @@ abstract class DIBImageReader extends ImageReaderBase {
|
|||||||
if (abortRequested()) {
|
if (abortRequested()) {
|
||||||
processReadAborted();
|
processReadAborted();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
processImageProgress(100 * y / (float) pBitmap.getHeight());
|
processImageProgress(100 * y / (float) pBitmap.getHeight());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -591,7 +598,7 @@ abstract class DIBImageReader extends ImageReaderBase {
|
|||||||
|
|
||||||
return directory.getEntry(pImageIndex);
|
return directory.getEntry(pImageIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Test code below, ignore.. :-)
|
/// Test code below, ignore.. :-)
|
||||||
public static void main(final String[] pArgs) throws IOException {
|
public static void main(final String[] pArgs) throws IOException {
|
||||||
if (pArgs.length == 0) {
|
if (pArgs.length == 0) {
|
||||||
@@ -701,10 +708,10 @@ abstract class DIBImageReader extends ImageReaderBase {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
button.setText("" + image.getWidth() + "x" +
|
button.setText(image.getWidth() + "x" +
|
||||||
image.getHeight() + ": "
|
image.getHeight() + ": "
|
||||||
+ ((image.getColorModel() instanceof IndexColorModel) ?
|
+ ((image.getColorModel() instanceof IndexColorModel) ?
|
||||||
"" + ((IndexColorModel) image.getColorModel()).getMapSize() :
|
String.valueOf(((IndexColorModel) image.getColorModel()).getMapSize()) :
|
||||||
"TrueColor"));
|
"TrueColor"));
|
||||||
|
|
||||||
pParent.add(button);
|
pParent.add(button);
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ import java.nio.ByteOrder;
|
|||||||
* DIBImageWriter
|
* DIBImageWriter
|
||||||
*/
|
*/
|
||||||
abstract class DIBImageWriter extends ImageWriterBase {
|
abstract class DIBImageWriter extends ImageWriterBase {
|
||||||
|
|
||||||
DIBImageWriter(ImageWriterSpi provider) {
|
DIBImageWriter(ImageWriterSpi provider) {
|
||||||
super(provider);
|
super(provider);
|
||||||
}
|
}
|
||||||
@@ -50,7 +51,9 @@ abstract class DIBImageWriter extends ImageWriterBase {
|
|||||||
@Override
|
@Override
|
||||||
public void setOutput(Object output) {
|
public void setOutput(Object output) {
|
||||||
super.setOutput(output);
|
super.setOutput(output);
|
||||||
imageOutput.setByteOrder(ByteOrder.LITTLE_ENDIAN);
|
if (imageOutput != null) {
|
||||||
|
imageOutput.setByteOrder(ByteOrder.LITTLE_ENDIAN);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void writeDIBHeader(int infoHeaderSize, int width, int height, boolean isTopDown, int pixelSize, int compression) throws IOException {
|
void writeDIBHeader(int infoHeaderSize, int width, int height, boolean isTopDown, int pixelSize, int compression) throws IOException {
|
||||||
@@ -82,9 +85,8 @@ abstract class DIBImageWriter extends ImageWriterBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void writeUncompressed(boolean isTopDown, BufferedImage img, int height, int width) throws IOException {
|
void writeUncompressed(boolean isTopDown, BufferedImage img, int height, int width) throws IOException {
|
||||||
// TODO: Fix
|
|
||||||
if (img.getType() != BufferedImage.TYPE_4BYTE_ABGR) {
|
if (img.getType() != BufferedImage.TYPE_4BYTE_ABGR) {
|
||||||
throw new IIOException("Blows!");
|
throw new IIOException("Only TYPE_4BYTE_ABGR supported");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Support
|
// Support
|
||||||
@@ -93,12 +95,13 @@ abstract class DIBImageWriter extends ImageWriterBase {
|
|||||||
// - TODO: Packed/DirectColorModel (16 and 32 bit, BI_BITFIELDS, BI_PNG? BI_JPEG?)
|
// - TODO: Packed/DirectColorModel (16 and 32 bit, BI_BITFIELDS, BI_PNG? BI_JPEG?)
|
||||||
|
|
||||||
Raster raster = img.getRaster();
|
Raster raster = img.getRaster();
|
||||||
WritableRaster rowRaster = Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE, width, 1, width * 4, 4, new int[]{2, 1, 0, 3}, null);
|
WritableRaster rowRaster = Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE, width, 1, width * 4, 4, new int[] {2, 1, 0, 3}, null);
|
||||||
byte[] row = ((DataBufferByte) rowRaster.getDataBuffer()).getData();
|
byte[] row = ((DataBufferByte) rowRaster.getDataBuffer()).getData();
|
||||||
|
final int[] bandList = {2, 1, 0, 3};
|
||||||
|
|
||||||
for (int i = 0; i < height; i++) {
|
for (int i = 0; i < height; i++) {
|
||||||
int line = isTopDown ? i : height - 1 - i;
|
int line = isTopDown ? i : height - 1 - i;
|
||||||
rowRaster.setDataElements(0, 0, raster.createChild(0, line, width, 1, 0, 0, new int[]{2, 1, 0, 3}));
|
rowRaster.setDataElements(0, 0, raster.createChild(0, line, width, 1, 0, 0, bandList));
|
||||||
|
|
||||||
imageOutput.write(row);
|
imageOutput.write(row);
|
||||||
|
|
||||||
|
|||||||
@@ -143,7 +143,7 @@ public final class ICOImageWriter extends DIBImageWriter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (image.hasRaster()) {
|
if (image.hasRaster()) {
|
||||||
throw new UnsupportedOperationException("image has a Raster");
|
throw new UnsupportedOperationException("Raster not supported");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sequenceIndex >= INITIAL_ENTRY_COUNT) {
|
if (sequenceIndex >= INITIAL_ENTRY_COUNT) {
|
||||||
@@ -155,7 +155,7 @@ public final class ICOImageWriter extends DIBImageWriter {
|
|||||||
ColorModel colorModel = image.getRenderedImage().getColorModel();
|
ColorModel colorModel = image.getRenderedImage().getColorModel();
|
||||||
|
|
||||||
// TODO: The output size may depend on the param (subsampling, source region, etc)
|
// TODO: The output size may depend on the param (subsampling, source region, etc)
|
||||||
if (width > ICO_MAX_DIMENSION && height > ICO_MAX_DIMENSION) {
|
if (width > ICO_MAX_DIMENSION || height > ICO_MAX_DIMENSION) {
|
||||||
throw new IIOException(String.format("ICO maximum width or height (%d) exceeded", ICO_MAX_DIMENSION));
|
throw new IIOException(String.format("ICO maximum width or height (%d) exceeded", ICO_MAX_DIMENSION));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ package com.twelvemonkeys.imageio.plugins.bmp;
|
|||||||
import com.twelvemonkeys.imageio.spi.ImageWriterSpiBase;
|
import com.twelvemonkeys.imageio.spi.ImageWriterSpiBase;
|
||||||
|
|
||||||
import javax.imageio.ImageTypeSpecifier;
|
import javax.imageio.ImageTypeSpecifier;
|
||||||
import java.io.IOException;
|
import java.awt.image.BufferedImage;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -46,11 +46,13 @@ public final class ICOImageWriterSpi extends ImageWriterSpiBase {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean canEncodeImage(final ImageTypeSpecifier type) {
|
public boolean canEncodeImage(final ImageTypeSpecifier type) {
|
||||||
return true;
|
// TODO: Support more types, as time permits.
|
||||||
|
// NOTE: We do support more types, if writing using PNG compression
|
||||||
|
return type.getBufferedImageType() == BufferedImage.TYPE_4BYTE_ABGR;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ICOImageWriter createWriterInstance(final Object extension) throws IOException {
|
public ICOImageWriter createWriterInstance(final Object extension) {
|
||||||
return new ICOImageWriter(this);
|
return new ICOImageWriter(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -41,8 +41,8 @@ import java.util.Arrays;
|
|||||||
* @version $Id: RLE4Decoder.java#1 $
|
* @version $Id: RLE4Decoder.java#1 $
|
||||||
*/
|
*/
|
||||||
final class RLE4Decoder extends AbstractRLEDecoder {
|
final class RLE4Decoder extends AbstractRLEDecoder {
|
||||||
final static int BIT_MASKS[] = {0xf0, 0x0f};
|
final static int[] BIT_MASKS = {0xf0, 0x0f};
|
||||||
final static int BIT_SHIFTS[] = {4, 0};
|
final static int[] BIT_SHIFTS = {4, 0};
|
||||||
|
|
||||||
public RLE4Decoder(final int width) {
|
public RLE4Decoder(final int width) {
|
||||||
super(width, 4);
|
super(width, 4);
|
||||||
@@ -94,7 +94,7 @@ final class RLE4Decoder extends AbstractRLEDecoder {
|
|||||||
boolean paddingByte = (((byte2 + 1) / 2) % 2) != 0;
|
boolean paddingByte = (((byte2 + 1) / 2) % 2) != 0;
|
||||||
|
|
||||||
int packed = 0;
|
int packed = 0;
|
||||||
for (int i = 0; i < byte2; i++) {
|
for (int i = 0; i < byte2 && srcX / 2 < row.length; i++) {
|
||||||
if (i % 2 == 0) {
|
if (i % 2 == 0) {
|
||||||
packed = checkEOF(stream.read());
|
packed = checkEOF(stream.read());
|
||||||
}
|
}
|
||||||
@@ -111,7 +111,7 @@ final class RLE4Decoder extends AbstractRLEDecoder {
|
|||||||
else {
|
else {
|
||||||
// Encoded mode
|
// Encoded mode
|
||||||
// Replicate the two samples in byte2 as many times as byte1 says
|
// Replicate the two samples in byte2 as many times as byte1 says
|
||||||
for (int i = 0; i < byte1; i++) {
|
for (int i = 0; i < byte1 && srcX / 2 < row.length; i++) {
|
||||||
row[srcX / 2] |= (byte) (((byte2 & BIT_MASKS[i % 2]) >> BIT_SHIFTS[i % 2]) << BIT_SHIFTS[srcX % 2]);
|
row[srcX / 2] |= (byte) (((byte2 & BIT_MASKS[i % 2]) >> BIT_SHIFTS[i % 2]) << BIT_SHIFTS[srcX % 2]);
|
||||||
srcX++;
|
srcX++;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -94,7 +94,7 @@ final class RLE8Decoder extends AbstractRLEDecoder {
|
|||||||
// an additional padding byte is in the stream and must be skipped
|
// an additional padding byte is in the stream and must be skipped
|
||||||
boolean paddingByte = (byte2 % 2) != 0;
|
boolean paddingByte = (byte2 % 2) != 0;
|
||||||
|
|
||||||
while (byte2-- > 0) {
|
while (byte2-- > 0 && srcX < row.length) {
|
||||||
row[srcX++] = (byte) checkEOF(stream.read());
|
row[srcX++] = (byte) checkEOF(stream.read());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -107,7 +107,7 @@ final class RLE8Decoder extends AbstractRLEDecoder {
|
|||||||
// Encoded mode
|
// Encoded mode
|
||||||
// Replicate byte2 as many times as byte1 says
|
// Replicate byte2 as many times as byte1 says
|
||||||
byte value = (byte) byte2;
|
byte value = (byte) byte2;
|
||||||
while (byte1-- > 0) {
|
while (byte1-- > 0 && srcX < row.length) {
|
||||||
row[srcX++] = value;
|
row[srcX++] = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,35 +30,43 @@
|
|||||||
|
|
||||||
package com.twelvemonkeys.imageio.plugins.bmp;
|
package com.twelvemonkeys.imageio.plugins.bmp;
|
||||||
|
|
||||||
import com.twelvemonkeys.imageio.util.ImageReaderAbstractTest;
|
import static org.junit.Assert.*;
|
||||||
import com.twelvemonkeys.xml.XMLSerializer;
|
import static org.junit.Assume.assumeNoException;
|
||||||
|
import static org.mockito.Matchers.anyInt;
|
||||||
|
import static org.mockito.Matchers.eq;
|
||||||
|
import static org.mockito.Mockito.atLeastOnce;
|
||||||
|
import static org.mockito.Mockito.inOrder;
|
||||||
|
import static org.mockito.Mockito.mock;
|
||||||
|
|
||||||
|
import java.awt.*;
|
||||||
|
import java.awt.image.BufferedImage;
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.lang.reflect.Constructor;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import javax.imageio.IIOException;
|
||||||
|
import javax.imageio.ImageIO;
|
||||||
|
import javax.imageio.ImageReadParam;
|
||||||
|
import javax.imageio.ImageReader;
|
||||||
|
import javax.imageio.ImageTypeSpecifier;
|
||||||
|
import javax.imageio.event.IIOReadProgressListener;
|
||||||
|
import javax.imageio.metadata.IIOMetadata;
|
||||||
|
import javax.imageio.metadata.IIOMetadataNode;
|
||||||
|
import javax.imageio.spi.ImageReaderSpi;
|
||||||
|
|
||||||
import org.junit.Ignore;
|
import org.junit.Ignore;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.mockito.InOrder;
|
import org.mockito.InOrder;
|
||||||
import org.w3c.dom.Node;
|
import org.w3c.dom.Node;
|
||||||
import org.w3c.dom.NodeList;
|
import org.w3c.dom.NodeList;
|
||||||
|
|
||||||
import javax.imageio.*;
|
import com.twelvemonkeys.imageio.util.ImageReaderAbstractTest;
|
||||||
import javax.imageio.event.IIOReadProgressListener;
|
import com.twelvemonkeys.xml.XMLSerializer;
|
||||||
import javax.imageio.metadata.IIOMetadata;
|
|
||||||
import javax.imageio.metadata.IIOMetadataNode;
|
|
||||||
import javax.imageio.spi.ImageReaderSpi;
|
|
||||||
import java.awt.*;
|
|
||||||
import java.awt.image.BufferedImage;
|
|
||||||
import java.io.ByteArrayOutputStream;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.lang.reflect.Constructor;
|
|
||||||
import java.net.URISyntaxException;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import static org.junit.Assert.*;
|
|
||||||
import static org.junit.Assume.assumeNoException;
|
|
||||||
import static org.mockito.Matchers.anyInt;
|
|
||||||
import static org.mockito.Matchers.eq;
|
|
||||||
import static org.mockito.Mockito.*;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* BMPImageReaderTest
|
* BMPImageReaderTest
|
||||||
@@ -68,6 +76,12 @@ import static org.mockito.Mockito.*;
|
|||||||
* @version $Id: BMPImageReaderTest.java,v 1.0 Apr 1, 2008 10:39:17 PM haraldk Exp$
|
* @version $Id: BMPImageReaderTest.java,v 1.0 Apr 1, 2008 10:39:17 PM haraldk Exp$
|
||||||
*/
|
*/
|
||||||
public class BMPImageReaderTest extends ImageReaderAbstractTest<BMPImageReader> {
|
public class BMPImageReaderTest extends ImageReaderAbstractTest<BMPImageReader> {
|
||||||
|
@Override
|
||||||
|
protected ImageReaderSpi createProvider() {
|
||||||
|
return new BMPImageReaderSpi();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
protected List<TestData> getTestData() {
|
protected List<TestData> getTestData() {
|
||||||
return Arrays.asList(
|
return Arrays.asList(
|
||||||
// BMP Suite "Good"
|
// BMP Suite "Good"
|
||||||
@@ -144,27 +158,17 @@ public class BMPImageReaderTest extends ImageReaderAbstractTest<BMPImageReader>
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected ImageReaderSpi createProvider() {
|
|
||||||
return new BMPImageReaderSpi();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected BMPImageReader createReader() {
|
|
||||||
return new BMPImageReader(createProvider());
|
|
||||||
}
|
|
||||||
|
|
||||||
protected Class<BMPImageReader> getReaderClass() {
|
|
||||||
return BMPImageReader.class;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected List<String> getFormatNames() {
|
protected List<String> getFormatNames() {
|
||||||
return Collections.singletonList("bmp");
|
return Collections.singletonList("bmp");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
protected List<String> getSuffixes() {
|
protected List<String> getSuffixes() {
|
||||||
return Arrays.asList("bmp", "rle");
|
return Arrays.asList("bmp", "rle");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
protected List<String> getMIMETypes() {
|
protected List<String> getMIMETypes() {
|
||||||
return Collections.singletonList("image/bmp");
|
return Collections.singletonList("image/bmp");
|
||||||
}
|
}
|
||||||
@@ -178,7 +182,7 @@ public class BMPImageReaderTest extends ImageReaderAbstractTest<BMPImageReader>
|
|||||||
|
|
||||||
ImageTypeSpecifier rawType = reader.getRawImageType(0);
|
ImageTypeSpecifier rawType = reader.getRawImageType(0);
|
||||||
|
|
||||||
// As the JPEGImageReader we delegate to returns null for YCbCr, we'll have to do the same
|
// As the JPEGImageReader we delegate to may return null for YCbCr, we'll have to do the same
|
||||||
if (rawType == null && data.getInput().toString().contains("jpeg")) {
|
if (rawType == null && data.getInput().toString().contains("jpeg")) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -273,7 +277,7 @@ public class BMPImageReaderTest extends ImageReaderAbstractTest<BMPImageReader>
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testAddIIOReadProgressListenerCallbacksJPEG() {
|
public void testAddIIOReadProgressListenerCallbacksJPEG() throws IOException {
|
||||||
ImageReader reader = createReader();
|
ImageReader reader = createReader();
|
||||||
TestData data = new TestData(getClassLoaderResource("/bmpsuite/q/rgb24jpeg.bmp"), new Dimension(127, 64));
|
TestData data = new TestData(getClassLoaderResource("/bmpsuite/q/rgb24jpeg.bmp"), new Dimension(127, 64));
|
||||||
reader.setInput(data.getInputStream());
|
reader.setInput(data.getInputStream());
|
||||||
@@ -296,7 +300,7 @@ public class BMPImageReaderTest extends ImageReaderAbstractTest<BMPImageReader>
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testAddIIOReadProgressListenerCallbacksPNG() {
|
public void testAddIIOReadProgressListenerCallbacksPNG() throws IOException {
|
||||||
ImageReader reader = createReader();
|
ImageReader reader = createReader();
|
||||||
TestData data = new TestData(getClassLoaderResource("/bmpsuite/q/rgb24png.bmp"), new Dimension(127, 64));
|
TestData data = new TestData(getClassLoaderResource("/bmpsuite/q/rgb24png.bmp"), new Dimension(127, 64));
|
||||||
reader.setInput(data.getInputStream());
|
reader.setInput(data.getInputStream());
|
||||||
@@ -319,7 +323,7 @@ public class BMPImageReaderTest extends ImageReaderAbstractTest<BMPImageReader>
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testMetadataEqualsJRE() throws IOException, URISyntaxException {
|
public void testMetadataEqualsJRE() throws IOException {
|
||||||
ImageReader jreReader;
|
ImageReader jreReader;
|
||||||
try {
|
try {
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
@@ -356,7 +360,7 @@ public class BMPImageReaderTest extends ImageReaderAbstractTest<BMPImageReader>
|
|||||||
}
|
}
|
||||||
IIOMetadata jreMetadata = jreReader.getImageMetadata(0);
|
IIOMetadata jreMetadata = jreReader.getImageMetadata(0);
|
||||||
|
|
||||||
assertEquals(true, metadata.isStandardMetadataFormatSupported());
|
assertTrue(metadata.isStandardMetadataFormatSupported());
|
||||||
assertEquals(jreMetadata.getNativeMetadataFormatName(), metadata.getNativeMetadataFormatName());
|
assertEquals(jreMetadata.getNativeMetadataFormatName(), metadata.getNativeMetadataFormatName());
|
||||||
assertArrayEquals(jreMetadata.getExtraMetadataFormatNames(), metadata.getExtraMetadataFormatNames());
|
assertArrayEquals(jreMetadata.getExtraMetadataFormatNames(), metadata.getExtraMetadataFormatNames());
|
||||||
|
|
||||||
@@ -379,7 +383,7 @@ public class BMPImageReaderTest extends ImageReaderAbstractTest<BMPImageReader>
|
|||||||
new XMLSerializer(expected, "UTF-8").serialize(expectedTree, false);
|
new XMLSerializer(expected, "UTF-8").serialize(expectedTree, false);
|
||||||
new XMLSerializer(actual, "UTF-8").serialize(actualTree, false);
|
new XMLSerializer(actual, "UTF-8").serialize(actualTree, false);
|
||||||
|
|
||||||
assertEquals(e.getMessage(), new String(expected.toByteArray(), "UTF-8"), new String(actual.toByteArray(), "UTF-8"));
|
assertEquals(e.getMessage(), new String(expected.toByteArray(), StandardCharsets.UTF_8), new String(actual.toByteArray(), StandardCharsets.UTF_8));
|
||||||
|
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,30 @@
|
|||||||
|
package com.twelvemonkeys.imageio.plugins.bmp;
|
||||||
|
|
||||||
|
import com.twelvemonkeys.imageio.util.ImageWriterAbstractTest;
|
||||||
|
|
||||||
|
import javax.imageio.spi.ImageWriterSpi;
|
||||||
|
import java.awt.image.BufferedImage;
|
||||||
|
import java.awt.image.RenderedImage;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* BMPImageWriterTest.
|
||||||
|
*
|
||||||
|
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||||
|
* @author last modified by : harald.kuhr$
|
||||||
|
* @version : BMPImageWriterTest.java,v 1.0 25/06/2020 harald.kuhr Exp$
|
||||||
|
*/
|
||||||
|
public class BMPImageWriterTest extends ImageWriterAbstractTest<BMPImageWriter> {
|
||||||
|
@Override
|
||||||
|
protected ImageWriterSpi createProvider() {
|
||||||
|
return new BMPImageWriterSpi();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected List<? extends RenderedImage> getTestData() {
|
||||||
|
return Collections.singletonList(
|
||||||
|
new BufferedImage(10, 10, BufferedImage.TYPE_4BYTE_ABGR)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -31,6 +31,7 @@
|
|||||||
package com.twelvemonkeys.imageio.plugins.bmp;
|
package com.twelvemonkeys.imageio.plugins.bmp;
|
||||||
|
|
||||||
import com.twelvemonkeys.imageio.util.ImageReaderAbstractTest;
|
import com.twelvemonkeys.imageio.util.ImageReaderAbstractTest;
|
||||||
|
|
||||||
import org.junit.Ignore;
|
import org.junit.Ignore;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
@@ -53,6 +54,12 @@ import static org.junit.Assert.*;
|
|||||||
* @version $Id: CURImageReaderTest.java,v 1.0 Apr 1, 2008 10:39:17 PM haraldk Exp$
|
* @version $Id: CURImageReaderTest.java,v 1.0 Apr 1, 2008 10:39:17 PM haraldk Exp$
|
||||||
*/
|
*/
|
||||||
public class CURImageReaderTest extends ImageReaderAbstractTest<CURImageReader> {
|
public class CURImageReaderTest extends ImageReaderAbstractTest<CURImageReader> {
|
||||||
|
@Override
|
||||||
|
protected ImageReaderSpi createProvider() {
|
||||||
|
return new CURImageReaderSpi();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
protected List<TestData> getTestData() {
|
protected List<TestData> getTestData() {
|
||||||
return Arrays.asList(
|
return Arrays.asList(
|
||||||
new TestData(getClassLoaderResource("/cur/hand.cur"), new Dimension(32, 32)),
|
new TestData(getClassLoaderResource("/cur/hand.cur"), new Dimension(32, 32)),
|
||||||
@@ -60,27 +67,17 @@ public class CURImageReaderTest extends ImageReaderAbstractTest<CURImageReader>
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected ImageReaderSpi createProvider() {
|
|
||||||
return new CURImageReaderSpi();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected CURImageReader createReader() {
|
|
||||||
return new CURImageReader();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected Class<CURImageReader> getReaderClass() {
|
|
||||||
return CURImageReader.class;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected List<String> getFormatNames() {
|
protected List<String> getFormatNames() {
|
||||||
return Collections.singletonList("cur");
|
return Collections.singletonList("cur");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
protected List<String> getSuffixes() {
|
protected List<String> getSuffixes() {
|
||||||
return Collections.singletonList("cur");
|
return Collections.singletonList("cur");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
protected List<String> getMIMETypes() {
|
protected List<String> getMIMETypes() {
|
||||||
return Arrays.asList("image/vnd.microsoft.cursor", "image/cursor", "image/x-cursor");
|
return Arrays.asList("image/vnd.microsoft.cursor", "image/cursor", "image/x-cursor");
|
||||||
}
|
}
|
||||||
@@ -99,7 +96,7 @@ public class CURImageReaderTest extends ImageReaderAbstractTest<CURImageReader>
|
|||||||
assertNotNull("Hotspot for cursor not present", hotspot);
|
assertNotNull("Hotspot for cursor not present", hotspot);
|
||||||
|
|
||||||
// Image weirdness
|
// Image weirdness
|
||||||
assertTrue("Hotspot for cursor undefined (java.awt.Image.UndefinedProperty)", Image.UndefinedProperty != hotspot);
|
assertNotSame("Hotspot for cursor undefined (java.awt.Image.UndefinedProperty)", Image.UndefinedProperty, hotspot);
|
||||||
|
|
||||||
assertTrue(String.format("Hotspot not a java.awt.Point: %s", hotspot.getClass()), hotspot instanceof Point);
|
assertTrue(String.format("Hotspot not a java.awt.Point: %s", hotspot.getClass()), hotspot instanceof Point);
|
||||||
assertEquals(pExpected, hotspot);
|
assertEquals(pExpected, hotspot);
|
||||||
|
|||||||
@@ -31,6 +31,7 @@
|
|||||||
package com.twelvemonkeys.imageio.plugins.bmp;
|
package com.twelvemonkeys.imageio.plugins.bmp;
|
||||||
|
|
||||||
import com.twelvemonkeys.imageio.util.ImageReaderAbstractTest;
|
import com.twelvemonkeys.imageio.util.ImageReaderAbstractTest;
|
||||||
|
|
||||||
import org.junit.Ignore;
|
import org.junit.Ignore;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
@@ -49,6 +50,12 @@ import java.util.List;
|
|||||||
* @version $Id: ICOImageReaderTest.java,v 1.0 Apr 1, 2008 10:39:17 PM haraldk Exp$
|
* @version $Id: ICOImageReaderTest.java,v 1.0 Apr 1, 2008 10:39:17 PM haraldk Exp$
|
||||||
*/
|
*/
|
||||||
public class ICOImageReaderTest extends ImageReaderAbstractTest<ICOImageReader> {
|
public class ICOImageReaderTest extends ImageReaderAbstractTest<ICOImageReader> {
|
||||||
|
@Override
|
||||||
|
protected ImageReaderSpi createProvider() {
|
||||||
|
return new ICOImageReaderSpi();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
protected List<TestData> getTestData() {
|
protected List<TestData> getTestData() {
|
||||||
return Arrays.asList(
|
return Arrays.asList(
|
||||||
new TestData(
|
new TestData(
|
||||||
@@ -75,27 +82,17 @@ public class ICOImageReaderTest extends ImageReaderAbstractTest<ICOImageReader>
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected ImageReaderSpi createProvider() {
|
|
||||||
return new ICOImageReaderSpi();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected ICOImageReader createReader() {
|
|
||||||
return new ICOImageReader();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected Class<ICOImageReader> getReaderClass() {
|
|
||||||
return ICOImageReader.class;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected List<String> getFormatNames() {
|
protected List<String> getFormatNames() {
|
||||||
return Collections.singletonList("ico");
|
return Collections.singletonList("ico");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
protected List<String> getSuffixes() {
|
protected List<String> getSuffixes() {
|
||||||
return Collections.singletonList("ico");
|
return Collections.singletonList("ico");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
protected List<String> getMIMETypes() {
|
protected List<String> getMIMETypes() {
|
||||||
return Arrays.asList("image/vnd.microsoft.icon", "image/ico", "image/x-icon");
|
return Arrays.asList("image/vnd.microsoft.icon", "image/ico", "image/x-icon");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,34 @@
|
|||||||
|
package com.twelvemonkeys.imageio.plugins.bmp;
|
||||||
|
|
||||||
|
import com.twelvemonkeys.imageio.util.ImageWriterAbstractTest;
|
||||||
|
|
||||||
|
import javax.imageio.spi.ImageWriterSpi;
|
||||||
|
import java.awt.image.BufferedImage;
|
||||||
|
import java.awt.image.RenderedImage;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ICOImageWriterTest.
|
||||||
|
*
|
||||||
|
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||||
|
* @author last modified by : harald.kuhr$
|
||||||
|
* @version : ICOImageWriterTest.java,v 1.0 25/06/2020 harald.kuhr Exp$
|
||||||
|
*/
|
||||||
|
public class ICOImageWriterTest extends ImageWriterAbstractTest<ICOImageWriter> {
|
||||||
|
@Override
|
||||||
|
protected ImageWriterSpi createProvider() {
|
||||||
|
return new ICOImageWriterSpi();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected List<? extends RenderedImage> getTestData() {
|
||||||
|
return Arrays.asList(
|
||||||
|
new BufferedImage(8, 8, BufferedImage.TYPE_4BYTE_ABGR),
|
||||||
|
new BufferedImage(16, 16, BufferedImage.TYPE_4BYTE_ABGR),
|
||||||
|
new BufferedImage(32, 32, BufferedImage.TYPE_4BYTE_ABGR),
|
||||||
|
new BufferedImage(64, 64, BufferedImage.TYPE_4BYTE_ABGR),
|
||||||
|
new BufferedImage(128, 128, BufferedImage.TYPE_4BYTE_ABGR)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,7 +4,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>com.twelvemonkeys.imageio</groupId>
|
<groupId>com.twelvemonkeys.imageio</groupId>
|
||||||
<artifactId>imageio</artifactId>
|
<artifactId>imageio</artifactId>
|
||||||
<version>3.5</version>
|
<version>3.6.2</version>
|
||||||
</parent>
|
</parent>
|
||||||
<artifactId>imageio-clippath</artifactId>
|
<artifactId>imageio-clippath</artifactId>
|
||||||
<name>TwelveMonkeys :: ImageIO :: Photoshop Path Support</name>
|
<name>TwelveMonkeys :: ImageIO :: Photoshop Path Support</name>
|
||||||
@@ -21,6 +21,7 @@
|
|||||||
<groupId>com.twelvemonkeys.imageio</groupId>
|
<groupId>com.twelvemonkeys.imageio</groupId>
|
||||||
<artifactId>imageio-core</artifactId>
|
<artifactId>imageio-core</artifactId>
|
||||||
<type>test-jar</type>
|
<type>test-jar</type>
|
||||||
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.twelvemonkeys.imageio</groupId>
|
<groupId>com.twelvemonkeys.imageio</groupId>
|
||||||
|
|||||||
@@ -107,8 +107,8 @@ final class AdobePathSegment {
|
|||||||
case OPEN_SUBPATH_BEZIER_LINKED:
|
case OPEN_SUBPATH_BEZIER_LINKED:
|
||||||
case OPEN_SUBPATH_BEZIER_UNLINKED:
|
case OPEN_SUBPATH_BEZIER_UNLINKED:
|
||||||
isTrue(
|
isTrue(
|
||||||
cppx >= 0 && cppx <= 1 && cppy >= 0 && cppy <= 1,
|
cppx >= -16 && cppx <= 16 && cppy >= -16 && cppy <= 16,
|
||||||
String.format("Expected point in range [0...1]: (%f, %f)", cppx ,cppy)
|
String.format("Expected point in range [-16...16]: (%f, %f)", cppx ,cppy)
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
case PATH_FILL_RULE_RECORD:
|
case PATH_FILL_RULE_RECORD:
|
||||||
|
|||||||
@@ -113,8 +113,13 @@ public class AdobePathSegmentTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = IllegalArgumentException.class)
|
@Test(expected = IllegalArgumentException.class)
|
||||||
public void testCreateOpenLinkedRecordNegative() {
|
public void testCreateOpenLinkedRecordOutOfRangeNegative() {
|
||||||
new AdobePathSegment(AdobePathSegment.OPEN_SUBPATH_BEZIER_LINKED, -.5, -.5, 0, 0, 1, 1);
|
new AdobePathSegment(AdobePathSegment.OPEN_SUBPATH_BEZIER_LINKED, -16.1, -16.1, 0, 0, 1, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = IllegalArgumentException.class)
|
||||||
|
public void testCreateOpenLinkedRecordOutOfRangePositive() {
|
||||||
|
new AdobePathSegment(AdobePathSegment.OPEN_SUBPATH_BEZIER_LINKED, 16.1, 16.1, 0, 0, 1, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -138,8 +143,13 @@ public class AdobePathSegmentTest {
|
|||||||
|
|
||||||
|
|
||||||
@Test(expected = IllegalArgumentException.class)
|
@Test(expected = IllegalArgumentException.class)
|
||||||
public void testCreateOpenUnlinkedRecordNegative() {
|
public void testCreateOpenUnlinkedRecordOutOfRangeNegative() {
|
||||||
new AdobePathSegment(AdobePathSegment.OPEN_SUBPATH_BEZIER_UNLINKED, -.5, -.5, 0, 0, 1, 1);
|
new AdobePathSegment(AdobePathSegment.OPEN_SUBPATH_BEZIER_UNLINKED, -16.5, 0, 0, 0, 1, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = IllegalArgumentException.class)
|
||||||
|
public void testCreateOpenUnlinkedRecorOutOfRangePositive() {
|
||||||
|
new AdobePathSegment(AdobePathSegment.OPEN_SUBPATH_BEZIER_UNLINKED, 0, -17, 0, 0, 16.5, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Closed subpath
|
/// Closed subpath
|
||||||
@@ -164,8 +174,13 @@ public class AdobePathSegmentTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = IllegalArgumentException.class)
|
@Test(expected = IllegalArgumentException.class)
|
||||||
public void testCreateClosedLinkedRecordNegative() {
|
public void testCreateClosedLinkedRecordOutOfRangeNegative() {
|
||||||
new AdobePathSegment(AdobePathSegment.CLOSED_SUBPATH_BEZIER_LINKED, -.5, -.5, 0, 0, 1, 1);
|
new AdobePathSegment(AdobePathSegment.CLOSED_SUBPATH_BEZIER_LINKED, -16.5, -.5, 0, 0, 1, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = IllegalArgumentException.class)
|
||||||
|
public void testCreateClosedLinkedRecordOutOfRangePositive() {
|
||||||
|
new AdobePathSegment(AdobePathSegment.CLOSED_SUBPATH_BEZIER_LINKED, .5, 16.5, 0, 0, 1, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -189,8 +204,13 @@ public class AdobePathSegmentTest {
|
|||||||
|
|
||||||
|
|
||||||
@Test(expected = IllegalArgumentException.class)
|
@Test(expected = IllegalArgumentException.class)
|
||||||
public void testCreateClosedUnlinkedRecordNegative() {
|
public void testCreateClosedUnlinkedRecordOutOfRangeNegative() {
|
||||||
new AdobePathSegment(AdobePathSegment.CLOSED_SUBPATH_BEZIER_UNLINKED, -.5, -.5, 0, 0, 1, 1);
|
new AdobePathSegment(AdobePathSegment.CLOSED_SUBPATH_BEZIER_UNLINKED, -.5, -16.5, 0, 0, 1, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = IllegalArgumentException.class)
|
||||||
|
public void testCreateClosedUnlinkedRecordOutOfRangePositive() {
|
||||||
|
new AdobePathSegment(AdobePathSegment.CLOSED_SUBPATH_BEZIER_UNLINKED, 16.5, .5, 0, 0, 1, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>com.twelvemonkeys.imageio</groupId>
|
<groupId>com.twelvemonkeys.imageio</groupId>
|
||||||
<artifactId>imageio</artifactId>
|
<artifactId>imageio</artifactId>
|
||||||
<version>3.5</version>
|
<version>3.6.2</version>
|
||||||
</parent>
|
</parent>
|
||||||
<artifactId>imageio-core</artifactId>
|
<artifactId>imageio-core</artifactId>
|
||||||
<name>TwelveMonkeys :: ImageIO :: Core</name>
|
<name>TwelveMonkeys :: ImageIO :: Core</name>
|
||||||
|
|||||||
@@ -30,20 +30,16 @@
|
|||||||
|
|
||||||
package com.twelvemonkeys.imageio;
|
package com.twelvemonkeys.imageio;
|
||||||
|
|
||||||
import com.twelvemonkeys.image.BufferedImageIcon;
|
|
||||||
import com.twelvemonkeys.image.ImageUtil;
|
|
||||||
import com.twelvemonkeys.imageio.util.IIOUtil;
|
|
||||||
|
|
||||||
import javax.imageio.*;
|
|
||||||
import javax.imageio.metadata.IIOMetadata;
|
|
||||||
import javax.imageio.spi.ImageReaderSpi;
|
|
||||||
import javax.imageio.stream.ImageInputStream;
|
|
||||||
import javax.swing.*;
|
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.awt.datatransfer.DataFlavor;
|
import java.awt.datatransfer.DataFlavor;
|
||||||
import java.awt.datatransfer.Transferable;
|
import java.awt.datatransfer.Transferable;
|
||||||
import java.awt.datatransfer.UnsupportedFlavorException;
|
import java.awt.datatransfer.UnsupportedFlavorException;
|
||||||
import java.awt.event.*;
|
import java.awt.event.ActionEvent;
|
||||||
|
import java.awt.event.KeyEvent;
|
||||||
|
import java.awt.event.MouseAdapter;
|
||||||
|
import java.awt.event.MouseEvent;
|
||||||
|
import java.awt.event.WindowAdapter;
|
||||||
|
import java.awt.event.WindowEvent;
|
||||||
import java.awt.image.BufferedImage;
|
import java.awt.image.BufferedImage;
|
||||||
import java.awt.image.IndexColorModel;
|
import java.awt.image.IndexColorModel;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
@@ -52,6 +48,20 @@ import java.lang.reflect.InvocationTargetException;
|
|||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
|
||||||
|
import javax.imageio.IIOException;
|
||||||
|
import javax.imageio.ImageIO;
|
||||||
|
import javax.imageio.ImageReadParam;
|
||||||
|
import javax.imageio.ImageReader;
|
||||||
|
import javax.imageio.ImageTypeSpecifier;
|
||||||
|
import javax.imageio.metadata.IIOMetadata;
|
||||||
|
import javax.imageio.spi.ImageReaderSpi;
|
||||||
|
import javax.imageio.stream.ImageInputStream;
|
||||||
|
import javax.swing.*;
|
||||||
|
|
||||||
|
import com.twelvemonkeys.image.BufferedImageIcon;
|
||||||
|
import com.twelvemonkeys.image.ImageUtil;
|
||||||
|
import com.twelvemonkeys.imageio.util.IIOUtil;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Abstract base class for image readers.
|
* Abstract base class for image readers.
|
||||||
*
|
*
|
||||||
@@ -314,12 +324,12 @@ public abstract class ImageReaderBase extends ImageReader {
|
|||||||
|
|
||||||
long dimension = (long) destWidth * destHeight;
|
long dimension = (long) destWidth * destHeight;
|
||||||
if (dimension > Integer.MAX_VALUE) {
|
if (dimension > Integer.MAX_VALUE) {
|
||||||
throw new IllegalArgumentException(String.format("destination width * height > Integer.MAX_VALUE: %d", dimension));
|
throw new IIOException(String.format("destination width * height > Integer.MAX_VALUE: %d", dimension));
|
||||||
}
|
}
|
||||||
|
|
||||||
long size = dimension * imageType.getSampleModel().getNumDataElements();
|
long size = dimension * imageType.getSampleModel().getNumDataElements();
|
||||||
if (size > Integer.MAX_VALUE) {
|
if (size > Integer.MAX_VALUE) {
|
||||||
throw new IllegalArgumentException(String.format("destination width * height * samplesPerPixel > Integer.MAX_VALUE: %d", size));
|
throw new IIOException(String.format("destination width * height * samplesPerPixel > Integer.MAX_VALUE: %d", size));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a new image based on the type specifier
|
// Create a new image based on the type specifier
|
||||||
|
|||||||
@@ -57,8 +57,10 @@ public final class BufferedImageInputStream extends ImageInputStreamImpl impleme
|
|||||||
|
|
||||||
private ImageInputStream stream;
|
private ImageInputStream stream;
|
||||||
|
|
||||||
private ByteBuffer buffer;
|
private ByteBuffer buffer;
|
||||||
private ByteBuffer integralCache = ByteBuffer.allocate(8);
|
|
||||||
|
private final ByteBuffer integralCache = ByteBuffer.allocate(8);
|
||||||
|
private final byte[] integralCacheArray = integralCache.array();
|
||||||
|
|
||||||
public BufferedImageInputStream(final ImageInputStream pStream) throws IOException {
|
public BufferedImageInputStream(final ImageInputStream pStream) throws IOException {
|
||||||
this(pStream, DEFAULT_BUFFER_SIZE);
|
this(pStream, DEFAULT_BUFFER_SIZE);
|
||||||
@@ -97,10 +99,10 @@ public final class BufferedImageInputStream extends ImageInputStreamImpl impleme
|
|||||||
|
|
||||||
if (!buffer.hasRemaining()) {
|
if (!buffer.hasRemaining()) {
|
||||||
fillBuffer();
|
fillBuffer();
|
||||||
}
|
|
||||||
|
|
||||||
if (!buffer.hasRemaining()) {
|
if (!buffer.hasRemaining()) {
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bitOffset = 0;
|
bitOffset = 0;
|
||||||
@@ -172,21 +174,21 @@ public final class BufferedImageInputStream extends ImageInputStreamImpl impleme
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public short readShort() throws IOException {
|
public short readShort() throws IOException {
|
||||||
readFully(integralCache.array(), 0, 2);
|
readFully(integralCacheArray, 0, 2);
|
||||||
|
|
||||||
return integralCache.getShort(0);
|
return integralCache.getShort(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int readInt() throws IOException {
|
public int readInt() throws IOException {
|
||||||
readFully(integralCache.array(), 0, 4);
|
readFully(integralCacheArray, 0, 4);
|
||||||
|
|
||||||
return integralCache.getInt(0);
|
return integralCache.getInt(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long readLong() throws IOException {
|
public long readLong() throws IOException {
|
||||||
readFully(integralCache.array(), 0, 8);
|
readFully(integralCacheArray, 0, 8);
|
||||||
|
|
||||||
return integralCache.getLong(0);
|
return integralCache.getLong(0);
|
||||||
}
|
}
|
||||||
@@ -253,6 +255,7 @@ public final class BufferedImageInputStream extends ImageInputStreamImpl impleme
|
|||||||
}
|
}
|
||||||
|
|
||||||
int val = buffer.get() & 0xff;
|
int val = buffer.get() & 0xff;
|
||||||
|
streamPos++;
|
||||||
|
|
||||||
accum <<= 8;
|
accum <<= 8;
|
||||||
accum |= val;
|
accum |= val;
|
||||||
@@ -262,9 +265,7 @@ public final class BufferedImageInputStream extends ImageInputStreamImpl impleme
|
|||||||
// Move byte position back if in the middle of a byte
|
// Move byte position back if in the middle of a byte
|
||||||
if (newBitOffset != 0) {
|
if (newBitOffset != 0) {
|
||||||
buffer.position(buffer.position() - 1);
|
buffer.position(buffer.position() - 1);
|
||||||
}
|
streamPos--;
|
||||||
else {
|
|
||||||
streamPos++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.bitOffset = newBitOffset;
|
this.bitOffset = newBitOffset;
|
||||||
@@ -279,26 +280,26 @@ public final class BufferedImageInputStream extends ImageInputStreamImpl impleme
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void seek(long pPosition) throws IOException {
|
public void seek(long position) throws IOException {
|
||||||
checkClosed();
|
checkClosed();
|
||||||
bitOffset = 0;
|
bitOffset = 0;
|
||||||
|
|
||||||
if (streamPos == pPosition) {
|
if (streamPos == position) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Optimized to not invalidate buffer if new position is within current buffer
|
// Optimized to not invalidate buffer if new position is within current buffer
|
||||||
long newBufferPos = buffer.position() + pPosition - streamPos;
|
long newBufferPos = buffer.position() + position - streamPos;
|
||||||
if (newBufferPos >= 0 && newBufferPos <= buffer.limit()) {
|
if (newBufferPos >= 0 && newBufferPos <= buffer.limit()) {
|
||||||
buffer.position((int) newBufferPos);
|
buffer.position((int) newBufferPos);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// Will invalidate buffer
|
// Will invalidate buffer
|
||||||
buffer.limit(0);
|
buffer.limit(0);
|
||||||
stream.seek(pPosition);
|
stream.seek(position);
|
||||||
}
|
}
|
||||||
|
|
||||||
streamPos = pPosition;
|
streamPos = position;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -330,7 +331,9 @@ public final class BufferedImageInputStream extends ImageInputStreamImpl impleme
|
|||||||
@Override
|
@Override
|
||||||
public void close() throws IOException {
|
public void close() throws IOException {
|
||||||
if (stream != null) {
|
if (stream != null) {
|
||||||
//stream.close();
|
// TODO: FixMe: Need to close underlying stream here!
|
||||||
|
// For call sites that relies on not closing, we should instead not close the buffered stream.
|
||||||
|
// stream.close();
|
||||||
stream = null;
|
stream = null;
|
||||||
buffer = null;
|
buffer = null;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,10 +30,11 @@
|
|||||||
|
|
||||||
package com.twelvemonkeys.imageio.stream;
|
package com.twelvemonkeys.imageio.stream;
|
||||||
|
|
||||||
|
import com.twelvemonkeys.imageio.spi.ProviderInfo;
|
||||||
|
|
||||||
import javax.imageio.spi.ImageInputStreamSpi;
|
import javax.imageio.spi.ImageInputStreamSpi;
|
||||||
import javax.imageio.stream.ImageInputStream;
|
import javax.imageio.stream.ImageInputStream;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -47,10 +48,14 @@ import java.util.Locale;
|
|||||||
public class ByteArrayImageInputStreamSpi extends ImageInputStreamSpi {
|
public class ByteArrayImageInputStreamSpi extends ImageInputStreamSpi {
|
||||||
|
|
||||||
public ByteArrayImageInputStreamSpi() {
|
public ByteArrayImageInputStreamSpi() {
|
||||||
super("TwelveMonkeys", "1.0 BETA", byte[].class);
|
this(new StreamProviderInfo());
|
||||||
}
|
}
|
||||||
|
|
||||||
public ImageInputStream createInputStreamInstance(Object pInput, boolean pUseCache, File pCacheDir) throws IOException {
|
private ByteArrayImageInputStreamSpi(ProviderInfo providerInfo) {
|
||||||
|
super(providerInfo.getVendorName(), providerInfo.getVersion(), byte[].class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ImageInputStream createInputStreamInstance(Object pInput, boolean pUseCache, File pCacheDir) {
|
||||||
if (pInput instanceof byte[]) {
|
if (pInput instanceof byte[]) {
|
||||||
return new ByteArrayImageInputStream((byte[]) pInput);
|
return new ByteArrayImageInputStream((byte[]) pInput);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
package com.twelvemonkeys.imageio.stream;
|
||||||
|
|
||||||
|
import com.twelvemonkeys.imageio.spi.ProviderInfo;
|
||||||
|
|
||||||
|
final class StreamProviderInfo extends ProviderInfo {
|
||||||
|
StreamProviderInfo() {
|
||||||
|
super(StreamProviderInfo.class.getPackage());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -30,6 +30,8 @@
|
|||||||
|
|
||||||
package com.twelvemonkeys.imageio.stream;
|
package com.twelvemonkeys.imageio.stream;
|
||||||
|
|
||||||
|
import com.twelvemonkeys.imageio.spi.ProviderInfo;
|
||||||
|
|
||||||
import javax.imageio.spi.ImageInputStreamSpi;
|
import javax.imageio.spi.ImageInputStreamSpi;
|
||||||
import javax.imageio.stream.FileCacheImageInputStream;
|
import javax.imageio.stream.FileCacheImageInputStream;
|
||||||
import javax.imageio.stream.FileImageInputStream;
|
import javax.imageio.stream.FileImageInputStream;
|
||||||
@@ -53,7 +55,11 @@ import java.util.Locale;
|
|||||||
// TODO: URI instead of URL?
|
// TODO: URI instead of URL?
|
||||||
public class URLImageInputStreamSpi extends ImageInputStreamSpi {
|
public class URLImageInputStreamSpi extends ImageInputStreamSpi {
|
||||||
public URLImageInputStreamSpi() {
|
public URLImageInputStreamSpi() {
|
||||||
super("TwelveMonkeys", "1.0 BETA", URL.class);
|
this(new StreamProviderInfo());
|
||||||
|
}
|
||||||
|
|
||||||
|
private URLImageInputStreamSpi(ProviderInfo providerInfo) {
|
||||||
|
super(providerInfo.getVendorName(), providerInfo.getVersion(), URL.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Create a URI or URLImageInputStream class, with a getUR[I|L] method, to allow for multiple file formats
|
// TODO: Create a URI or URLImageInputStream class, with a getUR[I|L] method, to allow for multiple file formats
|
||||||
@@ -108,6 +114,11 @@ public class URLImageInputStreamSpi extends ImageInputStreamSpi {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canUseCacheFile() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
public String getDescription(final Locale pLocale) {
|
public String getDescription(final Locale pLocale) {
|
||||||
return "Service provider that instantiates an ImageInputStream from a URL";
|
return "Service provider that instantiates an ImageInputStream from a URL";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -291,4 +291,21 @@ public final class IIOUtil {
|
|||||||
System.arraycopy(srcRow, srcPos + x, destRow, destPos + x / samplePeriod, pixelStride);
|
System.arraycopy(srcRow, srcPos + x, destRow, destPos + x / samplePeriod, pixelStride);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void subsampleRow(float[] srcRow, int srcPos, int srcWidth,
|
||||||
|
float[] destRow, int destPos,
|
||||||
|
int samplesPerPixel, int bitsPerSample, int samplePeriod) {
|
||||||
|
Validate.isTrue(samplePeriod > 1, "samplePeriod must be > 1"); // Period == 1 could be a no-op...
|
||||||
|
Validate.isTrue(bitsPerSample > 0 && bitsPerSample <= 32 && (bitsPerSample == 1 || bitsPerSample % 2 == 0),
|
||||||
|
"bitsPerSample must be > 0 and <= 32 and a power of 2");
|
||||||
|
Validate.isTrue(samplesPerPixel > 0, "samplesPerPixel must be > 0");
|
||||||
|
Validate.isTrue(samplesPerPixel * bitsPerSample <= 32 || samplesPerPixel * bitsPerSample % 32 == 0,
|
||||||
|
"samplesPerPixel * bitsPerSample must be < 32 or a multiple of 32 ");
|
||||||
|
|
||||||
|
int pixelStride = bitsPerSample * samplesPerPixel / 32;
|
||||||
|
for (int x = 0; x < srcWidth * pixelStride; x += samplePeriod * pixelStride) {
|
||||||
|
// System.arraycopy should be intrinsic, but consider using direct array access for pixelStride == 1
|
||||||
|
System.arraycopy(srcRow, srcPos + x, destRow, destPos + x / samplePeriod, pixelStride);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -30,11 +30,11 @@
|
|||||||
|
|
||||||
package com.twelvemonkeys.imageio;
|
package com.twelvemonkeys.imageio;
|
||||||
|
|
||||||
import org.junit.Test;
|
import static java.util.Collections.singleton;
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertFalse;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
import javax.imageio.IIOException;
|
|
||||||
import javax.imageio.ImageReadParam;
|
|
||||||
import javax.imageio.ImageTypeSpecifier;
|
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.awt.color.ColorSpace;
|
import java.awt.color.ColorSpace;
|
||||||
import java.awt.image.BufferedImage;
|
import java.awt.image.BufferedImage;
|
||||||
@@ -44,8 +44,11 @@ import java.util.Collections;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import static java.util.Collections.singleton;
|
import javax.imageio.IIOException;
|
||||||
import static org.junit.Assert.*;
|
import javax.imageio.ImageReadParam;
|
||||||
|
import javax.imageio.ImageTypeSpecifier;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ImageReaderBaseTest
|
* ImageReaderBaseTest
|
||||||
@@ -212,19 +215,19 @@ public class ImageReaderBaseTest {
|
|||||||
assertEquals(TYPES.get(0).getBufferedImageType(), destination.getType());
|
assertEquals(TYPES.get(0).getBufferedImageType(), destination.getType());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = IllegalArgumentException.class)
|
@Test(expected = IIOException.class)
|
||||||
public void testGetDestinationParamDestinationExceedsIntegerMax() throws IIOException {
|
public void testGetDestinationParamDestinationExceedsIntegerMax() throws IIOException {
|
||||||
ImageReadParam param = new ImageReadParam();
|
ImageReadParam param = new ImageReadParam();
|
||||||
param.setSourceRegion(new Rectangle(3 * Short.MAX_VALUE, 2 * Short.MAX_VALUE)); // 6 442 057 734 pixels
|
param.setSourceRegion(new Rectangle(3 * Short.MAX_VALUE, 2 * Short.MAX_VALUE)); // 6 442 057 734 pixels
|
||||||
ImageReaderBase.getDestination(param, TYPES.iterator(), 6 * Short.MAX_VALUE, 4 * Short.MAX_VALUE); // 25 768 230 936 pixels
|
ImageReaderBase.getDestination(param, TYPES.iterator(), 6 * Short.MAX_VALUE, 4 * Short.MAX_VALUE); // 25 768 230 936 pixels
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = IllegalArgumentException.class)
|
@Test(expected = IIOException.class)
|
||||||
public void testGetDestinationDimensionExceedsIntegerMax() throws IIOException {
|
public void testGetDestinationDimensionExceedsIntegerMax() throws IIOException {
|
||||||
ImageReaderBase.getDestination(null, TYPES.iterator(), 3 * Short.MAX_VALUE, 2 * Short.MAX_VALUE); // 6 442 057 734 pixels
|
ImageReaderBase.getDestination(null, TYPES.iterator(), 3 * Short.MAX_VALUE, 2 * Short.MAX_VALUE); // 6 442 057 734 pixels
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = IllegalArgumentException.class)
|
@Test(expected = IIOException.class)
|
||||||
public void testGetDestinationStorageExceedsIntegerMax() throws IIOException {
|
public void testGetDestinationStorageExceedsIntegerMax() throws IIOException {
|
||||||
Set<ImageTypeSpecifier> byteTypes = singleton(ImageTypeSpecifier.createFromBufferedImageType(BufferedImage.TYPE_3BYTE_BGR));
|
Set<ImageTypeSpecifier> byteTypes = singleton(ImageTypeSpecifier.createFromBufferedImageType(BufferedImage.TYPE_3BYTE_BGR));
|
||||||
ImageReaderBase.getDestination(null, byteTypes.iterator(), Short.MAX_VALUE, Short.MAX_VALUE); // 1 073 676 289 pixels
|
ImageReaderBase.getDestination(null, byteTypes.iterator(), Short.MAX_VALUE, Short.MAX_VALUE); // 1 073 676 289 pixels
|
||||||
|
|||||||
@@ -35,6 +35,8 @@ import org.junit.Test;
|
|||||||
|
|
||||||
import java.awt.image.*;
|
import java.awt.image.*;
|
||||||
|
|
||||||
|
import static org.hamcrest.CoreMatchers.instanceOf;
|
||||||
|
import static org.hamcrest.MatcherAssert.assertThat;
|
||||||
import static org.junit.Assert.*;
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
public class DiscreteAlphaIndexColorModelTest {
|
public class DiscreteAlphaIndexColorModelTest {
|
||||||
@@ -162,7 +164,7 @@ public class DiscreteAlphaIndexColorModelTest {
|
|||||||
assertEquals(2, sampleModel.getHeight());
|
assertEquals(2, sampleModel.getHeight());
|
||||||
|
|
||||||
assertTrue(colorModel.isCompatibleSampleModel(sampleModel));
|
assertTrue(colorModel.isCompatibleSampleModel(sampleModel));
|
||||||
assertThat(sampleModel, CoreMatchers.is(PixelInterleavedSampleModel.class));
|
assertThat(sampleModel, instanceOf(PixelInterleavedSampleModel.class));
|
||||||
assertThat(sampleModel.getDataType(), CoreMatchers.equalTo(DataBuffer.TYPE_BYTE));
|
assertThat(sampleModel.getDataType(), CoreMatchers.equalTo(DataBuffer.TYPE_BYTE));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -180,7 +182,7 @@ public class DiscreteAlphaIndexColorModelTest {
|
|||||||
assertEquals(2, sampleModel.getHeight());
|
assertEquals(2, sampleModel.getHeight());
|
||||||
|
|
||||||
assertTrue(colorModel.isCompatibleSampleModel(sampleModel));
|
assertTrue(colorModel.isCompatibleSampleModel(sampleModel));
|
||||||
assertThat(sampleModel, CoreMatchers.is(PixelInterleavedSampleModel.class));
|
assertThat(sampleModel, instanceOf(PixelInterleavedSampleModel.class));
|
||||||
assertThat(sampleModel.getDataType(), CoreMatchers.equalTo(DataBuffer.TYPE_USHORT));
|
assertThat(sampleModel.getDataType(), CoreMatchers.equalTo(DataBuffer.TYPE_USHORT));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ import static org.junit.Assert.*;
|
|||||||
*/
|
*/
|
||||||
public class ProviderInfoTest {
|
public class ProviderInfoTest {
|
||||||
@Test
|
@Test
|
||||||
public void testCreateNorma() {
|
public void testCreateNormal() {
|
||||||
new ProviderInfo(Package.getPackage("java.util"));
|
new ProviderInfo(Package.getPackage("java.util"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -31,8 +31,8 @@
|
|||||||
package com.twelvemonkeys.imageio.spi;
|
package com.twelvemonkeys.imageio.spi;
|
||||||
|
|
||||||
import org.hamcrest.Description;
|
import org.hamcrest.Description;
|
||||||
|
import org.hamcrest.TypeSafeMatcher;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.internal.matchers.TypeSafeMatcher;
|
|
||||||
|
|
||||||
import javax.imageio.ImageReader;
|
import javax.imageio.ImageReader;
|
||||||
import javax.imageio.ImageWriter;
|
import javax.imageio.ImageWriter;
|
||||||
@@ -42,6 +42,7 @@ import javax.imageio.spi.ImageWriterSpi;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import static java.util.Arrays.asList;
|
import static java.util.Arrays.asList;
|
||||||
|
import static org.hamcrest.MatcherAssert.assertThat;
|
||||||
import static org.junit.Assert.*;
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -62,52 +63,52 @@ public abstract class ReaderWriterProviderInfoTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void readerClassName() throws Exception {
|
public void readerClassName() {
|
||||||
assertClassExists(providerInfo.readerClassName(), ImageReader.class);
|
assertClassExists(providerInfo.readerClassName(), ImageReader.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void readerSpiClassNames() throws Exception {
|
public void readerSpiClassNames() {
|
||||||
assertClassesExist(providerInfo.readerSpiClassNames(), ImageReaderSpi.class);
|
assertClassesExist(providerInfo.readerSpiClassNames(), ImageReaderSpi.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void inputTypes() throws Exception {
|
public void inputTypes() {
|
||||||
assertNotNull(providerInfo.inputTypes());
|
assertNotNull(providerInfo.inputTypes());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void writerClassName() throws Exception {
|
public void writerClassName() {
|
||||||
assertClassExists(providerInfo.writerClassName(), ImageWriter.class);
|
assertClassExists(providerInfo.writerClassName(), ImageWriter.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void writerSpiClassNames() throws Exception {
|
public void writerSpiClassNames() {
|
||||||
assertClassesExist(providerInfo.writerSpiClassNames(), ImageWriterSpi.class);
|
assertClassesExist(providerInfo.writerSpiClassNames(), ImageWriterSpi.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void outputTypes() throws Exception {
|
public void outputTypes() {
|
||||||
assertNotNull(providerInfo.outputTypes());
|
assertNotNull(providerInfo.outputTypes());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void nativeStreamMetadataFormatClassName() throws Exception {
|
public void nativeStreamMetadataFormatClassName() {
|
||||||
assertClassExists(providerInfo.nativeStreamMetadataFormatClassName(), IIOMetadataFormat.class);
|
assertClassExists(providerInfo.nativeStreamMetadataFormatClassName(), IIOMetadataFormat.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void extraStreamMetadataFormatClassNames() throws Exception {
|
public void extraStreamMetadataFormatClassNames() {
|
||||||
assertClassesExist(providerInfo.extraStreamMetadataFormatClassNames(), IIOMetadataFormat.class);
|
assertClassesExist(providerInfo.extraStreamMetadataFormatClassNames(), IIOMetadataFormat.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void nativeImageMetadataFormatClassName() throws Exception {
|
public void nativeImageMetadataFormatClassName() {
|
||||||
assertClassExists(providerInfo.nativeImageMetadataFormatClassName(), IIOMetadataFormat.class);
|
assertClassExists(providerInfo.nativeImageMetadataFormatClassName(), IIOMetadataFormat.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void extraImageMetadataFormatClassNames() throws Exception {
|
public void extraImageMetadataFormatClassNames() {
|
||||||
assertClassesExist(providerInfo.extraImageMetadataFormatClassNames(), IIOMetadataFormat.class);
|
assertClassesExist(providerInfo.extraImageMetadataFormatClassNames(), IIOMetadataFormat.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -115,7 +116,7 @@ public abstract class ReaderWriterProviderInfoTest {
|
|||||||
public void formatNames() {
|
public void formatNames() {
|
||||||
String[] names = providerInfo.formatNames();
|
String[] names = providerInfo.formatNames();
|
||||||
assertNotNull(names);
|
assertNotNull(names);
|
||||||
assertFalse(names.length == 0);
|
assertNotEquals(0, names.length);
|
||||||
|
|
||||||
List<String> list = asList(names);
|
List<String> list = asList(names);
|
||||||
|
|
||||||
@@ -132,7 +133,7 @@ public abstract class ReaderWriterProviderInfoTest {
|
|||||||
public void suffixes() {
|
public void suffixes() {
|
||||||
String[] suffixes = providerInfo.suffixes();
|
String[] suffixes = providerInfo.suffixes();
|
||||||
assertNotNull(suffixes);
|
assertNotNull(suffixes);
|
||||||
assertFalse(suffixes.length == 0);
|
assertNotEquals(0, suffixes.length);
|
||||||
|
|
||||||
for (String suffix : suffixes) {
|
for (String suffix : suffixes) {
|
||||||
assertNotNull(suffix);
|
assertNotNull(suffix);
|
||||||
@@ -144,7 +145,7 @@ public abstract class ReaderWriterProviderInfoTest {
|
|||||||
public void mimeTypes() {
|
public void mimeTypes() {
|
||||||
String[] mimeTypes = providerInfo.mimeTypes();
|
String[] mimeTypes = providerInfo.mimeTypes();
|
||||||
assertNotNull(mimeTypes);
|
assertNotNull(mimeTypes);
|
||||||
assertFalse(mimeTypes.length == 0);
|
assertNotEquals(0, mimeTypes.length);
|
||||||
|
|
||||||
for (String mimeType : mimeTypes) {
|
for (String mimeType : mimeTypes) {
|
||||||
assertNotNull(mimeType);
|
assertNotNull(mimeType);
|
||||||
|
|||||||
@@ -32,16 +32,19 @@ package com.twelvemonkeys.imageio.stream;
|
|||||||
|
|
||||||
import com.twelvemonkeys.io.ole2.CompoundDocument;
|
import com.twelvemonkeys.io.ole2.CompoundDocument;
|
||||||
import com.twelvemonkeys.io.ole2.Entry;
|
import com.twelvemonkeys.io.ole2.Entry;
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import javax.imageio.stream.ImageInputStream;
|
import javax.imageio.stream.ImageInputStream;
|
||||||
import javax.imageio.stream.MemoryCacheImageInputStream;
|
import javax.imageio.stream.MemoryCacheImageInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
import java.nio.ByteOrder;
|
import java.nio.ByteOrder;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
|
||||||
import static java.util.Arrays.fill;
|
import static java.util.Arrays.fill;
|
||||||
import static org.junit.Assert.*;
|
import static org.junit.Assert.*;
|
||||||
|
import static org.mockito.Mockito.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* BufferedImageInputStreamTest
|
* BufferedImageInputStreamTest
|
||||||
@@ -72,6 +75,257 @@ public class BufferedImageInputStreamTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testReadBit() throws IOException {
|
||||||
|
byte[] bytes = new byte[] {(byte) 0xF0, (byte) 0x0F};
|
||||||
|
|
||||||
|
// Create wrapper stream
|
||||||
|
BufferedImageInputStream stream = new BufferedImageInputStream(new ByteArrayImageInputStream(bytes));
|
||||||
|
|
||||||
|
// Read all bits
|
||||||
|
assertEquals(1, stream.readBit());
|
||||||
|
assertEquals(1, stream.getBitOffset());
|
||||||
|
assertEquals(0, stream.getStreamPosition());
|
||||||
|
|
||||||
|
assertEquals(1, stream.readBit());
|
||||||
|
assertEquals(2, stream.getBitOffset());
|
||||||
|
assertEquals(0, stream.getStreamPosition());
|
||||||
|
|
||||||
|
assertEquals(1, stream.readBit());
|
||||||
|
assertEquals(3, stream.getBitOffset());
|
||||||
|
assertEquals(0, stream.getStreamPosition());
|
||||||
|
|
||||||
|
assertEquals(1, stream.readBit());
|
||||||
|
assertEquals(4, stream.getBitOffset());
|
||||||
|
assertEquals(0, stream.getStreamPosition());
|
||||||
|
|
||||||
|
assertEquals(0, stream.readBit());
|
||||||
|
assertEquals(5, stream.getBitOffset());
|
||||||
|
assertEquals(0, stream.getStreamPosition());
|
||||||
|
|
||||||
|
assertEquals(0, stream.readBit());
|
||||||
|
assertEquals(6, stream.getBitOffset());
|
||||||
|
assertEquals(0, stream.getStreamPosition());
|
||||||
|
|
||||||
|
assertEquals(0, stream.readBit());
|
||||||
|
assertEquals(7, stream.getBitOffset());
|
||||||
|
assertEquals(0, stream.getStreamPosition());
|
||||||
|
|
||||||
|
assertEquals(0, stream.readBit()); // last bit
|
||||||
|
assertEquals(0, stream.getBitOffset());
|
||||||
|
assertEquals(1, stream.getStreamPosition());
|
||||||
|
|
||||||
|
// Full reset, read same sequence again
|
||||||
|
stream.seek(0);
|
||||||
|
assertEquals(0, stream.getBitOffset());
|
||||||
|
assertEquals(0, stream.getStreamPosition());
|
||||||
|
|
||||||
|
assertEquals(1, stream.readBit());
|
||||||
|
assertEquals(1, stream.readBit());
|
||||||
|
assertEquals(1, stream.readBit());
|
||||||
|
assertEquals(1, stream.readBit());
|
||||||
|
assertEquals(0, stream.readBit());
|
||||||
|
assertEquals(0, stream.readBit());
|
||||||
|
assertEquals(0, stream.readBit());
|
||||||
|
assertEquals(0, stream.readBit());
|
||||||
|
|
||||||
|
assertEquals(0, stream.getBitOffset());
|
||||||
|
assertEquals(1, stream.getStreamPosition());
|
||||||
|
|
||||||
|
// Full reset, read partial
|
||||||
|
stream.seek(0);
|
||||||
|
|
||||||
|
assertEquals(1, stream.readBit());
|
||||||
|
assertEquals(1, stream.readBit());
|
||||||
|
|
||||||
|
// Byte reset, read same sequence again
|
||||||
|
stream.setBitOffset(0);
|
||||||
|
|
||||||
|
assertEquals(1, stream.readBit());
|
||||||
|
assertEquals(1, stream.readBit());
|
||||||
|
assertEquals(1, stream.readBit());
|
||||||
|
assertEquals(1, stream.readBit());
|
||||||
|
assertEquals(0, stream.readBit());
|
||||||
|
|
||||||
|
// Byte reset, read partial sequence again
|
||||||
|
stream.setBitOffset(3);
|
||||||
|
|
||||||
|
assertEquals(1, stream.readBit());
|
||||||
|
assertEquals(0, stream.readBit());
|
||||||
|
assertEquals(0, stream.getStreamPosition());
|
||||||
|
|
||||||
|
// Byte reset, read partial sequence again
|
||||||
|
stream.setBitOffset(6);
|
||||||
|
|
||||||
|
assertEquals(0, stream.readBit());
|
||||||
|
assertEquals(0, stream.readBit());
|
||||||
|
assertEquals(1, stream.getStreamPosition());
|
||||||
|
|
||||||
|
// Read all bits, second byte
|
||||||
|
assertEquals(0, stream.readBit());
|
||||||
|
assertEquals(1, stream.getBitOffset());
|
||||||
|
assertEquals(1, stream.getStreamPosition());
|
||||||
|
|
||||||
|
assertEquals(0, stream.readBit());
|
||||||
|
assertEquals(2, stream.getBitOffset());
|
||||||
|
assertEquals(1, stream.getStreamPosition());
|
||||||
|
|
||||||
|
assertEquals(0, stream.readBit());
|
||||||
|
assertEquals(3, stream.getBitOffset());
|
||||||
|
assertEquals(1, stream.getStreamPosition());
|
||||||
|
|
||||||
|
assertEquals(0, stream.readBit());
|
||||||
|
assertEquals(4, stream.getBitOffset());
|
||||||
|
assertEquals(1, stream.getStreamPosition());
|
||||||
|
|
||||||
|
assertEquals(1, stream.readBit());
|
||||||
|
assertEquals(5, stream.getBitOffset());
|
||||||
|
assertEquals(1, stream.getStreamPosition());
|
||||||
|
|
||||||
|
assertEquals(1, stream.readBit());
|
||||||
|
assertEquals(6, stream.getBitOffset());
|
||||||
|
assertEquals(1, stream.getStreamPosition());
|
||||||
|
|
||||||
|
assertEquals(1, stream.readBit());
|
||||||
|
assertEquals(7, stream.getBitOffset());
|
||||||
|
assertEquals(1, stream.getStreamPosition());
|
||||||
|
|
||||||
|
assertEquals(1, stream.readBit()); // last bit
|
||||||
|
assertEquals(0, stream.getBitOffset());
|
||||||
|
assertEquals(2, stream.getStreamPosition());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testReadBits() throws IOException {
|
||||||
|
byte[] bytes = new byte[] {(byte) 0xF0, (byte) 0xCC, (byte) 0xAA};
|
||||||
|
|
||||||
|
// Create wrapper stream
|
||||||
|
BufferedImageInputStream stream = new BufferedImageInputStream(new ByteArrayImageInputStream(bytes));
|
||||||
|
|
||||||
|
// Read all bits, first byte
|
||||||
|
assertEquals(3, stream.readBits(2));
|
||||||
|
assertEquals(2, stream.getBitOffset());
|
||||||
|
assertEquals(0, stream.getStreamPosition());
|
||||||
|
|
||||||
|
assertEquals(3, stream.readBits(2));
|
||||||
|
assertEquals(4, stream.getBitOffset());
|
||||||
|
assertEquals(0, stream.getStreamPosition());
|
||||||
|
|
||||||
|
assertEquals(0, stream.readBits(2));
|
||||||
|
assertEquals(6, stream.getBitOffset());
|
||||||
|
assertEquals(0, stream.getStreamPosition());
|
||||||
|
|
||||||
|
assertEquals(0, stream.readBits(2));
|
||||||
|
assertEquals(0, stream.getBitOffset());
|
||||||
|
assertEquals(1, stream.getStreamPosition());
|
||||||
|
|
||||||
|
// Read all bits, second byte
|
||||||
|
assertEquals(3, stream.readBits(2));
|
||||||
|
assertEquals(2, stream.getBitOffset());
|
||||||
|
assertEquals(1, stream.getStreamPosition());
|
||||||
|
|
||||||
|
assertEquals(0, stream.readBits(2));
|
||||||
|
assertEquals(4, stream.getBitOffset());
|
||||||
|
assertEquals(1, stream.getStreamPosition());
|
||||||
|
|
||||||
|
assertEquals(3, stream.readBits(2));
|
||||||
|
assertEquals(6, stream.getBitOffset());
|
||||||
|
assertEquals(1, stream.getStreamPosition());
|
||||||
|
|
||||||
|
assertEquals(0, stream.readBits(2));
|
||||||
|
assertEquals(0, stream.getBitOffset());
|
||||||
|
assertEquals(2, stream.getStreamPosition());
|
||||||
|
|
||||||
|
// Read all bits, third byte
|
||||||
|
assertEquals(2, stream.readBits(2));
|
||||||
|
assertEquals(2, stream.getBitOffset());
|
||||||
|
assertEquals(2, stream.getStreamPosition());
|
||||||
|
|
||||||
|
assertEquals(2, stream.readBits(2));
|
||||||
|
assertEquals(4, stream.getBitOffset());
|
||||||
|
assertEquals(2, stream.getStreamPosition());
|
||||||
|
|
||||||
|
assertEquals(2, stream.readBits(2));
|
||||||
|
assertEquals(6, stream.getBitOffset());
|
||||||
|
assertEquals(2, stream.getStreamPosition());
|
||||||
|
|
||||||
|
assertEquals(2, stream.readBits(2));
|
||||||
|
assertEquals(0, stream.getBitOffset());
|
||||||
|
assertEquals(3, stream.getStreamPosition());
|
||||||
|
|
||||||
|
// Full reset, read same sequence again
|
||||||
|
stream.seek(0);
|
||||||
|
assertEquals(0, stream.getBitOffset());
|
||||||
|
assertEquals(0, stream.getStreamPosition());
|
||||||
|
|
||||||
|
// Read all bits, increasing size
|
||||||
|
assertEquals(7, stream.readBits(3)); // 111
|
||||||
|
assertEquals(3, stream.getBitOffset());
|
||||||
|
assertEquals(0, stream.getStreamPosition());
|
||||||
|
|
||||||
|
assertEquals(8, stream.readBits(4)); // 1000
|
||||||
|
assertEquals(7, stream.getBitOffset());
|
||||||
|
assertEquals(0, stream.getStreamPosition());
|
||||||
|
|
||||||
|
assertEquals(12, stream.readBits(5)); // 01100
|
||||||
|
assertEquals(4, stream.getBitOffset());
|
||||||
|
assertEquals(1, stream.getStreamPosition());
|
||||||
|
|
||||||
|
assertEquals(50, stream.readBits(6)); // 110010
|
||||||
|
assertEquals(2, stream.getBitOffset());
|
||||||
|
assertEquals(2, stream.getStreamPosition());
|
||||||
|
|
||||||
|
assertEquals(42, stream.readBits(6)); // 101010
|
||||||
|
assertEquals(0, stream.getBitOffset());
|
||||||
|
assertEquals(3, stream.getStreamPosition());
|
||||||
|
|
||||||
|
// Full reset, read same sequence again
|
||||||
|
stream.seek(0);
|
||||||
|
assertEquals(0, stream.getBitOffset());
|
||||||
|
assertEquals(0, stream.getStreamPosition());
|
||||||
|
|
||||||
|
// Read all bits multi-byte
|
||||||
|
assertEquals(0xF0C, stream.readBits(12)); // 111100001100
|
||||||
|
assertEquals(4, stream.getBitOffset());
|
||||||
|
assertEquals(1, stream.getStreamPosition());
|
||||||
|
|
||||||
|
assertEquals(0xCAA, stream.readBits(12)); // 110010101010
|
||||||
|
assertEquals(0, stream.getBitOffset());
|
||||||
|
assertEquals(3, stream.getStreamPosition());
|
||||||
|
|
||||||
|
// Full reset, read same sequence again, all bits in one go
|
||||||
|
stream.seek(0);
|
||||||
|
assertEquals(0, stream.getBitOffset());
|
||||||
|
assertEquals(0, stream.getStreamPosition());
|
||||||
|
|
||||||
|
assertEquals(0xF0CCAA, stream.readBits(24));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testReadBitsRandom() throws IOException {
|
||||||
|
long value = random.nextLong();
|
||||||
|
byte[] bytes = new byte[8];
|
||||||
|
ByteBuffer.wrap(bytes).putLong(value);
|
||||||
|
|
||||||
|
// Create wrapper stream
|
||||||
|
BufferedImageInputStream stream = new BufferedImageInputStream(new ByteArrayImageInputStream(bytes));
|
||||||
|
|
||||||
|
for (int i = 1; i < 64; i++) {
|
||||||
|
stream.seek(0);
|
||||||
|
assertEquals(i + " bits differ", value >>> (64L - i), stream.readBits(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testClose() throws IOException {
|
||||||
|
// Create wrapper stream
|
||||||
|
ImageInputStream mock = mock(ImageInputStream.class);
|
||||||
|
BufferedImageInputStream stream = new BufferedImageInputStream(mock);
|
||||||
|
|
||||||
|
stream.close();
|
||||||
|
verify(mock, never()).close();
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: Write other tests
|
// TODO: Write other tests
|
||||||
|
|
||||||
// TODO: Create test that exposes read += -1 (eof) bug
|
// TODO: Create test that exposes read += -1 (eof) bug
|
||||||
|
|||||||
@@ -0,0 +1,16 @@
|
|||||||
|
package com.twelvemonkeys.imageio.stream;
|
||||||
|
|
||||||
|
import javax.imageio.spi.ImageInputStreamSpi;
|
||||||
|
|
||||||
|
public class ByteArrayImageInputStreamSpiTest extends ImageInputStreamSpiTest<byte[]> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected ImageInputStreamSpi createProvider() {
|
||||||
|
return new ByteArrayImageInputStreamSpi();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected byte[] createInput() {
|
||||||
|
return new byte[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,84 @@
|
|||||||
|
package com.twelvemonkeys.imageio.stream;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import javax.imageio.ImageIO;
|
||||||
|
import javax.imageio.spi.ImageInputStreamSpi;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.lang.reflect.ParameterizedType;
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
|
abstract class ImageInputStreamSpiTest<T> {
|
||||||
|
private final ImageInputStreamSpi provider = createProvider();
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
private final Class<T> inputClass = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
|
||||||
|
|
||||||
|
protected abstract ImageInputStreamSpi createProvider();
|
||||||
|
|
||||||
|
protected abstract T createInput();
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testInputClass() {
|
||||||
|
assertEquals(inputClass, provider.getInputClass());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testVendorName() {
|
||||||
|
assertNotNull(provider.getVendorName());
|
||||||
|
assertEquals("TwelveMonkeys", provider.getVendorName());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testVersion() {
|
||||||
|
assertNotNull(provider.getVersion());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDescription() {
|
||||||
|
assertNotNull(provider.getDescription(null));
|
||||||
|
assertNotNull(provider.getDescription(Locale.ENGLISH));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = IllegalArgumentException.class)
|
||||||
|
public void createNull() throws IOException {
|
||||||
|
provider.createInputStreamInstance(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = IllegalArgumentException.class)
|
||||||
|
public void createNullCached() throws IOException {
|
||||||
|
provider.createInputStreamInstance(null, true, ImageIO.getCacheDirectory());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void createCachedNullCache() throws IOException {
|
||||||
|
try {
|
||||||
|
provider.createInputStreamInstance(createInput(), true, null);
|
||||||
|
}
|
||||||
|
catch (IllegalArgumentException expected) {
|
||||||
|
// All good
|
||||||
|
assertFalse(provider.needsCacheFile());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void create() throws IOException {
|
||||||
|
assertNotNull(provider.createInputStreamInstance(createInput()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void createCached() throws IOException {
|
||||||
|
if (provider.canUseCacheFile()) {
|
||||||
|
assertNotNull(provider.createInputStreamInstance(createInput(), true, ImageIO.getCacheDirectory()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void createNonCached() throws IOException {
|
||||||
|
if (!provider.needsCacheFile()) {
|
||||||
|
assertNotNull(provider.createInputStreamInstance(createInput(), false, ImageIO.getCacheDirectory()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
package com.twelvemonkeys.imageio.stream;
|
||||||
|
|
||||||
|
import com.twelvemonkeys.imageio.spi.ProviderInfo;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertNotNull;
|
||||||
|
|
||||||
|
public class StreamProviderInfoTest {
|
||||||
|
private final ProviderInfo providerInfo = new StreamProviderInfo();
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testVendorName() {
|
||||||
|
assertNotNull(providerInfo.getVendorName());
|
||||||
|
assertEquals("TwelveMonkeys", providerInfo.getVendorName());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testVersion() {
|
||||||
|
assertNotNull(providerInfo.getVersion());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
package com.twelvemonkeys.imageio.stream;
|
||||||
|
|
||||||
|
import javax.imageio.spi.ImageInputStreamSpi;
|
||||||
|
import java.net.URL;
|
||||||
|
|
||||||
|
public class URLImageInputStreamSpiTest extends ImageInputStreamSpiTest<URL> {
|
||||||
|
@Override
|
||||||
|
protected ImageInputStreamSpi createProvider() {
|
||||||
|
return new URLImageInputStreamSpi();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected URL createInput() {
|
||||||
|
return getClass().getResource("/empty-stream.txt");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -31,6 +31,7 @@
|
|||||||
package com.twelvemonkeys.imageio.util;
|
package com.twelvemonkeys.imageio.util;
|
||||||
|
|
||||||
import com.twelvemonkeys.imageio.stream.URLImageInputStreamSpi;
|
import com.twelvemonkeys.imageio.stream.URLImageInputStreamSpi;
|
||||||
|
|
||||||
import org.junit.Ignore;
|
import org.junit.Ignore;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.mockito.InOrder;
|
import org.mockito.InOrder;
|
||||||
@@ -49,6 +50,7 @@ import java.awt.image.RenderedImage;
|
|||||||
import java.awt.image.SampleModel;
|
import java.awt.image.SampleModel;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.lang.reflect.ParameterizedType;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
@@ -69,27 +71,26 @@ public abstract class ImageReaderAbstractTest<T extends ImageReader> {
|
|||||||
// TODO: Should we really test if the provider is installed?
|
// TODO: Should we really test if the provider is installed?
|
||||||
// - Pro: Tests the META-INF/services config
|
// - Pro: Tests the META-INF/services config
|
||||||
// - Con: Not all providers should be installed at runtime...
|
// - Con: Not all providers should be installed at runtime...
|
||||||
|
// TODO: Create own subclass for testing the Spis?
|
||||||
|
|
||||||
static {
|
static {
|
||||||
IIORegistry.getDefaultInstance().registerServiceProvider(new URLImageInputStreamSpi());
|
IIORegistry.getDefaultInstance().registerServiceProvider(new URLImageInputStreamSpi());
|
||||||
ImageIO.setUseCache(false);
|
ImageIO.setUseCache(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract List<TestData> getTestData();
|
@SuppressWarnings("unchecked")
|
||||||
|
private final Class<T> readerClass = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
|
||||||
|
|
||||||
|
protected final ImageReaderSpi provider = createProvider();
|
||||||
|
|
||||||
protected abstract ImageReaderSpi createProvider();
|
protected abstract ImageReaderSpi createProvider();
|
||||||
|
|
||||||
protected abstract Class<T> getReaderClass();
|
protected final T createReader() throws IOException {
|
||||||
|
return readerClass.cast(provider.createReaderInstance(null));
|
||||||
protected T createReader() {
|
|
||||||
try {
|
|
||||||
return getReaderClass().newInstance();
|
|
||||||
}
|
|
||||||
catch (InstantiationException | IllegalAccessException e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected abstract List<TestData> getTestData();
|
||||||
|
|
||||||
protected abstract List<String> getFormatNames();
|
protected abstract List<String> getFormatNames();
|
||||||
|
|
||||||
protected abstract List<String> getSuffixes();
|
protected abstract List<String> getSuffixes();
|
||||||
@@ -101,9 +102,7 @@ public abstract class ImageReaderAbstractTest<T extends ImageReader> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected static void failBecause(String message, Throwable exception) {
|
protected static void failBecause(String message, Throwable exception) {
|
||||||
AssertionError error = new AssertionError(message);
|
throw new AssertionError(message, exception);
|
||||||
error.initCause(exception);
|
|
||||||
throw error;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void assertProviderInstalledForName(final String pFormat, final Class<? extends ImageReader> pReaderClass) {
|
protected void assertProviderInstalledForName(final String pFormat, final Class<? extends ImageReader> pReaderClass) {
|
||||||
@@ -123,17 +122,20 @@ public abstract class ImageReaderAbstractTest<T extends ImageReader> {
|
|||||||
boolean found = false;
|
boolean found = false;
|
||||||
while (pReaders.hasNext()) {
|
while (pReaders.hasNext()) {
|
||||||
ImageReader reader = pReaders.next();
|
ImageReader reader = pReaders.next();
|
||||||
if (reader.getClass() == pReaderClass) {
|
if (reader.getClass() == pReaderClass && isOurProvider(reader.getOriginatingProvider())) {
|
||||||
found = true;
|
found = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
assertTrue(String.format("%s not installed for %s", pReaderClass.getSimpleName(), pFormat), found);
|
assertTrue(String.format("%s not provided by %s for '%s'", pReaderClass.getSimpleName(), provider.getClass().getSimpleName(), pFormat), found);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isOurProvider(final ImageReaderSpi spi) {
|
||||||
|
return provider.getClass().isInstance(spi);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testProviderInstalledForNames() {
|
public void testProviderInstalledForNames() {
|
||||||
Class<? extends ImageReader> readerClass = getReaderClass();
|
|
||||||
for (String name : getFormatNames()) {
|
for (String name : getFormatNames()) {
|
||||||
assertProviderInstalledForName(name, readerClass);
|
assertProviderInstalledForName(name, readerClass);
|
||||||
}
|
}
|
||||||
@@ -141,7 +143,6 @@ public abstract class ImageReaderAbstractTest<T extends ImageReader> {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testProviderInstalledForSuffixes() {
|
public void testProviderInstalledForSuffixes() {
|
||||||
Class<? extends ImageReader> readerClass = getReaderClass();
|
|
||||||
for (String suffix : getSuffixes()) {
|
for (String suffix : getSuffixes()) {
|
||||||
assertProviderInstalledForSuffix(suffix, readerClass);
|
assertProviderInstalledForSuffix(suffix, readerClass);
|
||||||
}
|
}
|
||||||
@@ -149,7 +150,6 @@ public abstract class ImageReaderAbstractTest<T extends ImageReader> {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testProviderInstalledForMIMETypes() {
|
public void testProviderInstalledForMIMETypes() {
|
||||||
Class<? extends ImageReader> readerClass = getReaderClass();
|
|
||||||
for (String type : getMIMETypes()) {
|
for (String type : getMIMETypes()) {
|
||||||
assertProviderInstalledForMIMEType(type, readerClass);
|
assertProviderInstalledForMIMEType(type, readerClass);
|
||||||
}
|
}
|
||||||
@@ -159,7 +159,6 @@ public abstract class ImageReaderAbstractTest<T extends ImageReader> {
|
|||||||
public void testProviderCanRead() throws IOException {
|
public void testProviderCanRead() throws IOException {
|
||||||
List<TestData> testData = getTestData();
|
List<TestData> testData = getTestData();
|
||||||
|
|
||||||
ImageReaderSpi provider = createProvider();
|
|
||||||
for (TestData data : testData) {
|
for (TestData data : testData) {
|
||||||
ImageInputStream stream = data.getInputStream();
|
ImageInputStream stream = data.getInputStream();
|
||||||
assertNotNull(stream);
|
assertNotNull(stream);
|
||||||
@@ -172,7 +171,7 @@ public abstract class ImageReaderAbstractTest<T extends ImageReader> {
|
|||||||
boolean canRead = false;
|
boolean canRead = false;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
canRead = createProvider().canDecodeInput(null);
|
canRead = provider.canDecodeInput(null);
|
||||||
}
|
}
|
||||||
catch (IllegalArgumentException ignore) {
|
catch (IllegalArgumentException ignore) {
|
||||||
}
|
}
|
||||||
@@ -187,7 +186,7 @@ public abstract class ImageReaderAbstractTest<T extends ImageReader> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSetInput() {
|
public void testSetInput() throws IOException {
|
||||||
// Should just pass with no exceptions
|
// Should just pass with no exceptions
|
||||||
ImageReader reader = createReader();
|
ImageReader reader = createReader();
|
||||||
assertNotNull(reader);
|
assertNotNull(reader);
|
||||||
@@ -200,7 +199,7 @@ public abstract class ImageReaderAbstractTest<T extends ImageReader> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSetInputNull() {
|
public void testSetInputNull() throws IOException {
|
||||||
// Should just pass with no exceptions
|
// Should just pass with no exceptions
|
||||||
ImageReader reader = createReader();
|
ImageReader reader = createReader();
|
||||||
assertNotNull(reader);
|
assertNotNull(reader);
|
||||||
@@ -209,7 +208,7 @@ public abstract class ImageReaderAbstractTest<T extends ImageReader> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testRead() {
|
public void testRead() throws IOException {
|
||||||
ImageReader reader = createReader();
|
ImageReader reader = createReader();
|
||||||
|
|
||||||
for (TestData data : getTestData()) {
|
for (TestData data : getTestData()) {
|
||||||
@@ -243,7 +242,7 @@ public abstract class ImageReaderAbstractTest<T extends ImageReader> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testReadIndexNegative() {
|
public void testReadIndexNegative() throws IOException {
|
||||||
ImageReader reader = createReader();
|
ImageReader reader = createReader();
|
||||||
TestData data = getTestData().get(0);
|
TestData data = getTestData().get(0);
|
||||||
reader.setInput(data.getInputStream());
|
reader.setInput(data.getInputStream());
|
||||||
@@ -264,7 +263,7 @@ public abstract class ImageReaderAbstractTest<T extends ImageReader> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testReadIndexOutOfBounds() {
|
public void testReadIndexOutOfBounds() throws IOException {
|
||||||
ImageReader reader = createReader();
|
ImageReader reader = createReader();
|
||||||
TestData data = getTestData().get(0);
|
TestData data = getTestData().get(0);
|
||||||
reader.setInput(data.getInputStream());
|
reader.setInput(data.getInputStream());
|
||||||
@@ -285,7 +284,7 @@ public abstract class ImageReaderAbstractTest<T extends ImageReader> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testReadNoInput() {
|
public void testReadNoInput() throws IOException {
|
||||||
ImageReader reader = createReader();
|
ImageReader reader = createReader();
|
||||||
// Do not set input
|
// Do not set input
|
||||||
|
|
||||||
@@ -325,7 +324,7 @@ public abstract class ImageReaderAbstractTest<T extends ImageReader> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testReadIndexNegativeWithParam() {
|
public void testReadIndexNegativeWithParam() throws IOException {
|
||||||
ImageReader reader = createReader();
|
ImageReader reader = createReader();
|
||||||
TestData data = getTestData().get(0);
|
TestData data = getTestData().get(0);
|
||||||
reader.setInput(data.getInputStream());
|
reader.setInput(data.getInputStream());
|
||||||
@@ -347,7 +346,7 @@ public abstract class ImageReaderAbstractTest<T extends ImageReader> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testReadIndexOutOfBoundsWithParam() {
|
public void testReadIndexOutOfBoundsWithParam() throws IOException {
|
||||||
ImageReader reader = createReader();
|
ImageReader reader = createReader();
|
||||||
TestData data = getTestData().get(0);
|
TestData data = getTestData().get(0);
|
||||||
reader.setInput(data.getInputStream());
|
reader.setInput(data.getInputStream());
|
||||||
@@ -369,7 +368,7 @@ public abstract class ImageReaderAbstractTest<T extends ImageReader> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testReadNoInputWithParam() {
|
public void testReadNoInputWithParam() throws IOException {
|
||||||
ImageReader reader = createReader();
|
ImageReader reader = createReader();
|
||||||
// Do not set input
|
// Do not set input
|
||||||
|
|
||||||
@@ -390,7 +389,7 @@ public abstract class ImageReaderAbstractTest<T extends ImageReader> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testReadWithNewParam() {
|
public void testReadWithNewParam() throws IOException {
|
||||||
ImageReader reader = createReader();
|
ImageReader reader = createReader();
|
||||||
TestData data = getTestData().get(0);
|
TestData data = getTestData().get(0);
|
||||||
reader.setInput(data.getInputStream());
|
reader.setInput(data.getInputStream());
|
||||||
@@ -411,7 +410,7 @@ public abstract class ImageReaderAbstractTest<T extends ImageReader> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testReadWithDefaultParam() {
|
public void testReadWithDefaultParam() throws IOException {
|
||||||
ImageReader reader = createReader();
|
ImageReader reader = createReader();
|
||||||
TestData data = getTestData().get(0);
|
TestData data = getTestData().get(0);
|
||||||
reader.setInput(data.getInputStream());
|
reader.setInput(data.getInputStream());
|
||||||
@@ -432,7 +431,7 @@ public abstract class ImageReaderAbstractTest<T extends ImageReader> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testReadWithNullParam() {
|
public void testReadWithNullParam() throws IOException {
|
||||||
ImageReader reader = createReader();
|
ImageReader reader = createReader();
|
||||||
TestData data = getTestData().get(0);
|
TestData data = getTestData().get(0);
|
||||||
reader.setInput(data.getInputStream());
|
reader.setInput(data.getInputStream());
|
||||||
@@ -453,7 +452,7 @@ public abstract class ImageReaderAbstractTest<T extends ImageReader> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testReadWithSizeParam() {
|
public void testReadWithSizeParam() throws IOException {
|
||||||
ImageReader reader = createReader();
|
ImageReader reader = createReader();
|
||||||
TestData data = getTestData().get(0);
|
TestData data = getTestData().get(0);
|
||||||
reader.setInput(data.getInputStream());
|
reader.setInput(data.getInputStream());
|
||||||
@@ -479,7 +478,7 @@ public abstract class ImageReaderAbstractTest<T extends ImageReader> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testReadWithSubsampleParamDimensions() {
|
public void testReadWithSubsampleParamDimensions() throws IOException {
|
||||||
ImageReader reader = createReader();
|
ImageReader reader = createReader();
|
||||||
TestData data = getTestData().get(0);
|
TestData data = getTestData().get(0);
|
||||||
reader.setInput(data.getInputStream());
|
reader.setInput(data.getInputStream());
|
||||||
@@ -530,6 +529,7 @@ public abstract class ImageReaderAbstractTest<T extends ImageReader> {
|
|||||||
// TODO: Subsample all test data
|
// TODO: Subsample all test data
|
||||||
// TODO: Subsample with varying ratios and offsets
|
// TODO: Subsample with varying ratios and offsets
|
||||||
|
|
||||||
|
@SuppressWarnings("SameParameterValue")
|
||||||
protected final void assertSubsampledImageDataEquals(String message, BufferedImage expected, BufferedImage actual, ImageReadParam param) throws IOException {
|
protected final void assertSubsampledImageDataEquals(String message, BufferedImage expected, BufferedImage actual, ImageReadParam param) throws IOException {
|
||||||
assertNotNull("Expected image was null", expected);
|
assertNotNull("Expected image was null", expected);
|
||||||
assertNotNull("Actual image was null!", actual);
|
assertNotNull("Actual image was null!", actual);
|
||||||
@@ -595,7 +595,7 @@ public abstract class ImageReaderAbstractTest<T extends ImageReader> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testReadWithSourceRegionParam() {
|
public void testReadWithSourceRegionParam() throws IOException {
|
||||||
ImageReader reader = createReader();
|
ImageReader reader = createReader();
|
||||||
TestData data = getTestData().get(0);
|
TestData data = getTestData().get(0);
|
||||||
reader.setInput(data.getInputStream());
|
reader.setInput(data.getInputStream());
|
||||||
@@ -626,40 +626,53 @@ public abstract class ImageReaderAbstractTest<T extends ImageReader> {
|
|||||||
|
|
||||||
protected void assertReadWithSourceRegionParamEqualImage(final Rectangle r, final TestData data, final int imageIndex) throws IOException {
|
protected void assertReadWithSourceRegionParamEqualImage(final Rectangle r, final TestData data, final int imageIndex) throws IOException {
|
||||||
ImageReader reader = createReader();
|
ImageReader reader = createReader();
|
||||||
reader.setInput(data.getInputStream());
|
try (ImageInputStream inputStream = data.getInputStream()) {
|
||||||
ImageReadParam param = reader.getDefaultReadParam();
|
reader.setInput(inputStream);
|
||||||
|
ImageReadParam param = reader.getDefaultReadParam();
|
||||||
|
|
||||||
// Read full image and get sub image for comparison
|
// Read full image and get sub image for comparison
|
||||||
final BufferedImage roi = reader.read(imageIndex, param).getSubimage(r.x, r.y, r.width, r.height);
|
BufferedImage original = reader.read(imageIndex, param);
|
||||||
|
final BufferedImage roi = original.getSubimage(r.x, r.y, r.width, r.height);
|
||||||
|
|
||||||
param.setSourceRegion(r);
|
param.setSourceRegion(r);
|
||||||
|
|
||||||
final BufferedImage image = reader.read(imageIndex, param);
|
final BufferedImage image = reader.read(imageIndex, param);
|
||||||
|
|
||||||
// try {
|
assertNotNull("Image was null!", image);
|
||||||
// SwingUtilities.invokeAndWait(new Runnable() {
|
assertEquals("Read image has wrong width: " + image.getWidth(), r.width, image.getWidth());
|
||||||
// public void run() {
|
assertEquals("Read image has wrong height: " + image.getHeight(), r.height, image.getHeight());
|
||||||
// JPanel panel = new JPanel(new FlowLayout());
|
|
||||||
// panel.add(new JLabel(new BufferedImageIcon(roi, r.width * 10, r.height * 10, true)));
|
|
||||||
// panel.add(new JLabel(new BufferedImageIcon(image, r.width * 10, r.height * 10, true)));
|
|
||||||
// JOptionPane.showConfirmDialog(null, panel);
|
|
||||||
// }
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
// catch (Exception e) {
|
|
||||||
// throw new RuntimeException(e);
|
|
||||||
// }
|
|
||||||
|
|
||||||
assertNotNull("Image was null!", image);
|
try {
|
||||||
assertEquals("Read image has wrong width: " + image.getWidth(), r.width, image.getWidth());
|
assertImageDataEquals("Images differ", roi, image);
|
||||||
assertEquals("Read image has wrong height: " + image.getHeight(), r.height, image.getHeight());
|
}
|
||||||
assertImageDataEquals("Images differ", roi, image);
|
catch (AssertionError e) {
|
||||||
|
File tempExpected = File.createTempFile("junit-expected-", ".png");
|
||||||
|
System.err.println("tempExpected.getAbsolutePath(): " + tempExpected.getAbsolutePath());
|
||||||
|
|
||||||
reader.dispose();
|
Graphics2D graphics = original.createGraphics();
|
||||||
|
try {
|
||||||
|
graphics.setColor(Color.RED);
|
||||||
|
graphics.draw(r);
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
graphics.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
ImageIO.write(original, "PNG", tempExpected);
|
||||||
|
File tempActual = File.createTempFile("junit-actual-", ".png");
|
||||||
|
System.err.println("tempActual.getAbsolutePath(): " + tempActual.getAbsolutePath());
|
||||||
|
ImageIO.write(image, "PNG", tempActual);
|
||||||
|
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
reader.dispose();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testReadWithSizeAndSourceRegionParam() {
|
public void testReadWithSizeAndSourceRegionParam() throws IOException {
|
||||||
// TODO: Is this test correct???
|
// TODO: Is this test correct???
|
||||||
ImageReader reader = createReader();
|
ImageReader reader = createReader();
|
||||||
TestData data = getTestData().get(0);
|
TestData data = getTestData().get(0);
|
||||||
@@ -690,7 +703,7 @@ public abstract class ImageReaderAbstractTest<T extends ImageReader> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testReadWithSubsampleAndSourceRegionParam() {
|
public void testReadWithSubsampleAndSourceRegionParam() throws IOException {
|
||||||
// NOTE: The "standard" (com.sun.imageio.plugin.*) ImageReaders pass
|
// NOTE: The "standard" (com.sun.imageio.plugin.*) ImageReaders pass
|
||||||
// this test, so the test should be correct...
|
// this test, so the test should be correct...
|
||||||
ImageReader reader = createReader();
|
ImageReader reader = createReader();
|
||||||
@@ -716,7 +729,7 @@ public abstract class ImageReaderAbstractTest<T extends ImageReader> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testReadAsRenderedImageIndexNegative() {
|
public void testReadAsRenderedImageIndexNegative() throws IOException {
|
||||||
ImageReader reader = createReader();
|
ImageReader reader = createReader();
|
||||||
TestData data = getTestData().get(0);
|
TestData data = getTestData().get(0);
|
||||||
reader.setInput(data.getInputStream());
|
reader.setInput(data.getInputStream());
|
||||||
@@ -739,7 +752,7 @@ public abstract class ImageReaderAbstractTest<T extends ImageReader> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testReadAsRenderedImageIndexOutOfBounds() throws IIOException {
|
public void testReadAsRenderedImageIndexOutOfBounds() throws IOException {
|
||||||
ImageReader reader = createReader();
|
ImageReader reader = createReader();
|
||||||
TestData data = getTestData().get(0);
|
TestData data = getTestData().get(0);
|
||||||
reader.setInput(data.getInputStream());
|
reader.setInput(data.getInputStream());
|
||||||
@@ -766,7 +779,7 @@ public abstract class ImageReaderAbstractTest<T extends ImageReader> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testReadAsRenderedImageNoInput() {
|
public void testReadAsRenderedImageNoInput() throws IOException {
|
||||||
ImageReader reader = createReader();
|
ImageReader reader = createReader();
|
||||||
// Do not set input
|
// Do not set input
|
||||||
|
|
||||||
@@ -788,7 +801,7 @@ public abstract class ImageReaderAbstractTest<T extends ImageReader> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testReadAsRenderedImage() {
|
public void testReadAsRenderedImage() throws IOException {
|
||||||
ImageReader reader = createReader();
|
ImageReader reader = createReader();
|
||||||
TestData data = getTestData().get(0);
|
TestData data = getTestData().get(0);
|
||||||
reader.setInput(data.getInputStream());
|
reader.setInput(data.getInputStream());
|
||||||
@@ -811,7 +824,7 @@ public abstract class ImageReaderAbstractTest<T extends ImageReader> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testReadAsRenderedImageWithDefaultParam() {
|
public void testReadAsRenderedImageWithDefaultParam() throws IOException {
|
||||||
ImageReader reader = createReader();
|
ImageReader reader = createReader();
|
||||||
TestData data = getTestData().get(0);
|
TestData data = getTestData().get(0);
|
||||||
reader.setInput(data.getInputStream());
|
reader.setInput(data.getInputStream());
|
||||||
@@ -834,7 +847,7 @@ public abstract class ImageReaderAbstractTest<T extends ImageReader> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGetDefaultReadParam() {
|
public void testGetDefaultReadParam() throws IOException {
|
||||||
ImageReader reader = createReader();
|
ImageReader reader = createReader();
|
||||||
ImageReadParam param = reader.getDefaultReadParam();
|
ImageReadParam param = reader.getDefaultReadParam();
|
||||||
assertNotNull(param);
|
assertNotNull(param);
|
||||||
@@ -842,7 +855,7 @@ public abstract class ImageReaderAbstractTest<T extends ImageReader> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGetFormatName() {
|
public void testGetFormatName() throws IOException {
|
||||||
ImageReader reader = createReader();
|
ImageReader reader = createReader();
|
||||||
TestData data = getTestData().get(0);
|
TestData data = getTestData().get(0);
|
||||||
reader.setInput(data.getInputStream());
|
reader.setInput(data.getInputStream());
|
||||||
@@ -858,7 +871,7 @@ public abstract class ImageReaderAbstractTest<T extends ImageReader> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGetMinIndex() {
|
public void testGetMinIndex() throws IOException {
|
||||||
ImageReader reader = createReader();
|
ImageReader reader = createReader();
|
||||||
TestData data = getTestData().get(0);
|
TestData data = getTestData().get(0);
|
||||||
reader.setInput(data.getInputStream());
|
reader.setInput(data.getInputStream());
|
||||||
@@ -874,7 +887,7 @@ public abstract class ImageReaderAbstractTest<T extends ImageReader> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGetMinIndexNoInput() {
|
public void testGetMinIndexNoInput() throws IOException {
|
||||||
ImageReader reader = createReader();
|
ImageReader reader = createReader();
|
||||||
int num = 0;
|
int num = 0;
|
||||||
|
|
||||||
@@ -888,7 +901,7 @@ public abstract class ImageReaderAbstractTest<T extends ImageReader> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGetNumImages() {
|
public void testGetNumImages() throws IOException {
|
||||||
ImageReader reader = createReader();
|
ImageReader reader = createReader();
|
||||||
TestData data = getTestData().get(0);
|
TestData data = getTestData().get(0);
|
||||||
reader.setInput(data.getInputStream());
|
reader.setInput(data.getInputStream());
|
||||||
@@ -917,7 +930,7 @@ public abstract class ImageReaderAbstractTest<T extends ImageReader> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGetNumImagesNoInput() {
|
public void testGetNumImagesNoInput() throws IOException {
|
||||||
ImageReader reader = createReader();
|
ImageReader reader = createReader();
|
||||||
int num = -1;
|
int num = -1;
|
||||||
|
|
||||||
@@ -945,7 +958,7 @@ public abstract class ImageReaderAbstractTest<T extends ImageReader> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGetWidth() {
|
public void testGetWidth() throws IOException {
|
||||||
ImageReader reader = createReader();
|
ImageReader reader = createReader();
|
||||||
TestData data = getTestData().get(0);
|
TestData data = getTestData().get(0);
|
||||||
reader.setInput(data.getInputStream());
|
reader.setInput(data.getInputStream());
|
||||||
@@ -962,7 +975,7 @@ public abstract class ImageReaderAbstractTest<T extends ImageReader> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGetWidthIndexOutOfBounds() {
|
public void testGetWidthIndexOutOfBounds() throws IOException {
|
||||||
ImageReader reader = createReader();
|
ImageReader reader = createReader();
|
||||||
TestData data = getTestData().get(0);
|
TestData data = getTestData().get(0);
|
||||||
reader.setInput(data.getInputStream());
|
reader.setInput(data.getInputStream());
|
||||||
@@ -983,13 +996,13 @@ public abstract class ImageReaderAbstractTest<T extends ImageReader> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGetWidthNoInput() {
|
public void testGetWidthNoInput() throws IOException {
|
||||||
ImageReader reader = createReader();
|
ImageReader reader = createReader();
|
||||||
|
|
||||||
int width = 0;
|
int width = 0;
|
||||||
try {
|
try {
|
||||||
width = reader.getWidth(0);
|
width = reader.getWidth(0);
|
||||||
fail("Width read without imput");
|
fail("Width read without input");
|
||||||
}
|
}
|
||||||
catch (IllegalStateException ignore) {
|
catch (IllegalStateException ignore) {
|
||||||
}
|
}
|
||||||
@@ -1001,7 +1014,7 @@ public abstract class ImageReaderAbstractTest<T extends ImageReader> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGetHeight() {
|
public void testGetHeight() throws IOException {
|
||||||
ImageReader reader = createReader();
|
ImageReader reader = createReader();
|
||||||
TestData data = getTestData().get(0);
|
TestData data = getTestData().get(0);
|
||||||
reader.setInput(data.getInputStream());
|
reader.setInput(data.getInputStream());
|
||||||
@@ -1018,13 +1031,13 @@ public abstract class ImageReaderAbstractTest<T extends ImageReader> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGetHeightNoInput() {
|
public void testGetHeightNoInput() throws IOException {
|
||||||
ImageReader reader = createReader();
|
ImageReader reader = createReader();
|
||||||
|
|
||||||
int height = 0;
|
int height = 0;
|
||||||
try {
|
try {
|
||||||
height = reader.getHeight(0);
|
height = reader.getHeight(0);
|
||||||
fail("height read without imput");
|
fail("height read without input");
|
||||||
}
|
}
|
||||||
catch (IllegalStateException ignore) {
|
catch (IllegalStateException ignore) {
|
||||||
}
|
}
|
||||||
@@ -1036,7 +1049,7 @@ public abstract class ImageReaderAbstractTest<T extends ImageReader> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGetHeightIndexOutOfBounds() {
|
public void testGetHeightIndexOutOfBounds() throws IOException {
|
||||||
ImageReader reader = createReader();
|
ImageReader reader = createReader();
|
||||||
TestData data = getTestData().get(0);
|
TestData data = getTestData().get(0);
|
||||||
reader.setInput(data.getInputStream());
|
reader.setInput(data.getInputStream());
|
||||||
@@ -1057,7 +1070,7 @@ public abstract class ImageReaderAbstractTest<T extends ImageReader> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGetAspectRatio() {
|
public void testGetAspectRatio() throws IOException {
|
||||||
ImageReader reader = createReader();
|
ImageReader reader = createReader();
|
||||||
TestData data = getTestData().get(0);
|
TestData data = getTestData().get(0);
|
||||||
reader.setInput(data.getInputStream());
|
reader.setInput(data.getInputStream());
|
||||||
@@ -1075,7 +1088,7 @@ public abstract class ImageReaderAbstractTest<T extends ImageReader> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGetAspectRatioNoInput() {
|
public void testGetAspectRatioNoInput() throws IOException {
|
||||||
ImageReader reader = createReader();
|
ImageReader reader = createReader();
|
||||||
|
|
||||||
float aspectRatio = 0f;
|
float aspectRatio = 0f;
|
||||||
@@ -1093,7 +1106,7 @@ public abstract class ImageReaderAbstractTest<T extends ImageReader> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGetAspectRatioIndexOutOfBounds() {
|
public void testGetAspectRatioIndexOutOfBounds() throws IOException {
|
||||||
ImageReader reader = createReader();
|
ImageReader reader = createReader();
|
||||||
TestData data = getTestData().get(0);
|
TestData data = getTestData().get(0);
|
||||||
reader.setInput(data.getInputStream());
|
reader.setInput(data.getInputStream());
|
||||||
@@ -1114,13 +1127,13 @@ public abstract class ImageReaderAbstractTest<T extends ImageReader> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testDisposeBeforeRead() {
|
public void testDisposeBeforeRead() throws IOException {
|
||||||
ImageReader reader = createReader();
|
ImageReader reader = createReader();
|
||||||
reader.dispose(); // Just pass with no exceptions
|
reader.dispose(); // Just pass with no exceptions
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testDisposeAfterRead() {
|
public void testDisposeAfterRead() throws IOException {
|
||||||
ImageReader reader = createReader();
|
ImageReader reader = createReader();
|
||||||
TestData data = getTestData().get(0);
|
TestData data = getTestData().get(0);
|
||||||
reader.setInput(data.getInputStream());
|
reader.setInput(data.getInputStream());
|
||||||
@@ -1128,21 +1141,21 @@ public abstract class ImageReaderAbstractTest<T extends ImageReader> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testAddIIOReadProgressListener() {
|
public void testAddIIOReadProgressListener() throws IOException {
|
||||||
ImageReader reader = createReader();
|
ImageReader reader = createReader();
|
||||||
reader.addIIOReadProgressListener(mock(IIOReadProgressListener.class));
|
reader.addIIOReadProgressListener(mock(IIOReadProgressListener.class));
|
||||||
reader.dispose();
|
reader.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testAddIIOReadProgressListenerNull() {
|
public void testAddIIOReadProgressListenerNull() throws IOException {
|
||||||
ImageReader reader = createReader();
|
ImageReader reader = createReader();
|
||||||
reader.addIIOReadProgressListener(null);
|
reader.addIIOReadProgressListener(null);
|
||||||
reader.dispose();
|
reader.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testAddIIOReadProgressListenerCallbacks() {
|
public void testAddIIOReadProgressListenerCallbacks() throws IOException {
|
||||||
ImageReader reader = createReader();
|
ImageReader reader = createReader();
|
||||||
TestData data = getTestData().get(0);
|
TestData data = getTestData().get(0);
|
||||||
reader.setInput(data.getInputStream());
|
reader.setInput(data.getInputStream());
|
||||||
@@ -1166,7 +1179,7 @@ public abstract class ImageReaderAbstractTest<T extends ImageReader> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testMultipleAddIIOReadProgressListenerCallbacks() {
|
public void testMultipleAddIIOReadProgressListenerCallbacks() throws IOException {
|
||||||
ImageReader reader = createReader();
|
ImageReader reader = createReader();
|
||||||
TestData data = getTestData().get(0);
|
TestData data = getTestData().get(0);
|
||||||
reader.setInput(data.getInputStream());
|
reader.setInput(data.getInputStream());
|
||||||
@@ -1204,21 +1217,21 @@ public abstract class ImageReaderAbstractTest<T extends ImageReader> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testRemoveIIOReadProgressListenerNull() {
|
public void testRemoveIIOReadProgressListenerNull() throws IOException {
|
||||||
ImageReader reader = createReader();
|
ImageReader reader = createReader();
|
||||||
reader.removeIIOReadProgressListener(null);
|
reader.removeIIOReadProgressListener(null);
|
||||||
reader.dispose();
|
reader.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testRemoveIIOReadProgressListenerNone() {
|
public void testRemoveIIOReadProgressListenerNone() throws IOException {
|
||||||
ImageReader reader = createReader();
|
ImageReader reader = createReader();
|
||||||
reader.removeIIOReadProgressListener(mock(IIOReadProgressListener.class));
|
reader.removeIIOReadProgressListener(mock(IIOReadProgressListener.class));
|
||||||
reader.dispose();
|
reader.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testRemoveIIOReadProgressListener() {
|
public void testRemoveIIOReadProgressListener() throws IOException {
|
||||||
ImageReader reader = createReader();
|
ImageReader reader = createReader();
|
||||||
TestData data = getTestData().get(0);
|
TestData data = getTestData().get(0);
|
||||||
reader.setInput(data.getInputStream());
|
reader.setInput(data.getInputStream());
|
||||||
@@ -1240,7 +1253,7 @@ public abstract class ImageReaderAbstractTest<T extends ImageReader> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testRemoveIIOReadProgressListenerMultiple() {
|
public void testRemoveIIOReadProgressListenerMultiple() throws IOException {
|
||||||
ImageReader reader = createReader();
|
ImageReader reader = createReader();
|
||||||
TestData data = getTestData().get(0);
|
TestData data = getTestData().get(0);
|
||||||
reader.setInput(data.getInputStream());
|
reader.setInput(data.getInputStream());
|
||||||
@@ -1272,7 +1285,7 @@ public abstract class ImageReaderAbstractTest<T extends ImageReader> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testRemoveAllIIOReadProgressListeners() {
|
public void testRemoveAllIIOReadProgressListeners() throws IOException {
|
||||||
ImageReader reader = createReader();
|
ImageReader reader = createReader();
|
||||||
TestData data = getTestData().get(0);
|
TestData data = getTestData().get(0);
|
||||||
reader.setInput(data.getInputStream());
|
reader.setInput(data.getInputStream());
|
||||||
@@ -1295,7 +1308,7 @@ public abstract class ImageReaderAbstractTest<T extends ImageReader> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testRemoveAllIIOReadProgressListenersMultiple() {
|
public void testRemoveAllIIOReadProgressListenersMultiple() throws IOException {
|
||||||
ImageReader reader = createReader();
|
ImageReader reader = createReader();
|
||||||
TestData data = getTestData().get(0);
|
TestData data = getTestData().get(0);
|
||||||
reader.setInput(data.getInputStream());
|
reader.setInput(data.getInputStream());
|
||||||
@@ -1322,7 +1335,7 @@ public abstract class ImageReaderAbstractTest<T extends ImageReader> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testAbort() {
|
public void testAbort() throws IOException {
|
||||||
final ImageReader reader = createReader();
|
final ImageReader reader = createReader();
|
||||||
TestData data = getTestData().get(0);
|
TestData data = getTestData().get(0);
|
||||||
reader.setInput(data.getInputStream());
|
reader.setInput(data.getInputStream());
|
||||||
@@ -1336,7 +1349,7 @@ public abstract class ImageReaderAbstractTest<T extends ImageReader> {
|
|||||||
// Create a listener that just makes the reader abort immediately...
|
// Create a listener that just makes the reader abort immediately...
|
||||||
IIOReadProgressListener abortingListener = mock(IIOReadProgressListener.class, "Aborter");
|
IIOReadProgressListener abortingListener = mock(IIOReadProgressListener.class, "Aborter");
|
||||||
Answer<Void> abort = new Answer<Void>() {
|
Answer<Void> abort = new Answer<Void>() {
|
||||||
public Void answer(InvocationOnMock invocation) throws Throwable {
|
public Void answer(InvocationOnMock invocation) {
|
||||||
reader.abort();
|
reader.abort();
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -1387,7 +1400,7 @@ public abstract class ImageReaderAbstractTest<T extends ImageReader> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
assertTrue("ImageTypeSepcifier from getRawImageType should be in the iterator from getImageTypes", rawFound);
|
assertTrue("ImageTypeSpecifier from getRawImageType should be in the iterator from getImageTypes", rawFound);
|
||||||
}
|
}
|
||||||
reader.dispose();
|
reader.dispose();
|
||||||
}
|
}
|
||||||
@@ -1569,7 +1582,6 @@ public abstract class ImageReaderAbstractTest<T extends ImageReader> {
|
|||||||
reader.dispose();
|
reader.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("ConstantConditions")
|
|
||||||
@Test
|
@Test
|
||||||
public void testSetDestinationOffsetNull() throws IOException {
|
public void testSetDestinationOffsetNull() throws IOException {
|
||||||
final ImageReader reader = createReader();
|
final ImageReader reader = createReader();
|
||||||
@@ -1620,7 +1632,7 @@ public abstract class ImageReaderAbstractTest<T extends ImageReader> {
|
|||||||
assertEquals(expectedModel.getDataType(), resultModel.getDataType());
|
assertEquals(expectedModel.getDataType(), resultModel.getDataType());
|
||||||
assertEquals(expectedModel.getNumBands(), resultModel.getNumBands());
|
assertEquals(expectedModel.getNumBands(), resultModel.getNumBands());
|
||||||
assertEquals(expectedModel.getNumDataElements(), resultModel.getNumDataElements());
|
assertEquals(expectedModel.getNumDataElements(), resultModel.getNumDataElements());
|
||||||
assertTrue(Arrays.equals(expectedModel.getSampleSize(), resultModel.getSampleSize()));
|
assertArrayEquals(expectedModel.getSampleSize(), resultModel.getSampleSize());
|
||||||
assertEquals(expectedModel.getTransferType(), resultModel.getTransferType());
|
assertEquals(expectedModel.getTransferType(), resultModel.getTransferType());
|
||||||
for (int i = 0; i < expectedModel.getNumBands(); i++) {
|
for (int i = 0; i < expectedModel.getNumBands(); i++) {
|
||||||
assertEquals(expectedModel.getSampleSize(i), resultModel.getSampleSize(i));
|
assertEquals(expectedModel.getSampleSize(i), resultModel.getSampleSize(i));
|
||||||
@@ -1692,20 +1704,18 @@ public abstract class ImageReaderAbstractTest<T extends ImageReader> {
|
|||||||
|
|
||||||
@Ignore("TODO: Implement")
|
@Ignore("TODO: Implement")
|
||||||
@Test
|
@Test
|
||||||
public void testSetDestinationBands() throws IOException {
|
public void testSetDestinationBands() {
|
||||||
throw new UnsupportedOperationException("Method testSetDestinationBands not implemented"); // TODO: Implement
|
throw new UnsupportedOperationException("Method testSetDestinationBands not implemented"); // TODO: Implement
|
||||||
}
|
}
|
||||||
|
|
||||||
@Ignore("TODO: Implement")
|
@Ignore("TODO: Implement")
|
||||||
@Test
|
@Test
|
||||||
public void testSetSourceBands() throws IOException {
|
public void testSetSourceBands() {
|
||||||
throw new UnsupportedOperationException("Method testSetDestinationBands not implemented"); // TODO: Implement
|
throw new UnsupportedOperationException("Method testSetDestinationBands not implemented"); // TODO: Implement
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testProviderAndMetadataFormatNamesMatch() throws IOException {
|
public void testProviderAndMetadataFormatNamesMatch() throws IOException {
|
||||||
ImageReaderSpi provider = createProvider();
|
|
||||||
|
|
||||||
ImageReader reader = createReader();
|
ImageReader reader = createReader();
|
||||||
reader.setInput(getTestData().get(0).getInputStream());
|
reader.setInput(getTestData().get(0).getInputStream());
|
||||||
|
|
||||||
@@ -1826,7 +1836,7 @@ public abstract class ImageReaderAbstractTest<T extends ImageReader> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return getClass().getSimpleName() + ": " + String.valueOf(input);
|
return String.format("%s: %s", getClass().getSimpleName(), input);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,6 +31,7 @@
|
|||||||
package com.twelvemonkeys.imageio.util;
|
package com.twelvemonkeys.imageio.util;
|
||||||
|
|
||||||
import com.twelvemonkeys.imageio.stream.URLImageInputStreamSpi;
|
import com.twelvemonkeys.imageio.stream.URLImageInputStreamSpi;
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.mockito.InOrder;
|
import org.mockito.InOrder;
|
||||||
|
|
||||||
@@ -39,12 +40,14 @@ import javax.imageio.ImageWriteParam;
|
|||||||
import javax.imageio.ImageWriter;
|
import javax.imageio.ImageWriter;
|
||||||
import javax.imageio.event.IIOWriteProgressListener;
|
import javax.imageio.event.IIOWriteProgressListener;
|
||||||
import javax.imageio.spi.IIORegistry;
|
import javax.imageio.spi.IIORegistry;
|
||||||
|
import javax.imageio.spi.ImageWriterSpi;
|
||||||
import javax.imageio.stream.ImageOutputStream;
|
import javax.imageio.stream.ImageOutputStream;
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.awt.image.BufferedImage;
|
import java.awt.image.BufferedImage;
|
||||||
import java.awt.image.RenderedImage;
|
import java.awt.image.RenderedImage;
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.lang.reflect.ParameterizedType;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@@ -59,7 +62,7 @@ import static org.mockito.Mockito.*;
|
|||||||
* @author last modified by $Author: haku $
|
* @author last modified by $Author: haku $
|
||||||
* @version $Id: ImageReaderAbstractTestCase.java,v 1.0 18.nov.2004 17:38:33 haku Exp $
|
* @version $Id: ImageReaderAbstractTestCase.java,v 1.0 18.nov.2004 17:38:33 haku Exp $
|
||||||
*/
|
*/
|
||||||
public abstract class ImageWriterAbstractTest {
|
public abstract class ImageWriterAbstractTest<T extends ImageWriter> {
|
||||||
|
|
||||||
// TODO: Move static block + getClassLoaderResource to common superclass for reader/writer test cases or delegate.
|
// TODO: Move static block + getClassLoaderResource to common superclass for reader/writer test cases or delegate.
|
||||||
|
|
||||||
@@ -68,7 +71,16 @@ public abstract class ImageWriterAbstractTest {
|
|||||||
ImageIO.setUseCache(false);
|
ImageIO.setUseCache(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract ImageWriter createImageWriter();
|
@SuppressWarnings("unchecked")
|
||||||
|
private final Class<T> writerClass = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
|
||||||
|
|
||||||
|
protected final ImageWriterSpi provider = createProvider();
|
||||||
|
|
||||||
|
protected abstract ImageWriterSpi createProvider();
|
||||||
|
|
||||||
|
protected final T createWriter() throws IOException {
|
||||||
|
return writerClass.cast(provider.createWriterInstance(null));
|
||||||
|
}
|
||||||
|
|
||||||
protected abstract List<? extends RenderedImage> getTestData();
|
protected abstract List<? extends RenderedImage> getTestData();
|
||||||
|
|
||||||
@@ -104,22 +116,22 @@ public abstract class ImageWriterAbstractTest {
|
|||||||
@Test
|
@Test
|
||||||
public void testSetOutput() throws IOException {
|
public void testSetOutput() throws IOException {
|
||||||
// Should just pass with no exceptions
|
// Should just pass with no exceptions
|
||||||
ImageWriter writer = createImageWriter();
|
ImageWriter writer = createWriter();
|
||||||
assertNotNull(writer);
|
assertNotNull(writer);
|
||||||
writer.setOutput(ImageIO.createImageOutputStream(new ByteArrayOutputStream()));
|
writer.setOutput(ImageIO.createImageOutputStream(new ByteArrayOutputStream()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSetOutputNull() {
|
public void testSetOutputNull() throws IOException {
|
||||||
// Should just pass with no exceptions
|
// Should just pass with no exceptions
|
||||||
ImageWriter writer = createImageWriter();
|
ImageWriter writer = createWriter();
|
||||||
assertNotNull(writer);
|
assertNotNull(writer);
|
||||||
writer.setOutput(null);
|
writer.setOutput(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testWrite() throws IOException {
|
public void testWrite() throws IOException {
|
||||||
ImageWriter writer = createImageWriter();
|
ImageWriter writer = createWriter();
|
||||||
|
|
||||||
for (RenderedImage testData : getTestData()) {
|
for (RenderedImage testData : getTestData()) {
|
||||||
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
|
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
|
||||||
@@ -129,17 +141,16 @@ public abstract class ImageWriterAbstractTest {
|
|||||||
writer.write(drawSomething((BufferedImage) testData));
|
writer.write(drawSomething((BufferedImage) testData));
|
||||||
}
|
}
|
||||||
catch (IOException e) {
|
catch (IOException e) {
|
||||||
fail(e.getMessage());
|
throw new AssertionError(e.getMessage(), e);
|
||||||
}
|
}
|
||||||
|
|
||||||
assertTrue("No image data written", buffer.size() > 0);
|
assertTrue("No image data written", buffer.size() > 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("ConstantConditions")
|
|
||||||
@Test
|
@Test
|
||||||
public void testWriteNull() throws IOException {
|
public void testWriteNull() throws IOException {
|
||||||
ImageWriter writer = createImageWriter();
|
ImageWriter writer = createWriter();
|
||||||
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
|
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
|
||||||
writer.setOutput(ImageIO.createImageOutputStream(buffer));
|
writer.setOutput(ImageIO.createImageOutputStream(buffer));
|
||||||
|
|
||||||
@@ -149,15 +160,15 @@ public abstract class ImageWriterAbstractTest {
|
|||||||
catch(IllegalArgumentException ignore) {
|
catch(IllegalArgumentException ignore) {
|
||||||
}
|
}
|
||||||
catch (IOException e) {
|
catch (IOException e) {
|
||||||
fail(e.getMessage());
|
throw new AssertionError(e.getMessage(), e);
|
||||||
}
|
}
|
||||||
|
|
||||||
assertTrue("Image data written", buffer.size() == 0);
|
assertEquals("Image data written", 0, buffer.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = IllegalStateException.class)
|
@Test(expected = IllegalStateException.class)
|
||||||
public void testWriteNoOutput() {
|
public void testWriteNoOutput() throws IOException {
|
||||||
ImageWriter writer = createImageWriter();
|
ImageWriter writer = createWriter();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
writer.write(getTestData(0));
|
writer.write(getTestData(0));
|
||||||
@@ -168,8 +179,8 @@ public abstract class ImageWriterAbstractTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGetDefaultWriteParam() {
|
public void testGetDefaultWriteParam() throws IOException {
|
||||||
ImageWriter writer = createImageWriter();
|
ImageWriter writer = createWriter();
|
||||||
ImageWriteParam param = writer.getDefaultWriteParam();
|
ImageWriteParam param = writer.getDefaultWriteParam();
|
||||||
assertNotNull("Default ImageWriteParam is null", param);
|
assertNotNull("Default ImageWriteParam is null", param);
|
||||||
}
|
}
|
||||||
@@ -178,20 +189,20 @@ public abstract class ImageWriterAbstractTest {
|
|||||||
// TODO: Source region and subsampling at least
|
// TODO: Source region and subsampling at least
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testAddIIOWriteProgressListener() {
|
public void testAddIIOWriteProgressListener() throws IOException {
|
||||||
ImageWriter writer = createImageWriter();
|
ImageWriter writer = createWriter();
|
||||||
writer.addIIOWriteProgressListener(mock(IIOWriteProgressListener.class));
|
writer.addIIOWriteProgressListener(mock(IIOWriteProgressListener.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testAddIIOWriteProgressListenerNull() {
|
public void testAddIIOWriteProgressListenerNull() throws IOException {
|
||||||
ImageWriter writer = createImageWriter();
|
ImageWriter writer = createWriter();
|
||||||
writer.addIIOWriteProgressListener(null);
|
writer.addIIOWriteProgressListener(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testAddIIOWriteProgressListenerCallbacks() throws IOException {
|
public void testAddIIOWriteProgressListenerCallbacks() throws IOException {
|
||||||
ImageWriter writer = createImageWriter();
|
ImageWriter writer = createWriter();
|
||||||
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
|
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
|
||||||
writer.setOutput(ImageIO.createImageOutputStream(buffer));
|
writer.setOutput(ImageIO.createImageOutputStream(buffer));
|
||||||
|
|
||||||
@@ -214,7 +225,7 @@ public abstract class ImageWriterAbstractTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testMultipleAddIIOWriteProgressListenerCallbacks() throws IOException {
|
public void testMultipleAddIIOWriteProgressListenerCallbacks() throws IOException {
|
||||||
ImageWriter writer = createImageWriter();
|
ImageWriter writer = createWriter();
|
||||||
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
|
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
|
||||||
writer.setOutput(ImageIO.createImageOutputStream(buffer));
|
writer.setOutput(ImageIO.createImageOutputStream(buffer));
|
||||||
|
|
||||||
@@ -250,20 +261,20 @@ public abstract class ImageWriterAbstractTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testRemoveIIOWriteProgressListenerNull() {
|
public void testRemoveIIOWriteProgressListenerNull() throws IOException {
|
||||||
ImageWriter writer = createImageWriter();
|
ImageWriter writer = createWriter();
|
||||||
writer.removeIIOWriteProgressListener(null);
|
writer.removeIIOWriteProgressListener(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testRemoveIIOWriteProgressListenerNone() {
|
public void testRemoveIIOWriteProgressListenerNone() throws IOException {
|
||||||
ImageWriter writer = createImageWriter();
|
ImageWriter writer = createWriter();
|
||||||
writer.removeIIOWriteProgressListener(mock(IIOWriteProgressListener.class));
|
writer.removeIIOWriteProgressListener(mock(IIOWriteProgressListener.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testRemoveIIOWriteProgressListener() throws IOException {
|
public void testRemoveIIOWriteProgressListener() throws IOException {
|
||||||
ImageWriter writer = createImageWriter();
|
ImageWriter writer = createWriter();
|
||||||
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
|
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
|
||||||
writer.setOutput(ImageIO.createImageOutputStream(buffer));
|
writer.setOutput(ImageIO.createImageOutputStream(buffer));
|
||||||
|
|
||||||
@@ -284,7 +295,7 @@ public abstract class ImageWriterAbstractTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testRemoveIIOWriteProgressListenerMultiple() throws IOException {
|
public void testRemoveIIOWriteProgressListenerMultiple() throws IOException {
|
||||||
ImageWriter writer = createImageWriter();
|
ImageWriter writer = createWriter();
|
||||||
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
|
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
|
||||||
writer.setOutput(ImageIO.createImageOutputStream(buffer));
|
writer.setOutput(ImageIO.createImageOutputStream(buffer));
|
||||||
|
|
||||||
@@ -316,7 +327,7 @@ public abstract class ImageWriterAbstractTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testRemoveAllIIOWriteProgressListeners() throws IOException {
|
public void testRemoveAllIIOWriteProgressListeners() throws IOException {
|
||||||
ImageWriter writer = createImageWriter();
|
ImageWriter writer = createWriter();
|
||||||
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
|
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
|
||||||
writer.setOutput(ImageIO.createImageOutputStream(buffer));
|
writer.setOutput(ImageIO.createImageOutputStream(buffer));
|
||||||
|
|
||||||
@@ -339,7 +350,7 @@ public abstract class ImageWriterAbstractTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testRemoveAllIIOWriteProgressListenersMultiple() throws IOException {
|
public void testRemoveAllIIOWriteProgressListenersMultiple() throws IOException {
|
||||||
ImageWriter writer = createImageWriter();
|
ImageWriter writer = createWriter();
|
||||||
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
|
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
|
||||||
writer.setOutput(ImageIO.createImageOutputStream(buffer));
|
writer.setOutput(ImageIO.createImageOutputStream(buffer));
|
||||||
|
|
||||||
|
|||||||
@@ -31,6 +31,7 @@
|
|||||||
package com.twelvemonkeys.imageio.util;
|
package com.twelvemonkeys.imageio.util;
|
||||||
|
|
||||||
import com.twelvemonkeys.imageio.color.ColorSpaces;
|
import com.twelvemonkeys.imageio.color.ColorSpaces;
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import javax.imageio.ImageTypeSpecifier;
|
import javax.imageio.ImageTypeSpecifier;
|
||||||
@@ -39,7 +40,8 @@ import java.awt.image.ComponentColorModel;
|
|||||||
import java.awt.image.DataBuffer;
|
import java.awt.image.DataBuffer;
|
||||||
import java.awt.image.PixelInterleavedSampleModel;
|
import java.awt.image.PixelInterleavedSampleModel;
|
||||||
|
|
||||||
import static org.hamcrest.core.Is.is;
|
import static org.hamcrest.CoreMatchers.instanceOf;
|
||||||
|
import static org.hamcrest.MatcherAssert.assertThat;
|
||||||
import static org.junit.Assert.*;
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
public class UInt32ImageTypeSpecifierTest {
|
public class UInt32ImageTypeSpecifierTest {
|
||||||
@@ -55,13 +57,13 @@ public class UInt32ImageTypeSpecifierTest {
|
|||||||
assertEquals(1, spec.getNumComponents());
|
assertEquals(1, spec.getNumComponents());
|
||||||
assertEquals(32, spec.getBitsPerBand(0));
|
assertEquals(32, spec.getBitsPerBand(0));
|
||||||
|
|
||||||
assertThat(spec.getColorModel(), is(ComponentColorModel.class));
|
assertThat(spec.getColorModel(), instanceOf(ComponentColorModel.class));
|
||||||
assertFalse(spec.getColorModel().hasAlpha());
|
assertFalse(spec.getColorModel().hasAlpha());
|
||||||
assertFalse(spec.getColorModel().isAlphaPremultiplied());
|
assertFalse(spec.getColorModel().isAlphaPremultiplied());
|
||||||
assertEquals(1, spec.getColorModel().getNumComponents());
|
assertEquals(1, spec.getColorModel().getNumComponents());
|
||||||
assertEquals(1, spec.getColorModel().getNumColorComponents());
|
assertEquals(1, spec.getColorModel().getNumColorComponents());
|
||||||
|
|
||||||
assertThat(spec.getSampleModel(), is(PixelInterleavedSampleModel.class));
|
assertThat(spec.getSampleModel(), instanceOf(PixelInterleavedSampleModel.class));
|
||||||
assertEquals(1, spec.getSampleModel().getNumBands());
|
assertEquals(1, spec.getSampleModel().getNumBands());
|
||||||
assertEquals(1, spec.getSampleModel().getNumDataElements());
|
assertEquals(1, spec.getSampleModel().getNumDataElements());
|
||||||
}
|
}
|
||||||
@@ -74,13 +76,13 @@ public class UInt32ImageTypeSpecifierTest {
|
|||||||
assertEquals(32, spec.getBitsPerBand(0));
|
assertEquals(32, spec.getBitsPerBand(0));
|
||||||
assertEquals(32, spec.getBitsPerBand(1));
|
assertEquals(32, spec.getBitsPerBand(1));
|
||||||
|
|
||||||
assertThat(spec.getColorModel(), is(ComponentColorModel.class));
|
assertThat(spec.getColorModel(), instanceOf(ComponentColorModel.class));
|
||||||
assertTrue(spec.getColorModel().hasAlpha());
|
assertTrue(spec.getColorModel().hasAlpha());
|
||||||
assertFalse(spec.getColorModel().isAlphaPremultiplied());
|
assertFalse(spec.getColorModel().isAlphaPremultiplied());
|
||||||
assertEquals(2, spec.getColorModel().getNumComponents());
|
assertEquals(2, spec.getColorModel().getNumComponents());
|
||||||
assertEquals(1, spec.getColorModel().getNumColorComponents());
|
assertEquals(1, spec.getColorModel().getNumColorComponents());
|
||||||
|
|
||||||
assertThat(spec.getSampleModel(), is(PixelInterleavedSampleModel.class));
|
assertThat(spec.getSampleModel(), instanceOf(PixelInterleavedSampleModel.class));
|
||||||
assertEquals(2, spec.getSampleModel().getNumBands());
|
assertEquals(2, spec.getSampleModel().getNumBands());
|
||||||
assertEquals(2, spec.getSampleModel().getNumDataElements());
|
assertEquals(2, spec.getSampleModel().getNumDataElements());
|
||||||
}
|
}
|
||||||
@@ -95,13 +97,13 @@ public class UInt32ImageTypeSpecifierTest {
|
|||||||
assertEquals(32, spec.getBitsPerBand(1));
|
assertEquals(32, spec.getBitsPerBand(1));
|
||||||
assertEquals(32, spec.getBitsPerBand(2));
|
assertEquals(32, spec.getBitsPerBand(2));
|
||||||
|
|
||||||
assertThat(spec.getColorModel(), is(ComponentColorModel.class));
|
assertThat(spec.getColorModel(), instanceOf(ComponentColorModel.class));
|
||||||
assertFalse(spec.getColorModel().hasAlpha());
|
assertFalse(spec.getColorModel().hasAlpha());
|
||||||
assertFalse(spec.getColorModel().isAlphaPremultiplied());
|
assertFalse(spec.getColorModel().isAlphaPremultiplied());
|
||||||
assertEquals(3, spec.getColorModel().getNumComponents());
|
assertEquals(3, spec.getColorModel().getNumComponents());
|
||||||
assertEquals(3, spec.getColorModel().getNumColorComponents());
|
assertEquals(3, spec.getColorModel().getNumColorComponents());
|
||||||
|
|
||||||
assertThat(spec.getSampleModel(), is(PixelInterleavedSampleModel.class));
|
assertThat(spec.getSampleModel(), instanceOf(PixelInterleavedSampleModel.class));
|
||||||
assertEquals(3, spec.getSampleModel().getNumBands());
|
assertEquals(3, spec.getSampleModel().getNumBands());
|
||||||
assertEquals(3, spec.getSampleModel().getNumDataElements());
|
assertEquals(3, spec.getSampleModel().getNumDataElements());
|
||||||
}
|
}
|
||||||
@@ -116,13 +118,13 @@ public class UInt32ImageTypeSpecifierTest {
|
|||||||
assertEquals(32, spec.getBitsPerBand(2));
|
assertEquals(32, spec.getBitsPerBand(2));
|
||||||
assertEquals(32, spec.getBitsPerBand(3));
|
assertEquals(32, spec.getBitsPerBand(3));
|
||||||
|
|
||||||
assertThat(spec.getColorModel(), is(ComponentColorModel.class));
|
assertThat(spec.getColorModel(), instanceOf(ComponentColorModel.class));
|
||||||
assertTrue(spec.getColorModel().hasAlpha());
|
assertTrue(spec.getColorModel().hasAlpha());
|
||||||
assertFalse(spec.getColorModel().isAlphaPremultiplied());
|
assertFalse(spec.getColorModel().isAlphaPremultiplied());
|
||||||
assertEquals(4, spec.getColorModel().getNumComponents());
|
assertEquals(4, spec.getColorModel().getNumComponents());
|
||||||
assertEquals(3, spec.getColorModel().getNumColorComponents());
|
assertEquals(3, spec.getColorModel().getNumColorComponents());
|
||||||
|
|
||||||
assertThat(spec.getSampleModel(), is(PixelInterleavedSampleModel.class));
|
assertThat(spec.getSampleModel(), instanceOf(PixelInterleavedSampleModel.class));
|
||||||
assertEquals(4, spec.getSampleModel().getNumBands());
|
assertEquals(4, spec.getSampleModel().getNumBands());
|
||||||
assertEquals(4, spec.getSampleModel().getNumDataElements());
|
assertEquals(4, spec.getSampleModel().getNumDataElements());
|
||||||
}
|
}
|
||||||
@@ -137,13 +139,13 @@ public class UInt32ImageTypeSpecifierTest {
|
|||||||
assertEquals(32, spec.getBitsPerBand(2));
|
assertEquals(32, spec.getBitsPerBand(2));
|
||||||
assertEquals(32, spec.getBitsPerBand(3));
|
assertEquals(32, spec.getBitsPerBand(3));
|
||||||
|
|
||||||
assertThat(spec.getColorModel(), is(ComponentColorModel.class));
|
assertThat(spec.getColorModel(), instanceOf(ComponentColorModel.class));
|
||||||
assertTrue(spec.getColorModel().hasAlpha());
|
assertTrue(spec.getColorModel().hasAlpha());
|
||||||
assertTrue(spec.getColorModel().isAlphaPremultiplied());
|
assertTrue(spec.getColorModel().isAlphaPremultiplied());
|
||||||
assertEquals(4, spec.getColorModel().getNumComponents());
|
assertEquals(4, spec.getColorModel().getNumComponents());
|
||||||
assertEquals(3, spec.getColorModel().getNumColorComponents());
|
assertEquals(3, spec.getColorModel().getNumColorComponents());
|
||||||
|
|
||||||
assertThat(spec.getSampleModel(), is(PixelInterleavedSampleModel.class));
|
assertThat(spec.getSampleModel(), instanceOf(PixelInterleavedSampleModel.class));
|
||||||
assertEquals(4, spec.getSampleModel().getNumBands());
|
assertEquals(4, spec.getSampleModel().getNumBands());
|
||||||
assertEquals(4, spec.getSampleModel().getNumDataElements());
|
assertEquals(4, spec.getSampleModel().getNumDataElements());
|
||||||
}
|
}
|
||||||
@@ -159,13 +161,13 @@ public class UInt32ImageTypeSpecifierTest {
|
|||||||
assertEquals(32, spec.getBitsPerBand(2));
|
assertEquals(32, spec.getBitsPerBand(2));
|
||||||
assertEquals(32, spec.getBitsPerBand(3));
|
assertEquals(32, spec.getBitsPerBand(3));
|
||||||
|
|
||||||
assertThat(spec.getColorModel(), is(ComponentColorModel.class));
|
assertThat(spec.getColorModel(), instanceOf(ComponentColorModel.class));
|
||||||
assertFalse(spec.getColorModel().hasAlpha());
|
assertFalse(spec.getColorModel().hasAlpha());
|
||||||
assertFalse(spec.getColorModel().isAlphaPremultiplied());
|
assertFalse(spec.getColorModel().isAlphaPremultiplied());
|
||||||
assertEquals(4, spec.getColorModel().getNumComponents());
|
assertEquals(4, spec.getColorModel().getNumComponents());
|
||||||
assertEquals(4, spec.getColorModel().getNumColorComponents());
|
assertEquals(4, spec.getColorModel().getNumColorComponents());
|
||||||
|
|
||||||
assertThat(spec.getSampleModel(), is(PixelInterleavedSampleModel.class));
|
assertThat(spec.getSampleModel(), instanceOf(PixelInterleavedSampleModel.class));
|
||||||
assertEquals(4, spec.getSampleModel().getNumBands());
|
assertEquals(4, spec.getSampleModel().getNumBands());
|
||||||
assertEquals(4, spec.getSampleModel().getNumDataElements());
|
assertEquals(4, spec.getSampleModel().getNumDataElements());
|
||||||
}
|
}
|
||||||
@@ -181,13 +183,13 @@ public class UInt32ImageTypeSpecifierTest {
|
|||||||
assertEquals(32, spec.getBitsPerBand(3));
|
assertEquals(32, spec.getBitsPerBand(3));
|
||||||
assertEquals(32, spec.getBitsPerBand(4));
|
assertEquals(32, spec.getBitsPerBand(4));
|
||||||
|
|
||||||
assertThat(spec.getColorModel(), is(ComponentColorModel.class));
|
assertThat(spec.getColorModel(), instanceOf(ComponentColorModel.class));
|
||||||
assertTrue(spec.getColorModel().hasAlpha());
|
assertTrue(spec.getColorModel().hasAlpha());
|
||||||
assertFalse(spec.getColorModel().isAlphaPremultiplied());
|
assertFalse(spec.getColorModel().isAlphaPremultiplied());
|
||||||
assertEquals(5, spec.getColorModel().getNumComponents());
|
assertEquals(5, spec.getColorModel().getNumComponents());
|
||||||
assertEquals(4, spec.getColorModel().getNumColorComponents());
|
assertEquals(4, spec.getColorModel().getNumColorComponents());
|
||||||
|
|
||||||
assertThat(spec.getSampleModel(), is(PixelInterleavedSampleModel.class));
|
assertThat(spec.getSampleModel(), instanceOf(PixelInterleavedSampleModel.class));
|
||||||
assertEquals(5, spec.getSampleModel().getNumBands());
|
assertEquals(5, spec.getSampleModel().getNumBands());
|
||||||
assertEquals(5, spec.getSampleModel().getNumDataElements());
|
assertEquals(5, spec.getSampleModel().getNumDataElements());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>com.twelvemonkeys.imageio</groupId>
|
<groupId>com.twelvemonkeys.imageio</groupId>
|
||||||
<artifactId>imageio</artifactId>
|
<artifactId>imageio</artifactId>
|
||||||
<version>3.5</version>
|
<version>3.6.2</version>
|
||||||
</parent>
|
</parent>
|
||||||
<artifactId>imageio-hdr</artifactId>
|
<artifactId>imageio-hdr</artifactId>
|
||||||
<name>TwelveMonkeys :: ImageIO :: HDR plugin</name>
|
<name>TwelveMonkeys :: ImageIO :: HDR plugin</name>
|
||||||
@@ -21,6 +21,7 @@
|
|||||||
<groupId>com.twelvemonkeys.imageio</groupId>
|
<groupId>com.twelvemonkeys.imageio</groupId>
|
||||||
<artifactId>imageio-core</artifactId>
|
<artifactId>imageio-core</artifactId>
|
||||||
<type>test-jar</type>
|
<type>test-jar</type>
|
||||||
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.twelvemonkeys.imageio</groupId>
|
<groupId>com.twelvemonkeys.imageio</groupId>
|
||||||
|
|||||||
@@ -46,26 +46,16 @@ import java.util.List;
|
|||||||
* @version $Id: TGAImageReaderTest.java,v 1.0 03.07.14 22:28 haraldk Exp$
|
* @version $Id: TGAImageReaderTest.java,v 1.0 03.07.14 22:28 haraldk Exp$
|
||||||
*/
|
*/
|
||||||
public class HDRImageReaderTest extends ImageReaderAbstractTest<HDRImageReader> {
|
public class HDRImageReaderTest extends ImageReaderAbstractTest<HDRImageReader> {
|
||||||
@Override
|
|
||||||
protected List<TestData> getTestData() {
|
|
||||||
return Arrays.asList(
|
|
||||||
new TestData(getClassLoaderResource("/hdr/memorial_o876.hdr"), new Dimension(512, 768))
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected ImageReaderSpi createProvider() {
|
protected ImageReaderSpi createProvider() {
|
||||||
return new HDRImageReaderSpi();
|
return new HDRImageReaderSpi();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Class<HDRImageReader> getReaderClass() {
|
protected List<TestData> getTestData() {
|
||||||
return HDRImageReader.class;
|
return Collections.singletonList(
|
||||||
}
|
new TestData(getClassLoaderResource("/hdr/memorial_o876.hdr"), new Dimension(512, 768))
|
||||||
|
);
|
||||||
@Override
|
|
||||||
protected HDRImageReader createReader() {
|
|
||||||
return new HDRImageReader(createProvider());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -0,0 +1,31 @@
|
|||||||
|
package com.twelvemonkeys.imageio.plugins.hdr.tonemap;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertArrayEquals;
|
||||||
|
|
||||||
|
public class DefaultToneMapperTest {
|
||||||
|
|
||||||
|
private final DefaultToneMapper mapper = new DefaultToneMapper();
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testMap0() {
|
||||||
|
float[] rgb = {0};
|
||||||
|
mapper.map(rgb);
|
||||||
|
assertArrayEquals(new float[]{0}, rgb, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testMap1() {
|
||||||
|
float[] rgb = {1};
|
||||||
|
mapper.map(rgb);
|
||||||
|
assertArrayEquals(new float[]{0.5f}, rgb, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testMapMax() {
|
||||||
|
float[] rgb = {Float.MAX_VALUE};
|
||||||
|
mapper.map(rgb);
|
||||||
|
assertArrayEquals(new float[]{1}, rgb, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
package com.twelvemonkeys.imageio.plugins.hdr.tonemap;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertArrayEquals;
|
||||||
|
|
||||||
|
public class GammaToneMapperTest {
|
||||||
|
private final GammaToneMapper mapper = new GammaToneMapper();
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testMap0() {
|
||||||
|
float[] rgb = {0};
|
||||||
|
mapper.map(rgb);
|
||||||
|
assertArrayEquals(new float[]{0}, rgb, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testMap1() {
|
||||||
|
float[] rgb = {1};
|
||||||
|
mapper.map(rgb);
|
||||||
|
assertArrayEquals(new float[]{0.5f}, rgb, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testMap16() {
|
||||||
|
float[] rgb = {15.999999f};
|
||||||
|
mapper.map(rgb);
|
||||||
|
assertArrayEquals(new float[]{1}, rgb, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testMapMax() {
|
||||||
|
float[] rgb = {Float.MAX_VALUE};
|
||||||
|
mapper.map(rgb);
|
||||||
|
assertArrayEquals(new float[]{1}, rgb, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
package com.twelvemonkeys.imageio.plugins.hdr.tonemap;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertArrayEquals;
|
||||||
|
|
||||||
|
public class NullToneMapperTest {
|
||||||
|
private final NullToneMapper mapper = new NullToneMapper();
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testMap0() {
|
||||||
|
float[] rgb = {0};
|
||||||
|
mapper.map(rgb);
|
||||||
|
assertArrayEquals(new float[]{0}, rgb, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testMap1() {
|
||||||
|
float[] rgb = {1};
|
||||||
|
mapper.map(rgb);
|
||||||
|
assertArrayEquals(new float[]{1}, rgb, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testMapMax() {
|
||||||
|
float[] rgb = {Float.MAX_VALUE};
|
||||||
|
mapper.map(rgb);
|
||||||
|
assertArrayEquals(new float[]{Float.MAX_VALUE}, rgb, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -4,7 +4,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>com.twelvemonkeys.imageio</groupId>
|
<groupId>com.twelvemonkeys.imageio</groupId>
|
||||||
<artifactId>imageio</artifactId>
|
<artifactId>imageio</artifactId>
|
||||||
<version>3.5</version>
|
<version>3.6.2</version>
|
||||||
</parent>
|
</parent>
|
||||||
<artifactId>imageio-icns</artifactId>
|
<artifactId>imageio-icns</artifactId>
|
||||||
<name>TwelveMonkeys :: ImageIO :: ICNS plugin</name>
|
<name>TwelveMonkeys :: ImageIO :: ICNS plugin</name>
|
||||||
@@ -19,6 +19,7 @@
|
|||||||
<groupId>com.twelvemonkeys.imageio</groupId>
|
<groupId>com.twelvemonkeys.imageio</groupId>
|
||||||
<artifactId>imageio-core</artifactId>
|
<artifactId>imageio-core</artifactId>
|
||||||
<type>test-jar</type>
|
<type>test-jar</type>
|
||||||
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
</project>
|
</project>
|
||||||
|
|||||||
@@ -31,10 +31,10 @@
|
|||||||
package com.twelvemonkeys.imageio.plugins.icns;
|
package com.twelvemonkeys.imageio.plugins.icns;
|
||||||
|
|
||||||
import com.twelvemonkeys.imageio.util.ImageReaderAbstractTest;
|
import com.twelvemonkeys.imageio.util.ImageReaderAbstractTest;
|
||||||
|
|
||||||
import org.junit.Ignore;
|
import org.junit.Ignore;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import javax.imageio.ImageReader;
|
|
||||||
import javax.imageio.spi.ImageReaderSpi;
|
import javax.imageio.spi.ImageReaderSpi;
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@@ -49,7 +49,12 @@ import java.util.List;
|
|||||||
* @author last modified by $Author: haraldk$
|
* @author last modified by $Author: haraldk$
|
||||||
* @version $Id: ICNSImageReaderTest.java,v 1.0 25.10.11 18:44 haraldk Exp$
|
* @version $Id: ICNSImageReaderTest.java,v 1.0 25.10.11 18:44 haraldk Exp$
|
||||||
*/
|
*/
|
||||||
public class ICNSImageReaderTest extends ImageReaderAbstractTest {
|
public class ICNSImageReaderTest extends ImageReaderAbstractTest<ICNSImageReader> {
|
||||||
|
@Override
|
||||||
|
protected ImageReaderSpi createProvider() {
|
||||||
|
return new ICNSImageReaderSpi();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected List<TestData> getTestData() {
|
protected List<TestData> getTestData() {
|
||||||
return Arrays.asList(
|
return Arrays.asList(
|
||||||
@@ -105,21 +110,6 @@ public class ICNSImageReaderTest extends ImageReaderAbstractTest {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
protected ImageReaderSpi createProvider() {
|
|
||||||
return new ICNSImageReaderSpi();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected ImageReader createReader() {
|
|
||||||
return new ICNSImageReader();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Class getReaderClass() {
|
|
||||||
return ICNSImageReader.class;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected List<String> getFormatNames() {
|
protected List<String> getFormatNames() {
|
||||||
return Collections.singletonList("icns");
|
return Collections.singletonList("icns");
|
||||||
|
|||||||
@@ -31,11 +31,13 @@
|
|||||||
package com.twelvemonkeys.imageio.plugins.icns;
|
package com.twelvemonkeys.imageio.plugins.icns;
|
||||||
|
|
||||||
import com.twelvemonkeys.imageio.util.ImageWriterAbstractTest;
|
import com.twelvemonkeys.imageio.util.ImageWriterAbstractTest;
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import javax.imageio.IIOImage;
|
import javax.imageio.IIOImage;
|
||||||
import javax.imageio.ImageIO;
|
import javax.imageio.ImageIO;
|
||||||
import javax.imageio.ImageWriter;
|
import javax.imageio.ImageWriter;
|
||||||
|
import javax.imageio.spi.ImageWriterSpi;
|
||||||
import javax.imageio.stream.ImageOutputStream;
|
import javax.imageio.stream.ImageOutputStream;
|
||||||
import java.awt.image.BufferedImage;
|
import java.awt.image.BufferedImage;
|
||||||
import java.awt.image.RenderedImage;
|
import java.awt.image.RenderedImage;
|
||||||
@@ -53,13 +55,11 @@ import static org.junit.Assert.assertTrue;
|
|||||||
* @author last modified by $Author: harald.kuhr$
|
* @author last modified by $Author: harald.kuhr$
|
||||||
* @version $Id: ICNSImageWriterTest.java,v 1.0 25/08/2018 harald.kuhr Exp$
|
* @version $Id: ICNSImageWriterTest.java,v 1.0 25/08/2018 harald.kuhr Exp$
|
||||||
*/
|
*/
|
||||||
public class ICNSImageWriterTest extends ImageWriterAbstractTest {
|
public class ICNSImageWriterTest extends ImageWriterAbstractTest<ICNSImageWriter> {
|
||||||
|
|
||||||
private final ICNSImageWriterSpi provider = new ICNSImageWriterSpi();
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected ImageWriter createImageWriter() {
|
protected ImageWriterSpi createProvider() {
|
||||||
return provider.createWriterInstance(null);
|
return new ICNSImageWriterSpi();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -81,7 +81,7 @@ public class ICNSImageWriterTest extends ImageWriterAbstractTest {
|
|||||||
@Test(expected = IllegalArgumentException.class)
|
@Test(expected = IllegalArgumentException.class)
|
||||||
public void testWriteNonSquare() throws IOException {
|
public void testWriteNonSquare() throws IOException {
|
||||||
// ICNS only supports square icons (except some arcane 16x12 we don't currently support)
|
// ICNS only supports square icons (except some arcane 16x12 we don't currently support)
|
||||||
ImageWriter writer = createImageWriter();
|
ImageWriter writer = createWriter();
|
||||||
try (ImageOutputStream stream = ImageIO.createImageOutputStream(new ByteArrayOutputStream())) {
|
try (ImageOutputStream stream = ImageIO.createImageOutputStream(new ByteArrayOutputStream())) {
|
||||||
|
|
||||||
writer.setOutput(stream);
|
writer.setOutput(stream);
|
||||||
@@ -97,7 +97,7 @@ public class ICNSImageWriterTest extends ImageWriterAbstractTest {
|
|||||||
@Test(expected = IllegalArgumentException.class)
|
@Test(expected = IllegalArgumentException.class)
|
||||||
public void testWriteBadSize() throws IOException {
|
public void testWriteBadSize() throws IOException {
|
||||||
// ICNS only supports sizes in multiples of 2 (16, 32, 64, ..., 1024 + 48 and 96)
|
// ICNS only supports sizes in multiples of 2 (16, 32, 64, ..., 1024 + 48 and 96)
|
||||||
ImageWriter writer = createImageWriter();
|
ImageWriter writer = createWriter();
|
||||||
try (ImageOutputStream stream = ImageIO.createImageOutputStream(new ByteArrayOutputStream())) {
|
try (ImageOutputStream stream = ImageIO.createImageOutputStream(new ByteArrayOutputStream())) {
|
||||||
|
|
||||||
writer.setOutput(stream);
|
writer.setOutput(stream);
|
||||||
@@ -111,8 +111,8 @@ public class ICNSImageWriterTest extends ImageWriterAbstractTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSequencesSupported() {
|
public void testSequencesSupported() throws IOException {
|
||||||
ImageWriter writer = createImageWriter();
|
ImageWriter writer = createWriter();
|
||||||
try {
|
try {
|
||||||
assertTrue(writer.canWriteSequence());
|
assertTrue(writer.canWriteSequence());
|
||||||
}
|
}
|
||||||
@@ -124,7 +124,7 @@ public class ICNSImageWriterTest extends ImageWriterAbstractTest {
|
|||||||
@Test(expected = IllegalStateException.class)
|
@Test(expected = IllegalStateException.class)
|
||||||
public void testWriteSequenceNotStarted() throws IOException {
|
public void testWriteSequenceNotStarted() throws IOException {
|
||||||
// ICNS only supports sizes in multiples of 2 (16, 32, 64, ..., 1024 + 48 and 96)
|
// ICNS only supports sizes in multiples of 2 (16, 32, 64, ..., 1024 + 48 and 96)
|
||||||
ImageWriter writer = createImageWriter();
|
ImageWriter writer = createWriter();
|
||||||
try (ImageOutputStream stream = ImageIO.createImageOutputStream(new ByteArrayOutputStream())) {
|
try (ImageOutputStream stream = ImageIO.createImageOutputStream(new ByteArrayOutputStream())) {
|
||||||
|
|
||||||
writer.setOutput(stream);
|
writer.setOutput(stream);
|
||||||
@@ -141,7 +141,7 @@ public class ICNSImageWriterTest extends ImageWriterAbstractTest {
|
|||||||
@Test(expected = IllegalStateException.class)
|
@Test(expected = IllegalStateException.class)
|
||||||
public void testEndSequenceNotStarted() throws IOException {
|
public void testEndSequenceNotStarted() throws IOException {
|
||||||
// ICNS only supports sizes in multiples of 2 (16, 32, 64, ..., 1024 + 48 and 96)
|
// ICNS only supports sizes in multiples of 2 (16, 32, 64, ..., 1024 + 48 and 96)
|
||||||
ImageWriter writer = createImageWriter();
|
ImageWriter writer = createWriter();
|
||||||
try (ImageOutputStream stream = ImageIO.createImageOutputStream(new ByteArrayOutputStream())) {
|
try (ImageOutputStream stream = ImageIO.createImageOutputStream(new ByteArrayOutputStream())) {
|
||||||
|
|
||||||
writer.setOutput(stream);
|
writer.setOutput(stream);
|
||||||
@@ -155,7 +155,7 @@ public class ICNSImageWriterTest extends ImageWriterAbstractTest {
|
|||||||
@Test(expected = IllegalStateException.class)
|
@Test(expected = IllegalStateException.class)
|
||||||
public void testPrepareSequenceAlreadyStarted() throws IOException {
|
public void testPrepareSequenceAlreadyStarted() throws IOException {
|
||||||
// ICNS only supports sizes in multiples of 2 (16, 32, 64, ..., 1024 + 48 and 96)
|
// ICNS only supports sizes in multiples of 2 (16, 32, 64, ..., 1024 + 48 and 96)
|
||||||
ImageWriter writer = createImageWriter();
|
ImageWriter writer = createWriter();
|
||||||
try (ImageOutputStream stream = ImageIO.createImageOutputStream(new ByteArrayOutputStream())) {
|
try (ImageOutputStream stream = ImageIO.createImageOutputStream(new ByteArrayOutputStream())) {
|
||||||
|
|
||||||
writer.setOutput(stream);
|
writer.setOutput(stream);
|
||||||
@@ -169,7 +169,7 @@ public class ICNSImageWriterTest extends ImageWriterAbstractTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testWriteSequence() throws IOException {
|
public void testWriteSequence() throws IOException {
|
||||||
ImageWriter writer = createImageWriter();
|
ImageWriter writer = createWriter();
|
||||||
ByteArrayOutputStream output = new ByteArrayOutputStream();
|
ByteArrayOutputStream output = new ByteArrayOutputStream();
|
||||||
|
|
||||||
try (ImageOutputStream stream = ImageIO.createImageOutputStream(output)) {
|
try (ImageOutputStream stream = ImageIO.createImageOutputStream(output)) {
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>com.twelvemonkeys.imageio</groupId>
|
<groupId>com.twelvemonkeys.imageio</groupId>
|
||||||
<artifactId>imageio</artifactId>
|
<artifactId>imageio</artifactId>
|
||||||
<version>3.5</version>
|
<version>3.6.2</version>
|
||||||
</parent>
|
</parent>
|
||||||
<artifactId>imageio-iff</artifactId>
|
<artifactId>imageio-iff</artifactId>
|
||||||
<name>TwelveMonkeys :: ImageIO :: IFF plugin</name>
|
<name>TwelveMonkeys :: ImageIO :: IFF plugin</name>
|
||||||
@@ -22,6 +22,7 @@
|
|||||||
<groupId>com.twelvemonkeys.imageio</groupId>
|
<groupId>com.twelvemonkeys.imageio</groupId>
|
||||||
<artifactId>imageio-core</artifactId>
|
<artifactId>imageio-core</artifactId>
|
||||||
<type>test-jar</type>
|
<type>test-jar</type>
|
||||||
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
</project>
|
</project>
|
||||||
|
|||||||
@@ -31,6 +31,7 @@
|
|||||||
package com.twelvemonkeys.imageio.plugins.iff;
|
package com.twelvemonkeys.imageio.plugins.iff;
|
||||||
|
|
||||||
import com.twelvemonkeys.imageio.util.ImageReaderAbstractTest;
|
import com.twelvemonkeys.imageio.util.ImageReaderAbstractTest;
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import javax.imageio.ImageIO;
|
import javax.imageio.ImageIO;
|
||||||
@@ -54,6 +55,12 @@ import static org.junit.Assert.*;
|
|||||||
* @version $Id: IFFImageReaderTestCase.java,v 1.0 Apr 1, 2008 10:39:17 PM haraldk Exp$
|
* @version $Id: IFFImageReaderTestCase.java,v 1.0 Apr 1, 2008 10:39:17 PM haraldk Exp$
|
||||||
*/
|
*/
|
||||||
public class IFFImageReaderTest extends ImageReaderAbstractTest<IFFImageReader> {
|
public class IFFImageReaderTest extends ImageReaderAbstractTest<IFFImageReader> {
|
||||||
|
@Override
|
||||||
|
protected ImageReaderSpi createProvider() {
|
||||||
|
return new IFFImageReaderSpi();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
protected List<TestData> getTestData() {
|
protected List<TestData> getTestData() {
|
||||||
return Arrays.asList(
|
return Arrays.asList(
|
||||||
// 32 bit - Ok
|
// 32 bit - Ok
|
||||||
@@ -85,22 +92,17 @@ public class IFFImageReaderTest extends ImageReaderAbstractTest<IFFImageReader>
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected ImageReaderSpi createProvider() {
|
@Override
|
||||||
return new IFFImageReaderSpi();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected Class<IFFImageReader> getReaderClass() {
|
|
||||||
return IFFImageReader.class;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected List<String> getFormatNames() {
|
protected List<String> getFormatNames() {
|
||||||
return Collections.singletonList("iff");
|
return Collections.singletonList("iff");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
protected List<String> getSuffixes() {
|
protected List<String> getSuffixes() {
|
||||||
return Arrays.asList("iff", "ilbm", "ham", "ham8", "lbm");
|
return Arrays.asList("iff", "ilbm", "ham", "ham8", "lbm");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
protected List<String> getMIMETypes() {
|
protected List<String> getMIMETypes() {
|
||||||
return Arrays.asList("image/iff", "image/x-iff");
|
return Arrays.asList("image/iff", "image/x-iff");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,10 +32,12 @@ package com.twelvemonkeys.imageio.plugins.iff;
|
|||||||
|
|
||||||
import com.twelvemonkeys.image.MonochromeColorModel;
|
import com.twelvemonkeys.image.MonochromeColorModel;
|
||||||
import com.twelvemonkeys.imageio.util.ImageWriterAbstractTest;
|
import com.twelvemonkeys.imageio.util.ImageWriterAbstractTest;
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import javax.imageio.ImageIO;
|
import javax.imageio.ImageIO;
|
||||||
import javax.imageio.ImageWriter;
|
import javax.imageio.ImageWriter;
|
||||||
|
import javax.imageio.spi.ImageWriterSpi;
|
||||||
import javax.imageio.stream.ImageInputStream;
|
import javax.imageio.stream.ImageInputStream;
|
||||||
import javax.imageio.stream.ImageOutputStream;
|
import javax.imageio.stream.ImageOutputStream;
|
||||||
import java.awt.color.ColorSpace;
|
import java.awt.color.ColorSpace;
|
||||||
@@ -56,12 +58,10 @@ import static org.junit.Assert.*;
|
|||||||
* @author last modified by $Author: haraldk$
|
* @author last modified by $Author: haraldk$
|
||||||
* @version $Id: JPEG2000ImageWriterTest.java,v 1.0 20.01.12 12:19 haraldk Exp$
|
* @version $Id: JPEG2000ImageWriterTest.java,v 1.0 20.01.12 12:19 haraldk Exp$
|
||||||
*/
|
*/
|
||||||
public class IFFImageWriterTest extends ImageWriterAbstractTest {
|
public class IFFImageWriterTest extends ImageWriterAbstractTest<IFFImageWriter> {
|
||||||
private final IFFImageWriterSpi provider = new IFFImageWriterSpi();
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected ImageWriter createImageWriter() {
|
protected ImageWriterSpi createProvider() {
|
||||||
return new IFFImageWriter(provider);
|
return new IFFImageWriterSpi();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -81,7 +81,7 @@ public class IFFImageWriterTest extends ImageWriterAbstractTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testWriteReadCompare() throws IOException {
|
public void testWriteReadCompare() throws IOException {
|
||||||
ImageWriter writer = createImageWriter();
|
ImageWriter writer = createWriter();
|
||||||
|
|
||||||
List<? extends RenderedImage> testData = getTestData();
|
List<? extends RenderedImage> testData = getTestData();
|
||||||
|
|
||||||
@@ -116,9 +116,7 @@ public class IFFImageWriterTest extends ImageWriterAbstractTest {
|
|||||||
assertSameData(original, written);
|
assertSameData(original, written);
|
||||||
}
|
}
|
||||||
catch (IOException e) {
|
catch (IOException e) {
|
||||||
AssertionError fail = new AssertionError("Failure writing test data " + i + " " + e);
|
throw new AssertionError("Failure writing test data " + i + " " + e, e);
|
||||||
fail.initCause(e);
|
|
||||||
throw fail;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>com.twelvemonkeys.imageio</groupId>
|
<groupId>com.twelvemonkeys.imageio</groupId>
|
||||||
<artifactId>imageio</artifactId>
|
<artifactId>imageio</artifactId>
|
||||||
<version>3.5</version>
|
<version>3.6.2</version>
|
||||||
</parent>
|
</parent>
|
||||||
<artifactId>imageio-jpeg</artifactId>
|
<artifactId>imageio-jpeg</artifactId>
|
||||||
<name>TwelveMonkeys :: ImageIO :: JPEG plugin</name>
|
<name>TwelveMonkeys :: ImageIO :: JPEG plugin</name>
|
||||||
@@ -21,6 +21,7 @@
|
|||||||
<groupId>com.twelvemonkeys.imageio</groupId>
|
<groupId>com.twelvemonkeys.imageio</groupId>
|
||||||
<artifactId>imageio-core</artifactId>
|
<artifactId>imageio-core</artifactId>
|
||||||
<type>test-jar</type>
|
<type>test-jar</type>
|
||||||
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.twelvemonkeys.imageio</groupId>
|
<groupId>com.twelvemonkeys.imageio</groupId>
|
||||||
|
|||||||
@@ -35,27 +35,27 @@ package com.twelvemonkeys.imageio.plugins.jpeg;
|
|||||||
import com.twelvemonkeys.imageio.metadata.jpeg.JPEG;
|
import com.twelvemonkeys.imageio.metadata.jpeg.JPEG;
|
||||||
|
|
||||||
import javax.imageio.IIOException;
|
import javax.imageio.IIOException;
|
||||||
|
import javax.imageio.plugins.jpeg.JPEGHuffmanTable;
|
||||||
import java.io.DataInput;
|
import java.io.DataInput;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
final class HuffmanTable extends Segment {
|
final class HuffmanTable extends Segment {
|
||||||
|
|
||||||
private final int l[][][] = new int[4][2][16];
|
private final short[][][] l = new short[4][2][16];
|
||||||
private final int th[] = new int[4]; // 1: this table is present
|
private final short[][][][] v = new short[4][2][16][200]; // tables
|
||||||
final int v[][][][] = new int[4][2][16][200]; // tables
|
private final boolean[][] tc = new boolean[4][2]; // 1: this table is present
|
||||||
final int[][] tc = new int[4][2]; // 1: this table is present
|
|
||||||
|
|
||||||
static final int MSB = 0x80000000;
|
private static final int MSB = 0x80000000;
|
||||||
|
|
||||||
private HuffmanTable() {
|
private HuffmanTable() {
|
||||||
super(JPEG.DHT);
|
super(JPEG.DHT);
|
||||||
}
|
}
|
||||||
|
|
||||||
void buildHuffTables(final int[][][] HuffTab) throws IOException {
|
void buildHuffTables(final int[][][] huffTab) throws IOException {
|
||||||
for (int t = 0; t < 4; t++) {
|
for (int t = 0; t < 4; t++) {
|
||||||
for (int c = 0; c < 2; c++) {
|
for (int c = 0; c < 2; c++) {
|
||||||
if (tc[t][c] != 0) {
|
if (tc[t][c]) {
|
||||||
buildHuffTable(HuffTab[t][c], l[t][c], v[t][c]);
|
buildHuffTable(huffTab[t][c], l[t][c], v[t][c]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -68,7 +68,7 @@ final class HuffmanTable extends Segment {
|
|||||||
// V[i][j] Huffman Value (length=i)
|
// V[i][j] Huffman Value (length=i)
|
||||||
// Effect:
|
// Effect:
|
||||||
// build up HuffTab[t][c] using L and V.
|
// build up HuffTab[t][c] using L and V.
|
||||||
private void buildHuffTable(final int tab[], final int L[], final int V[][]) throws IOException {
|
private void buildHuffTable(final int[] tab, final short[] L, final short[][] V) throws IOException {
|
||||||
int temp = 256;
|
int temp = 256;
|
||||||
int k = 0;
|
int k = 0;
|
||||||
|
|
||||||
@@ -112,7 +112,7 @@ final class HuffmanTable extends Segment {
|
|||||||
|
|
||||||
for (int t = 0; t < tc.length; t++) {
|
for (int t = 0; t < tc.length; t++) {
|
||||||
for (int c = 0; c < tc[t].length; c++) {
|
for (int c = 0; c < tc[t].length; c++) {
|
||||||
if (tc[t][c] != 0) {
|
if (tc[t][c]) {
|
||||||
if (builder.length() > 4) {
|
if (builder.length() > 4) {
|
||||||
builder.append(", ");
|
builder.append(", ");
|
||||||
}
|
}
|
||||||
@@ -149,11 +149,10 @@ final class HuffmanTable extends Segment {
|
|||||||
throw new IIOException("Unexpected JPEG Huffman Table class (> 2): " + c);
|
throw new IIOException("Unexpected JPEG Huffman Table class (> 2): " + c);
|
||||||
}
|
}
|
||||||
|
|
||||||
table.th[t] = 1;
|
table.tc[t][c] = true;
|
||||||
table.tc[t][c] = 1;
|
|
||||||
|
|
||||||
for (int i = 0; i < 16; i++) {
|
for (int i = 0; i < 16; i++) {
|
||||||
table.l[t][c][i] = data.readUnsignedByte();
|
table.l[t][c][i] = (short) data.readUnsignedByte();
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -162,7 +161,7 @@ final class HuffmanTable extends Segment {
|
|||||||
if (count > length) {
|
if (count > length) {
|
||||||
throw new IIOException("JPEG Huffman Table format error");
|
throw new IIOException("JPEG Huffman Table format error");
|
||||||
}
|
}
|
||||||
table.v[t][c][i][j] = data.readUnsignedByte();
|
table.v[t][c][i][j] = (short) data.readUnsignedByte();
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -174,4 +173,41 @@ final class HuffmanTable extends Segment {
|
|||||||
|
|
||||||
return table;
|
return table;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isPresent(int tableId, int tableClass) {
|
||||||
|
return tc[tableId][tableClass];
|
||||||
|
}
|
||||||
|
|
||||||
|
private short[] lengths(int tableId, int tableClass) {
|
||||||
|
// TODO: Consider stripping the 0s?
|
||||||
|
return l[tableId][tableClass];
|
||||||
|
}
|
||||||
|
|
||||||
|
private short[] tables(int tableId, int tableClass) {
|
||||||
|
// Find sum of lengths
|
||||||
|
short[] lengths = lengths(tableId, tableClass);
|
||||||
|
|
||||||
|
int sumOfLengths = 0;
|
||||||
|
for (int length : lengths) {
|
||||||
|
sumOfLengths += length;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Flatten the tables
|
||||||
|
short[] tables = new short[sumOfLengths];
|
||||||
|
|
||||||
|
int pos = 0;
|
||||||
|
for (int i = 0; i < 16; i++) {
|
||||||
|
short[] table = v[tableId][tableClass][i];
|
||||||
|
short length = lengths[i];
|
||||||
|
|
||||||
|
System.arraycopy(table, 0, tables, pos, length);
|
||||||
|
pos += length;
|
||||||
|
}
|
||||||
|
|
||||||
|
return tables;
|
||||||
|
}
|
||||||
|
|
||||||
|
JPEGHuffmanTable toNativeTable(int tableId, int tableClass) {
|
||||||
|
return new JPEGHuffmanTable(lengths(tableId, tableClass), tables(tableId, tableClass));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -113,7 +113,7 @@ final class JFXXThumbnailReader extends ThumbnailReader {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cachedThumbnail = pixelsExposed ? null : new SoftReference<BufferedImage>(thumbnail);
|
cachedThumbnail = pixelsExposed ? null : new SoftReference<>(thumbnail);
|
||||||
|
|
||||||
return thumbnail;
|
return thumbnail;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,10 +30,16 @@
|
|||||||
package com.twelvemonkeys.imageio.plugins.jpeg;
|
package com.twelvemonkeys.imageio.plugins.jpeg;
|
||||||
|
|
||||||
import com.twelvemonkeys.imageio.AbstractMetadata;
|
import com.twelvemonkeys.imageio.AbstractMetadata;
|
||||||
|
import com.twelvemonkeys.imageio.metadata.CompoundDirectory;
|
||||||
|
import com.twelvemonkeys.imageio.metadata.Directory;
|
||||||
|
import com.twelvemonkeys.imageio.metadata.Entry;
|
||||||
import com.twelvemonkeys.imageio.metadata.jpeg.JPEG;
|
import com.twelvemonkeys.imageio.metadata.jpeg.JPEG;
|
||||||
|
import com.twelvemonkeys.imageio.metadata.tiff.TIFF;
|
||||||
import org.w3c.dom.Node;
|
import org.w3c.dom.Node;
|
||||||
|
|
||||||
|
import javax.imageio.IIOException;
|
||||||
import javax.imageio.metadata.IIOMetadataNode;
|
import javax.imageio.metadata.IIOMetadataNode;
|
||||||
|
import java.awt.color.ICC_Profile;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -45,31 +51,89 @@ import java.util.List;
|
|||||||
*/
|
*/
|
||||||
class JPEGImage10Metadata extends AbstractMetadata {
|
class JPEGImage10Metadata extends AbstractMetadata {
|
||||||
|
|
||||||
// TODO: Clean up. Consider just making the meta data classes we were trying to avoid in the first place....
|
/**
|
||||||
|
* Native metadata format name
|
||||||
|
*/
|
||||||
|
static final String JAVAX_IMAGEIO_JPEG_IMAGE_1_0 = "javax_imageio_jpeg_image_1.0";
|
||||||
|
|
||||||
|
// TODO: Create our own native format, which is simply markerSequence from the Sun format, with the segments as-is, in sequence...
|
||||||
|
// + add special case for app segments, containing appXX + identifier (ie. <app0JFIF /> to <app0 identifier="JFIF" /> or <app app="0" identifier="JFIF" />
|
||||||
|
|
||||||
private final List<Segment> segments;
|
private final List<Segment> segments;
|
||||||
|
|
||||||
JPEGImage10Metadata(List<Segment> segments) {
|
private final Frame frame;
|
||||||
super(true, JPEGImage10MetadataCleaner.JAVAX_IMAGEIO_JPEG_IMAGE_1_0, null, null, null);
|
private final JFIF jfif;
|
||||||
|
private final AdobeDCT adobeDCT;
|
||||||
|
private final JFXX jfxx;
|
||||||
|
private final ICC_Profile embeddedICCProfile;
|
||||||
|
|
||||||
|
private final CompoundDirectory exif;
|
||||||
|
|
||||||
|
// TODO: Consider moving all the metadata stuff from the reader, over here...
|
||||||
|
JPEGImage10Metadata(final List<Segment> segments, Frame frame, JFIF jfif, JFXX jfxx, ICC_Profile embeddedICCProfile, AdobeDCT adobeDCT, final CompoundDirectory exif) {
|
||||||
|
super(true, JAVAX_IMAGEIO_JPEG_IMAGE_1_0, null, null, null);
|
||||||
|
|
||||||
this.segments = segments;
|
this.segments = segments;
|
||||||
|
this.frame = frame;
|
||||||
|
this.jfif = jfif;
|
||||||
|
this.adobeDCT = adobeDCT;
|
||||||
|
this.jfxx = jfxx;
|
||||||
|
this.embeddedICCProfile = embeddedICCProfile;
|
||||||
|
this.exif = exif;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Node getNativeTree() {
|
protected Node getNativeTree() {
|
||||||
IIOMetadataNode root = new IIOMetadataNode(JPEGImage10MetadataCleaner.JAVAX_IMAGEIO_JPEG_IMAGE_1_0);
|
IIOMetadataNode root = new IIOMetadataNode(JAVAX_IMAGEIO_JPEG_IMAGE_1_0);
|
||||||
|
|
||||||
IIOMetadataNode jpegVariety = new IIOMetadataNode("JPEGvariety");
|
IIOMetadataNode jpegVariety = new IIOMetadataNode("JPEGvariety");
|
||||||
root.appendChild(jpegVariety);
|
boolean isJFIF = jfif != null;
|
||||||
// TODO: If we have JFIF, append in JPEGvariety, but can't happen for lossless
|
if (isJFIF) {
|
||||||
|
IIOMetadataNode app0JFIF = new IIOMetadataNode("app0JFIF");
|
||||||
|
app0JFIF.setAttribute("majorVersion", Integer.toString(jfif.majorVersion));
|
||||||
|
app0JFIF.setAttribute("minorVersion", Integer.toString(jfif.minorVersion));
|
||||||
|
|
||||||
|
app0JFIF.setAttribute("resUnits", Integer.toString(jfif.units));
|
||||||
|
app0JFIF.setAttribute("Xdensity", Integer.toString(jfif.xDensity));
|
||||||
|
app0JFIF.setAttribute("Ydensity", Integer.toString(jfif.yDensity));
|
||||||
|
|
||||||
|
app0JFIF.setAttribute("thumbWidth", Integer.toString(jfif.xThumbnail));
|
||||||
|
app0JFIF.setAttribute("thumbHeight", Integer.toString(jfif.yThumbnail));
|
||||||
|
|
||||||
|
jpegVariety.appendChild(app0JFIF);
|
||||||
|
|
||||||
|
// Due to format oddity, add JFXX and app2ICC as subnodes here...
|
||||||
|
// ...and ignore them below, if added...
|
||||||
|
apendJFXX(app0JFIF);
|
||||||
|
appendICCProfile(app0JFIF);
|
||||||
|
}
|
||||||
|
|
||||||
|
root.appendChild(jpegVariety);
|
||||||
|
|
||||||
|
appendMarkerSequence(root, segments, isJFIF);
|
||||||
|
|
||||||
|
return root;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void appendMarkerSequence(IIOMetadataNode root, List<Segment> segments, boolean isJFIF) {
|
||||||
IIOMetadataNode markerSequence = new IIOMetadataNode("markerSequence");
|
IIOMetadataNode markerSequence = new IIOMetadataNode("markerSequence");
|
||||||
root.appendChild(markerSequence);
|
root.appendChild(markerSequence);
|
||||||
|
|
||||||
for (Segment segment : segments)
|
for (Segment segment : segments)
|
||||||
switch (segment.marker) {
|
switch (segment.marker) {
|
||||||
// SOF3 is the only one supported by now
|
case JPEG.SOF0:
|
||||||
|
case JPEG.SOF1:
|
||||||
|
case JPEG.SOF2:
|
||||||
case JPEG.SOF3:
|
case JPEG.SOF3:
|
||||||
|
case JPEG.SOF5:
|
||||||
|
case JPEG.SOF6:
|
||||||
|
case JPEG.SOF7:
|
||||||
|
case JPEG.SOF9:
|
||||||
|
case JPEG.SOF10:
|
||||||
|
case JPEG.SOF11:
|
||||||
|
case JPEG.SOF13:
|
||||||
|
case JPEG.SOF14:
|
||||||
|
case JPEG.SOF15:
|
||||||
Frame sofSegment = (Frame) segment;
|
Frame sofSegment = (Frame) segment;
|
||||||
|
|
||||||
IIOMetadataNode sof = new IIOMetadataNode("sof");
|
IIOMetadataNode sof = new IIOMetadataNode("sof");
|
||||||
@@ -96,13 +160,13 @@ class JPEGImage10Metadata extends AbstractMetadata {
|
|||||||
HuffmanTable huffmanTable = (HuffmanTable) segment;
|
HuffmanTable huffmanTable = (HuffmanTable) segment;
|
||||||
IIOMetadataNode dht = new IIOMetadataNode("dht");
|
IIOMetadataNode dht = new IIOMetadataNode("dht");
|
||||||
|
|
||||||
// Uses fixed tables...
|
|
||||||
for (int i = 0; i < 4; i++) {
|
for (int i = 0; i < 4; i++) {
|
||||||
for (int j = 0; j < 2; j++) {
|
for (int c = 0; c < 2; c++) {
|
||||||
if (huffmanTable.tc[i][j] != 0) {
|
if (huffmanTable.isPresent(i, c)) {
|
||||||
IIOMetadataNode dhtable = new IIOMetadataNode("dhtable");
|
IIOMetadataNode dhtable = new IIOMetadataNode("dhtable");
|
||||||
dhtable.setAttribute("class", String.valueOf(j));
|
dhtable.setAttribute("class", String.valueOf(c));
|
||||||
dhtable.setAttribute("htableId", String.valueOf(i));
|
dhtable.setAttribute("htableId", String.valueOf(i));
|
||||||
|
dhtable.setUserObject(huffmanTable.toNativeTable(i, c));
|
||||||
dht.appendChild(dhtable);
|
dht.appendChild(dhtable);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -112,8 +176,28 @@ class JPEGImage10Metadata extends AbstractMetadata {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case JPEG.DQT:
|
case JPEG.DQT:
|
||||||
markerSequence.appendChild(new IIOMetadataNode("dqt"));
|
QuantizationTable quantizationTable = (QuantizationTable) segment;
|
||||||
// TODO:
|
IIOMetadataNode dqt = new IIOMetadataNode("dqt");
|
||||||
|
|
||||||
|
for (int i = 0; i < 4; i++) {
|
||||||
|
if (quantizationTable.isPresent(i)) {
|
||||||
|
IIOMetadataNode dqtable = new IIOMetadataNode("dqtable");
|
||||||
|
dqtable.setAttribute("elementPrecision", quantizationTable.precision(i) != 16 ? "0" : "1"); // 0 = 8 bits, 1 = 16 bits
|
||||||
|
dqtable.setAttribute("qtableId", Integer.toString(i));
|
||||||
|
dqtable.setUserObject(quantizationTable.toNativeTable(i));
|
||||||
|
dqt.appendChild(dqtable);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
markerSequence.appendChild(dqt);
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case JPEG.DRI:
|
||||||
|
RestartInterval restartInterval = (RestartInterval) segment;
|
||||||
|
IIOMetadataNode dri = new IIOMetadataNode("dri");
|
||||||
|
dri.setAttribute("interval", Integer.toString(restartInterval.interval));
|
||||||
|
markerSequence.appendChild(dri);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case JPEG.SOS:
|
case JPEG.SOS:
|
||||||
@@ -144,6 +228,25 @@ class JPEGImage10Metadata extends AbstractMetadata {
|
|||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case JPEG.APP0:
|
||||||
|
if (segment instanceof JFIF) {
|
||||||
|
// Either already added, or we'll ignore it anyway...
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if (isJFIF && segment instanceof JFXX) {
|
||||||
|
// Already added
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Else, fall through to unknown segment
|
||||||
|
|
||||||
|
case JPEG.APP2:
|
||||||
|
if (isJFIF && segment instanceof ICCProfile) {
|
||||||
|
// Already added
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// Else, fall through to unknown segment
|
||||||
|
|
||||||
case JPEG.APP14:
|
case JPEG.APP14:
|
||||||
if (segment instanceof AdobeDCT) {
|
if (segment instanceof AdobeDCT) {
|
||||||
AdobeDCT adobe = (AdobeDCT) segment;
|
AdobeDCT adobe = (AdobeDCT) segment;
|
||||||
@@ -165,32 +268,149 @@ class JPEGImage10Metadata extends AbstractMetadata {
|
|||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return root;
|
private void appendICCProfile(IIOMetadataNode app0JFIF) {
|
||||||
|
if (embeddedICCProfile != null) {
|
||||||
|
IIOMetadataNode app2ICC = new IIOMetadataNode("app2ICC");
|
||||||
|
app2ICC.setUserObject(embeddedICCProfile);
|
||||||
|
|
||||||
|
app0JFIF.appendChild(app2ICC);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void apendJFXX(IIOMetadataNode app0JFIF) {
|
||||||
|
if (jfxx != null) {
|
||||||
|
IIOMetadataNode jfxxNode = new IIOMetadataNode("JFXX");
|
||||||
|
app0JFIF.appendChild(jfxxNode);
|
||||||
|
|
||||||
|
IIOMetadataNode app0JFXX = new IIOMetadataNode("app0JFXX");
|
||||||
|
app0JFXX.setAttribute("extensionCode", Integer.toString(jfxx.extensionCode));
|
||||||
|
jfxxNode.appendChild(app0JFXX);
|
||||||
|
|
||||||
|
switch (jfxx.extensionCode) {
|
||||||
|
case JFXX.JPEG:
|
||||||
|
IIOMetadataNode thumbJPEG = new IIOMetadataNode("JFIFthumbJPEG");
|
||||||
|
thumbJPEG.appendChild(new IIOMetadataNode("markerSequence"));
|
||||||
|
// TODO: Insert segments in marker sequence...
|
||||||
|
// List<JPEGSegment> segments = JPEGSegmentUtil.readSegments(new ByteArrayImageInputStream(jfxx.thumbnail), JPEGSegmentUtil.ALL_SEGMENTS);
|
||||||
|
// Convert to Segment as in JPEGImageReader...
|
||||||
|
// appendMarkerSequence(thumbJPEG, segments, false);
|
||||||
|
|
||||||
|
app0JFXX.appendChild(thumbJPEG);
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case JFXX.INDEXED:
|
||||||
|
IIOMetadataNode thumbPalette = new IIOMetadataNode("JFIFthumbPalette");
|
||||||
|
thumbPalette.setAttribute("thumbWidth", Integer.toString(jfxx.thumbnail[0] & 0xFF));
|
||||||
|
thumbPalette.setAttribute("thumbHeight", Integer.toString(jfxx.thumbnail[1] & 0xFF));
|
||||||
|
app0JFXX.appendChild(thumbPalette);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case JFXX.RGB:
|
||||||
|
IIOMetadataNode thumbRGB = new IIOMetadataNode("JFIFthumbRGB");
|
||||||
|
thumbRGB.setAttribute("thumbWidth", Integer.toString(jfxx.thumbnail[0] & 0xFF));
|
||||||
|
thumbRGB.setAttribute("thumbHeight", Integer.toString(jfxx.thumbnail[1] & 0xFF));
|
||||||
|
app0JFXX.appendChild(thumbRGB);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected IIOMetadataNode getStandardChromaNode() {
|
protected IIOMetadataNode getStandardChromaNode() {
|
||||||
IIOMetadataNode chroma = new IIOMetadataNode("Chroma");
|
IIOMetadataNode chroma = new IIOMetadataNode("Chroma");
|
||||||
|
|
||||||
for (Segment segment : segments) {
|
IIOMetadataNode colorSpaceType = new IIOMetadataNode("ColorSpaceType");
|
||||||
if (segment instanceof Frame) {
|
colorSpaceType.setAttribute("name", getColorSpaceType());
|
||||||
Frame sofSegment = (Frame) segment;
|
chroma.appendChild(colorSpaceType);
|
||||||
IIOMetadataNode colorSpaceType = new IIOMetadataNode("ColorSpaceType");
|
|
||||||
colorSpaceType.setAttribute("name", sofSegment.componentsInFrame() == 1 ? "GRAY" : "RGB"); // TODO YCC, YCCK, CMYK etc
|
|
||||||
chroma.appendChild(colorSpaceType);
|
|
||||||
|
|
||||||
IIOMetadataNode numChannels = new IIOMetadataNode("NumChannels");
|
IIOMetadataNode numChannels = new IIOMetadataNode("NumChannels");
|
||||||
numChannels.setAttribute("value", String.valueOf(sofSegment.componentsInFrame()));
|
numChannels.setAttribute("value", String.valueOf(frame.componentsInFrame()));
|
||||||
chroma.appendChild(numChannels);
|
chroma.appendChild(numChannels);
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return chroma;
|
return chroma;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String getColorSpaceType() {
|
||||||
|
try {
|
||||||
|
JPEGColorSpace csType = JPEGImageReader.getSourceCSType(jfif, adobeDCT, frame);
|
||||||
|
|
||||||
|
switch (csType) {
|
||||||
|
case Gray:
|
||||||
|
case GrayA:
|
||||||
|
return "GRAY";
|
||||||
|
case YCbCr:
|
||||||
|
case YCbCrA:
|
||||||
|
return "YCbCr";
|
||||||
|
case RGB:
|
||||||
|
case RGBA:
|
||||||
|
return "RGB";
|
||||||
|
case PhotoYCC:
|
||||||
|
case PhotoYCCA:
|
||||||
|
return "PhotoYCC";
|
||||||
|
case YCCK:
|
||||||
|
return "YCCK";
|
||||||
|
case CMYK:
|
||||||
|
return "CMYK";
|
||||||
|
default:
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (IIOException ignore) {
|
||||||
|
}
|
||||||
|
|
||||||
|
return Integer.toString(frame.componentsInFrame(), 16) + "CLR";
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean hasAlpha() {
|
||||||
|
try {
|
||||||
|
JPEGColorSpace csType = JPEGImageReader.getSourceCSType(jfif, adobeDCT, frame);
|
||||||
|
|
||||||
|
switch (csType) {
|
||||||
|
case GrayA:
|
||||||
|
case YCbCrA:
|
||||||
|
case RGBA:
|
||||||
|
case PhotoYCCA:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (IIOException ignore) {
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isLossess() {
|
||||||
|
switch (frame.marker) {
|
||||||
|
case JPEG.SOF3:
|
||||||
|
case JPEG.SOF7:
|
||||||
|
case JPEG.SOF11:
|
||||||
|
case JPEG.SOF15:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected IIOMetadataNode getStandardTransparencyNode() {
|
||||||
|
if (hasAlpha()) {
|
||||||
|
IIOMetadataNode transparency = new IIOMetadataNode("Transparency");
|
||||||
|
|
||||||
|
IIOMetadataNode alpha = new IIOMetadataNode("Alpha");
|
||||||
|
alpha.setAttribute("value", "nonpremultipled");
|
||||||
|
transparency.appendChild(alpha);
|
||||||
|
|
||||||
|
return transparency;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected IIOMetadataNode getStandardCompressionNode() {
|
protected IIOMetadataNode getStandardCompressionNode() {
|
||||||
IIOMetadataNode compression = new IIOMetadataNode("Compression");
|
IIOMetadataNode compression = new IIOMetadataNode("Compression");
|
||||||
@@ -200,7 +420,7 @@ class JPEGImage10Metadata extends AbstractMetadata {
|
|||||||
compression.appendChild(compressionTypeName);
|
compression.appendChild(compressionTypeName);
|
||||||
|
|
||||||
IIOMetadataNode lossless = new IIOMetadataNode("Lossless");
|
IIOMetadataNode lossless = new IIOMetadataNode("Lossless");
|
||||||
lossless.setAttribute("value", "TRUE"); // TODO: For lossless only
|
lossless.setAttribute("value", isLossess() ? "TRUE" : "FALSE");
|
||||||
compression.appendChild(lossless);
|
compression.appendChild(lossless);
|
||||||
|
|
||||||
IIOMetadataNode numProgressiveScans = new IIOMetadataNode("NumProgressiveScans");
|
IIOMetadataNode numProgressiveScans = new IIOMetadataNode("NumProgressiveScans");
|
||||||
@@ -215,12 +435,67 @@ class JPEGImage10Metadata extends AbstractMetadata {
|
|||||||
IIOMetadataNode dimension = new IIOMetadataNode("Dimension");
|
IIOMetadataNode dimension = new IIOMetadataNode("Dimension");
|
||||||
|
|
||||||
IIOMetadataNode imageOrientation = new IIOMetadataNode("ImageOrientation");
|
IIOMetadataNode imageOrientation = new IIOMetadataNode("ImageOrientation");
|
||||||
imageOrientation.setAttribute("value", "normal"); // TODO
|
imageOrientation.setAttribute("value", getExifOrientation(exif));
|
||||||
dimension.appendChild(imageOrientation);
|
dimension.appendChild(imageOrientation);
|
||||||
|
|
||||||
|
if (jfif != null) {
|
||||||
|
// Aspect ratio
|
||||||
|
float xDensity = Math.max(1, jfif.xDensity);
|
||||||
|
float yDensity = Math.max(1, jfif.yDensity);
|
||||||
|
float aspectRatio = jfif.units == 0 ? xDensity / yDensity : yDensity / xDensity;
|
||||||
|
|
||||||
|
IIOMetadataNode pixelAspectRatio = new IIOMetadataNode("PixelAspectRatio");
|
||||||
|
pixelAspectRatio.setAttribute("value", Float.toString(aspectRatio));
|
||||||
|
dimension.insertBefore(pixelAspectRatio, imageOrientation); // Keep order
|
||||||
|
|
||||||
|
if (jfif.units != 0) {
|
||||||
|
// Pixel size
|
||||||
|
float scale = jfif.units == 1 ? 25.4F : 10.0F; // DPI or DPcm
|
||||||
|
|
||||||
|
IIOMetadataNode horizontalPixelSize = new IIOMetadataNode("HorizontalPixelSize");
|
||||||
|
horizontalPixelSize.setAttribute("value", Float.toString(scale / xDensity));
|
||||||
|
dimension.appendChild(horizontalPixelSize);
|
||||||
|
|
||||||
|
IIOMetadataNode verticalPixelSize = new IIOMetadataNode("VerticalPixelSize");
|
||||||
|
verticalPixelSize.setAttribute("value", Float.toString(scale / yDensity));
|
||||||
|
dimension.appendChild(verticalPixelSize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return dimension;
|
return dimension;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String getExifOrientation(Directory exif) {
|
||||||
|
if (exif != null) {
|
||||||
|
Entry orientationEntry = exif.getEntryById(TIFF.TAG_ORIENTATION);
|
||||||
|
|
||||||
|
if (orientationEntry != null) {
|
||||||
|
switch (((Number) orientationEntry.getValue()).intValue()) {
|
||||||
|
case 2:
|
||||||
|
return "FlipH";
|
||||||
|
case 3:
|
||||||
|
return "Rotate180";
|
||||||
|
case 4:
|
||||||
|
return "FlipV";
|
||||||
|
case 5:
|
||||||
|
return "FlipVRotate90";
|
||||||
|
case 6:
|
||||||
|
return "Rotate270";
|
||||||
|
case 7:
|
||||||
|
return "FlipHRotate90";
|
||||||
|
case 8:
|
||||||
|
return "Rotate90";
|
||||||
|
case 0:
|
||||||
|
case 1:
|
||||||
|
default:
|
||||||
|
// Fall-through
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return "Normal";
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected IIOMetadataNode getStandardTextNode() {
|
protected IIOMetadataNode getStandardTextNode() {
|
||||||
IIOMetadataNode text = new IIOMetadataNode("Text");
|
IIOMetadataNode text = new IIOMetadataNode("Text");
|
||||||
@@ -235,6 +510,10 @@ class JPEGImage10Metadata extends AbstractMetadata {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Add the following from Exif (as in TIFFMetadata)
|
||||||
|
// DocumentName, ImageDescription, Make, Model, PageName, Software, Artist, HostComputer, InkNames, Copyright:
|
||||||
|
// /Text/TextEntry@keyword = field name, /Text/TextEntry@value = field value.
|
||||||
|
|
||||||
return text.hasChildNodes() ? text : null;
|
return text.hasChildNodes() ? text : null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -52,11 +52,6 @@ import java.util.List;
|
|||||||
*/
|
*/
|
||||||
final class JPEGImage10MetadataCleaner {
|
final class JPEGImage10MetadataCleaner {
|
||||||
|
|
||||||
/**
|
|
||||||
* Native metadata format name
|
|
||||||
*/
|
|
||||||
static final String JAVAX_IMAGEIO_JPEG_IMAGE_1_0 = "javax_imageio_jpeg_image_1.0";
|
|
||||||
|
|
||||||
private final JPEGImageReader reader;
|
private final JPEGImageReader reader;
|
||||||
|
|
||||||
JPEGImage10MetadataCleaner(final JPEGImageReader reader) {
|
JPEGImage10MetadataCleaner(final JPEGImageReader reader) {
|
||||||
@@ -93,7 +88,7 @@ final class JPEGImage10MetadataCleaner {
|
|||||||
the version to the method/constructor used to obtain an IIOMetadata object.)
|
the version to the method/constructor used to obtain an IIOMetadata object.)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
IIOMetadataNode tree = (IIOMetadataNode) imageMetadata.getAsTree(JAVAX_IMAGEIO_JPEG_IMAGE_1_0);
|
IIOMetadataNode tree = (IIOMetadataNode) imageMetadata.getAsTree(JPEGImage10Metadata.JAVAX_IMAGEIO_JPEG_IMAGE_1_0);
|
||||||
IIOMetadataNode jpegVariety = (IIOMetadataNode) tree.getElementsByTagName("JPEGvariety").item(0);
|
IIOMetadataNode jpegVariety = (IIOMetadataNode) tree.getElementsByTagName("JPEGvariety").item(0);
|
||||||
IIOMetadataNode markerSequence = (IIOMetadataNode) tree.getElementsByTagName("markerSequence").item(0);
|
IIOMetadataNode markerSequence = (IIOMetadataNode) tree.getElementsByTagName("markerSequence").item(0);
|
||||||
|
|
||||||
@@ -145,7 +140,7 @@ final class JPEGImage10MetadataCleaner {
|
|||||||
jfifThumb = new IIOMetadataNode("JFIFthumbJPEG");
|
jfifThumb = new IIOMetadataNode("JFIFthumbJPEG");
|
||||||
// Contains it's own "markerSequence" with full DHT, DQT, SOF etc...
|
// Contains it's own "markerSequence" with full DHT, DQT, SOF etc...
|
||||||
IIOMetadata thumbMeta = thumbnailReader.readMetadata();
|
IIOMetadata thumbMeta = thumbnailReader.readMetadata();
|
||||||
Node thumbTree = thumbMeta.getAsTree(JAVAX_IMAGEIO_JPEG_IMAGE_1_0);
|
Node thumbTree = thumbMeta.getAsTree(JPEGImage10Metadata.JAVAX_IMAGEIO_JPEG_IMAGE_1_0);
|
||||||
jfifThumb.appendChild(thumbTree.getLastChild());
|
jfifThumb.appendChild(thumbTree.getLastChild());
|
||||||
app0JFXX.appendChild(jfifThumb);
|
app0JFXX.appendChild(jfifThumb);
|
||||||
break;
|
break;
|
||||||
@@ -307,11 +302,11 @@ final class JPEGImage10MetadataCleaner {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
imageMetadata.setFromTree(JAVAX_IMAGEIO_JPEG_IMAGE_1_0, tree);
|
imageMetadata.setFromTree(JPEGImage10Metadata.JAVAX_IMAGEIO_JPEG_IMAGE_1_0, tree);
|
||||||
}
|
}
|
||||||
catch (IIOInvalidTreeException e) {
|
catch (IIOInvalidTreeException e) {
|
||||||
if (JPEGImageReader.DEBUG) {
|
if (JPEGImageReader.DEBUG) {
|
||||||
new XMLSerializer(System.out, System.getProperty("file.encoding")).serialize(imageMetadata.getAsTree(JAVAX_IMAGEIO_JPEG_IMAGE_1_0), false);
|
new XMLSerializer(System.out, System.getProperty("file.encoding")).serialize(imageMetadata.getAsTree(JPEGImage10Metadata.JAVAX_IMAGEIO_JPEG_IMAGE_1_0), false);
|
||||||
System.out.println("-- 8< --");
|
System.out.println("-- 8< --");
|
||||||
new XMLSerializer(System.out, System.getProperty("file.encoding")).serialize(tree, false);
|
new XMLSerializer(System.out, System.getProperty("file.encoding")).serialize(tree, false);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,6 +30,37 @@
|
|||||||
|
|
||||||
package com.twelvemonkeys.imageio.plugins.jpeg;
|
package com.twelvemonkeys.imageio.plugins.jpeg;
|
||||||
|
|
||||||
|
import java.awt.*;
|
||||||
|
import java.awt.color.ColorSpace;
|
||||||
|
import java.awt.color.ICC_ColorSpace;
|
||||||
|
import java.awt.color.ICC_Profile;
|
||||||
|
import java.awt.image.*;
|
||||||
|
import java.io.DataInput;
|
||||||
|
import java.io.DataInputStream;
|
||||||
|
import java.io.EOFException;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.SequenceInputStream;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import javax.imageio.IIOException;
|
||||||
|
import javax.imageio.ImageIO;
|
||||||
|
import javax.imageio.ImageReadParam;
|
||||||
|
import javax.imageio.ImageReader;
|
||||||
|
import javax.imageio.ImageTypeSpecifier;
|
||||||
|
import javax.imageio.event.IIOReadUpdateListener;
|
||||||
|
import javax.imageio.event.IIOReadWarningListener;
|
||||||
|
import javax.imageio.metadata.IIOMetadata;
|
||||||
|
import javax.imageio.metadata.IIOMetadataFormatImpl;
|
||||||
|
import javax.imageio.metadata.IIOMetadataNode;
|
||||||
|
import javax.imageio.spi.ImageReaderSpi;
|
||||||
|
import javax.imageio.stream.ImageInputStream;
|
||||||
|
|
||||||
import com.twelvemonkeys.imageio.ImageReaderBase;
|
import com.twelvemonkeys.imageio.ImageReaderBase;
|
||||||
import com.twelvemonkeys.imageio.color.ColorSpaces;
|
import com.twelvemonkeys.imageio.color.ColorSpaces;
|
||||||
import com.twelvemonkeys.imageio.color.YCbCrConverter;
|
import com.twelvemonkeys.imageio.color.YCbCrConverter;
|
||||||
@@ -49,24 +80,6 @@ import com.twelvemonkeys.imageio.util.ProgressListenerBase;
|
|||||||
import com.twelvemonkeys.lang.Validate;
|
import com.twelvemonkeys.lang.Validate;
|
||||||
import com.twelvemonkeys.xml.XMLSerializer;
|
import com.twelvemonkeys.xml.XMLSerializer;
|
||||||
|
|
||||||
import javax.imageio.*;
|
|
||||||
import javax.imageio.event.IIOReadUpdateListener;
|
|
||||||
import javax.imageio.event.IIOReadWarningListener;
|
|
||||||
import javax.imageio.metadata.IIOMetadata;
|
|
||||||
import javax.imageio.metadata.IIOMetadataFormatImpl;
|
|
||||||
import javax.imageio.metadata.IIOMetadataNode;
|
|
||||||
import javax.imageio.spi.ImageReaderSpi;
|
|
||||||
import javax.imageio.stream.ImageInputStream;
|
|
||||||
import javax.imageio.stream.MemoryCacheImageInputStream;
|
|
||||||
import java.awt.*;
|
|
||||||
import java.awt.color.ColorSpace;
|
|
||||||
import java.awt.color.ICC_ColorSpace;
|
|
||||||
import java.awt.color.ICC_Profile;
|
|
||||||
import java.awt.image.*;
|
|
||||||
import java.io.*;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.*;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A JPEG {@code ImageReader} implementation based on the JRE {@code JPEGImageReader},
|
* A JPEG {@code ImageReader} implementation based on the JRE {@code JPEGImageReader},
|
||||||
* that adds support and properly handles cases where the JRE version throws exceptions.
|
* that adds support and properly handles cases where the JRE version throws exceptions.
|
||||||
@@ -113,9 +126,6 @@ public final class JPEGImageReader extends ImageReaderBase {
|
|||||||
/** Internal constant for referring all APP segments */
|
/** Internal constant for referring all APP segments */
|
||||||
static final int ALL_APP_MARKERS = -1;
|
static final int ALL_APP_MARKERS = -1;
|
||||||
|
|
||||||
/** Segment identifiers for the JPEG segments we care about reading. */
|
|
||||||
private static final Map<Integer, List<String>> SEGMENT_IDENTIFIERS = JPEGSegmentUtil.ALL_SEGMENTS;
|
|
||||||
|
|
||||||
/** Our JPEG reading delegate */
|
/** Our JPEG reading delegate */
|
||||||
private final ImageReader delegate;
|
private final ImageReader delegate;
|
||||||
|
|
||||||
@@ -126,8 +136,6 @@ public final class JPEGImageReader extends ImageReaderBase {
|
|||||||
private ImageReader thumbnailReader;
|
private ImageReader thumbnailReader;
|
||||||
private List<ThumbnailReader> thumbnails;
|
private List<ThumbnailReader> thumbnails;
|
||||||
|
|
||||||
private JPEGImage10MetadataCleaner metadataCleaner;
|
|
||||||
|
|
||||||
/** Cached list of JPEG segments we filter from the underlying stream */
|
/** Cached list of JPEG segments we filter from the underlying stream */
|
||||||
private List<Segment> segments;
|
private List<Segment> segments;
|
||||||
|
|
||||||
@@ -161,8 +169,6 @@ public final class JPEGImageReader extends ImageReaderBase {
|
|||||||
thumbnailReader.reset();
|
thumbnailReader.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
metadataCleaner = null;
|
|
||||||
|
|
||||||
installListeners();
|
installListeners();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -472,15 +478,12 @@ public final class JPEGImageReader extends ImageReaderBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// We'll need a read param
|
// We'll need a read param
|
||||||
Rectangle origSourceRegion;
|
|
||||||
if (param == null) {
|
if (param == null) {
|
||||||
param = delegate.getDefaultReadParam();
|
param = delegate.getDefaultReadParam();
|
||||||
origSourceRegion = null;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
origSourceRegion = param.getSourceRegion();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Rectangle origSourceRegion = param.getSourceRegion();
|
||||||
|
|
||||||
Rectangle srcRegion = new Rectangle();
|
Rectangle srcRegion = new Rectangle();
|
||||||
Rectangle dstRegion = new Rectangle();
|
Rectangle dstRegion = new Rectangle();
|
||||||
computeRegions(param, origWidth, origHeight, image, srcRegion, dstRegion);
|
computeRegions(param, origWidth, origHeight, image, srcRegion, dstRegion);
|
||||||
@@ -534,7 +537,7 @@ public final class JPEGImageReader extends ImageReaderBase {
|
|||||||
return image;
|
return image;
|
||||||
}
|
}
|
||||||
|
|
||||||
private JPEGColorSpace getSourceCSType(final JFIF jfif, final AdobeDCT adobeDCT, final Frame startOfFrame) throws IIOException {
|
static JPEGColorSpace getSourceCSType(final JFIF jfif, final AdobeDCT adobeDCT, final Frame startOfFrame) throws IIOException {
|
||||||
// Adapted from libjpeg jdapimin.c:
|
// Adapted from libjpeg jdapimin.c:
|
||||||
// Guess the input colorspace
|
// Guess the input colorspace
|
||||||
// (Wish JPEG committee had provided a real way to specify this...)
|
// (Wish JPEG committee had provided a real way to specify this...)
|
||||||
@@ -717,10 +720,11 @@ public final class JPEGImageReader extends ImageReaderBase {
|
|||||||
|
|
||||||
private void initHeader(final int imageIndex) throws IOException {
|
private void initHeader(final int imageIndex) throws IOException {
|
||||||
if (imageIndex < 0) {
|
if (imageIndex < 0) {
|
||||||
throw new IllegalArgumentException("imageIndex < 0: " + imageIndex);
|
throw new IndexOutOfBoundsException("imageIndex < 0: " + imageIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (imageIndex == currentStreamIndex) {
|
if (imageIndex == currentStreamIndex) {
|
||||||
|
initHeader();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -837,7 +841,7 @@ public final class JPEGImageReader extends ImageReaderBase {
|
|||||||
try {
|
try {
|
||||||
imageInput.seek(streamOffsets.get(currentStreamIndex));
|
imageInput.seek(streamOffsets.get(currentStreamIndex));
|
||||||
|
|
||||||
return JPEGSegmentUtil.readSegments(imageInput, SEGMENT_IDENTIFIERS);
|
return JPEGSegmentUtil.readSegments(imageInput, JPEGSegmentUtil.ALL_SEGMENTS);
|
||||||
}
|
}
|
||||||
catch (IIOException | IllegalArgumentException ignore) {
|
catch (IIOException | IllegalArgumentException ignore) {
|
||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
@@ -905,16 +909,16 @@ public final class JPEGImageReader extends ImageReaderBase {
|
|||||||
|
|
||||||
if (!exifSegments.isEmpty()) {
|
if (!exifSegments.isEmpty()) {
|
||||||
Application exif = exifSegments.get(0);
|
Application exif = exifSegments.get(0);
|
||||||
InputStream data = exif.data();
|
int offset = exif.identifier.length() + 2; // Incl. pad
|
||||||
|
|
||||||
if (data.read() == -1) { // Read pad
|
if (exif.data.length <= offset) {
|
||||||
processWarningOccurred("Exif chunk has no data.");
|
processWarningOccurred("Exif chunk has no data.");
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
ImageInputStream stream = new MemoryCacheImageInputStream(data);
|
// TODO: Consider returning ByteArrayImageInputStream from Segment.data()
|
||||||
return (CompoundDirectory) new TIFFReader().read(stream);
|
try (ImageInputStream stream = new ByteArrayImageInputStream(exif.data, offset, exif.data.length - offset)) {
|
||||||
|
return (CompoundDirectory) new TIFFReader().read(stream);
|
||||||
// TODO: Directory offset of thumbnail is wrong/relative to container stream, causing trouble for the TIFFReader...
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1125,13 +1129,13 @@ public final class JPEGImageReader extends ImageReaderBase {
|
|||||||
Application exif = exifSegments.get(0);
|
Application exif = exifSegments.get(0);
|
||||||
|
|
||||||
// Identifier is "Exif\0" + 1 byte pad
|
// Identifier is "Exif\0" + 1 byte pad
|
||||||
int offset = exif.identifier.length() + 2;
|
int dataOffset = exif.identifier.length() + 2;
|
||||||
|
|
||||||
if (exif.data.length <= offset) {
|
if (exif.data.length <= dataOffset) {
|
||||||
processWarningOccurred("Exif chunk has no data.");
|
processWarningOccurred("Exif chunk has no data.");
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
ImageInputStream stream = new ByteArrayImageInputStream(exif.data, offset, exif.data.length - offset);
|
ImageInputStream stream = new ByteArrayImageInputStream(exif.data, dataOffset, exif.data.length - dataOffset);
|
||||||
CompoundDirectory exifMetadata = (CompoundDirectory) new TIFFReader().read(stream);
|
CompoundDirectory exifMetadata = (CompoundDirectory) new TIFFReader().read(stream);
|
||||||
|
|
||||||
if (exifMetadata.directoryCount() == 2) {
|
if (exifMetadata.directoryCount() == 2) {
|
||||||
@@ -1142,14 +1146,18 @@ public final class JPEGImageReader extends ImageReaderBase {
|
|||||||
int compression = compressionEntry == null ? 6 : ((Number) compressionEntry.getValue()).intValue();
|
int compression = compressionEntry == null ? 6 : ((Number) compressionEntry.getValue()).intValue();
|
||||||
|
|
||||||
if (compression == 6) {
|
if (compression == 6) {
|
||||||
if (ifd1.getEntryById(TIFF.TAG_JPEG_INTERCHANGE_FORMAT) != null) {
|
Entry jpegOffEntry = ifd1.getEntryById(TIFF.TAG_JPEG_INTERCHANGE_FORMAT);
|
||||||
Entry jpegLength = ifd1.getEntryById(TIFF.TAG_JPEG_INTERCHANGE_FORMAT_LENGTH);
|
if (jpegOffEntry != null) {
|
||||||
|
Entry jpegLenEntry = ifd1.getEntryById(TIFF.TAG_JPEG_INTERCHANGE_FORMAT_LENGTH);
|
||||||
|
|
||||||
if ((jpegLength == null || ((Number) jpegLength.getValue()).longValue() > 0)) {
|
// Test if Exif thumbnail is contained within the Exif segment (offset + length <= segment.length)
|
||||||
|
long jpegOffset = ((Number) jpegOffEntry.getValue()).longValue();
|
||||||
|
long jpegLength = jpegLenEntry != null ? ((Number) jpegLenEntry.getValue()).longValue() : -1;
|
||||||
|
if (jpegLength > 0 && jpegOffset + jpegLength <= stream.length()) {
|
||||||
thumbnails.add(new EXIFThumbnailReader(thumbnailProgressDelegator, getThumbnailReader(), 0, thumbnails.size(), ifd1, stream));
|
thumbnails.add(new EXIFThumbnailReader(thumbnailProgressDelegator, getThumbnailReader(), 0, thumbnails.size(), ifd1, stream));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
processWarningOccurred("EXIF IFD with empty (zero-length) thumbnail");
|
processWarningOccurred("EXIF IFD with empty or incomplete JPEG thumbnail");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -1218,38 +1226,9 @@ public final class JPEGImageReader extends ImageReaderBase {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public IIOMetadata getImageMetadata(int imageIndex) throws IOException {
|
public IIOMetadata getImageMetadata(int imageIndex) throws IOException {
|
||||||
// checkBounds needed, as we catch the IndexOutOfBoundsException below.
|
|
||||||
checkBounds(imageIndex);
|
|
||||||
initHeader(imageIndex);
|
initHeader(imageIndex);
|
||||||
|
|
||||||
IIOMetadata imageMetadata;
|
return new JPEGImage10Metadata(segments, getSOF(), getJFIF(), getJFXX(), getEmbeddedICCProfile(true), getAdobeDCT(), getExif());
|
||||||
|
|
||||||
if (isLossless()) {
|
|
||||||
return new JPEGImage10Metadata(segments);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
try {
|
|
||||||
imageMetadata = delegate.getImageMetadata(0);
|
|
||||||
}
|
|
||||||
catch (IndexOutOfBoundsException knownIssue) {
|
|
||||||
// TMI-101: com.sun.imageio.plugins.jpeg.JPEGBuffer doesn't do proper sanity check of input data.
|
|
||||||
throw new IIOException("Corrupt JPEG data: Bad segment length", knownIssue);
|
|
||||||
}
|
|
||||||
catch (NegativeArraySizeException knownIssue) {
|
|
||||||
// Most likely from com.sun.imageio.plugins.jpeg.SOSMarkerSegment
|
|
||||||
throw new IIOException("Corrupt JPEG data: Bad component count", knownIssue);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (imageMetadata != null && Arrays.asList(imageMetadata.getMetadataFormatNames()).contains(JPEGImage10MetadataCleaner.JAVAX_IMAGEIO_JPEG_IMAGE_1_0)) {
|
|
||||||
if (metadataCleaner == null) {
|
|
||||||
metadataCleaner = new JPEGImage10MetadataCleaner(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
return metadataCleaner.cleanMetadata(imageMetadata);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return imageMetadata;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ import java.nio.charset.StandardCharsets;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
|
||||||
import static com.twelvemonkeys.imageio.plugins.jpeg.JPEGImage10MetadataCleaner.JAVAX_IMAGEIO_JPEG_IMAGE_1_0;
|
import static com.twelvemonkeys.imageio.plugins.jpeg.JPEGImage10Metadata.JAVAX_IMAGEIO_JPEG_IMAGE_1_0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* JPEGImageWriter
|
* JPEGImageWriter
|
||||||
@@ -159,6 +159,17 @@ public final class JPEGImageWriter extends ImageWriterBase {
|
|||||||
writeCMYK(streamMetadata, image, param);
|
writeCMYK(streamMetadata, image, param);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
// If the image metadata is our substitute, convert it back to native com.sun format
|
||||||
|
if (image.getMetadata() instanceof JPEGImage10Metadata) {
|
||||||
|
ImageTypeSpecifier type = image.hasRaster() ? null : ImageTypeSpecifier.createFromRenderedImage(image.getRenderedImage());
|
||||||
|
IIOMetadata nativeMetadata = delegate.getDefaultImageMetadata(type, param);
|
||||||
|
|
||||||
|
JPEGImage10Metadata metadata = (JPEGImage10Metadata) image.getMetadata();
|
||||||
|
nativeMetadata.setFromTree(metadata.getNativeMetadataFormatName(), metadata.getNativeTree());
|
||||||
|
|
||||||
|
image.setMetadata(nativeMetadata);
|
||||||
|
}
|
||||||
|
|
||||||
delegate.write(streamMetadata, image, param);
|
delegate.write(streamMetadata, image, param);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ import javax.imageio.IIOException;
|
|||||||
import javax.imageio.stream.ImageInputStream;
|
import javax.imageio.stream.ImageInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
final class JPEGLosslessDecoder {
|
final class JPEGLosslessDecoder {
|
||||||
@@ -51,12 +52,12 @@ final class JPEGLosslessDecoder {
|
|||||||
private final QuantizationTable quantTable;
|
private final QuantizationTable quantTable;
|
||||||
private Scan scan;
|
private Scan scan;
|
||||||
|
|
||||||
private final int HuffTab[][][] = new int[4][2][MAX_HUFFMAN_SUBTREE * 256];
|
private final int[][][] HuffTab = new int[4][2][MAX_HUFFMAN_SUBTREE * 256];
|
||||||
private final int IDCT_Source[] = new int[64];
|
private final int[] IDCT_Source = new int[64];
|
||||||
private final int nBlock[] = new int[10]; // number of blocks in the i-th Comp in a scan
|
private final int[] nBlock = new int[10]; // number of blocks in the i-th Comp in a scan
|
||||||
private final int[] acTab[] = new int[10][]; // ac HuffTab for the i-th Comp in a scan
|
private final int[][] acTab = new int[10][]; // ac HuffTab for the i-th Comp in a scan
|
||||||
private final int[] dcTab[] = new int[10][]; // dc HuffTab for the i-th Comp in a scan
|
private final int[][] dcTab = new int[10][]; // dc HuffTab for the i-th Comp in a scan
|
||||||
private final int[] qTab[] = new int[10][]; // quantization table for the i-th Comp in a scan
|
private final int[][] qTab = new int[10][]; // quantization table for the i-th Comp in a scan
|
||||||
|
|
||||||
private boolean restarting;
|
private boolean restarting;
|
||||||
private int marker;
|
private int marker;
|
||||||
@@ -70,7 +71,7 @@ final class JPEGLosslessDecoder {
|
|||||||
private int mask;
|
private int mask;
|
||||||
private int[][] outputData;
|
private int[][] outputData;
|
||||||
|
|
||||||
private static final int IDCT_P[] = {
|
private static final int[] IDCT_P = {
|
||||||
0, 5, 40, 16, 45, 2, 7, 42,
|
0, 5, 40, 16, 45, 2, 7, 42,
|
||||||
21, 56, 8, 61, 18, 47, 1, 4,
|
21, 56, 8, 61, 18, 47, 1, 4,
|
||||||
41, 23, 58, 13, 32, 24, 37, 10,
|
41, 23, 58, 13, 32, 24, 37, 10,
|
||||||
@@ -80,16 +81,6 @@ final class JPEGLosslessDecoder {
|
|||||||
50, 55, 25, 36, 11, 62, 14, 35,
|
50, 55, 25, 36, 11, 62, 14, 35,
|
||||||
28, 49, 52, 27, 38, 30, 51, 54
|
28, 49, 52, 27, 38, 30, 51, 54
|
||||||
};
|
};
|
||||||
private static final int TABLE[] = {
|
|
||||||
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
|
|
||||||
};
|
|
||||||
|
|
||||||
private static final int RESTART_MARKER_BEGIN = 0xFFD0;
|
private static final int RESTART_MARKER_BEGIN = 0xFFD0;
|
||||||
private static final int RESTART_MARKER_END = 0xFFD7;
|
private static final int RESTART_MARKER_END = 0xFFD7;
|
||||||
@@ -158,7 +149,7 @@ final class JPEGLosslessDecoder {
|
|||||||
huffTable.buildHuffTables(HuffTab);
|
huffTable.buildHuffTables(HuffTab);
|
||||||
}
|
}
|
||||||
|
|
||||||
quantTable.enhanceTables(TABLE);
|
quantTable.enhanceTables();
|
||||||
|
|
||||||
current = input.readUnsignedShort();
|
current = input.readUnsignedShort();
|
||||||
|
|
||||||
@@ -185,11 +176,10 @@ final class JPEGLosslessDecoder {
|
|||||||
selection = scan.spectralSelStart;
|
selection = scan.spectralSelStart;
|
||||||
|
|
||||||
final Scan.Component[] scanComps = scan.components;
|
final Scan.Component[] scanComps = scan.components;
|
||||||
final int[][] quantTables = quantTable.quantTables;
|
|
||||||
|
|
||||||
for (int i = 0; i < numComp; i++) {
|
for (int i = 0; i < numComp; i++) {
|
||||||
Frame.Component component = getComponentSpec(components, scanComps[i].scanCompSel);
|
Frame.Component component = getComponentSpec(components, scanComps[i].scanCompSel);
|
||||||
qTab[i] = quantTables[component.qtSel];
|
qTab[i] = quantTable.qTable(component.qtSel);
|
||||||
nBlock[i] = component.vSub * component.hSub;
|
nBlock[i] = component.vSub * component.hSub;
|
||||||
|
|
||||||
int dcTabSel = scanComps[i].dcTabSel;
|
int dcTabSel = scanComps[i].dcTabSel;
|
||||||
@@ -220,18 +210,18 @@ final class JPEGLosslessDecoder {
|
|||||||
outputData[componentIndex] = new int[xDim * yDim];
|
outputData[componentIndex] = new int[xDim * yDim];
|
||||||
}
|
}
|
||||||
|
|
||||||
final int firstValue[] = new int[numComp];
|
final int[] firstValue = new int[numComp];
|
||||||
for (int i = 0; i < numComp; i++) {
|
for (int i = 0; i < numComp; i++) {
|
||||||
firstValue[i] = (1 << (precision - 1));
|
firstValue[i] = (1 << (precision - 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
final int pred[] = new int[numComp];
|
final int[] pred = new int[numComp];
|
||||||
|
|
||||||
scanNum++;
|
scanNum++;
|
||||||
|
|
||||||
while (true) { // Decode one scan
|
while (true) { // Decode one scan
|
||||||
int temp[] = new int[1]; // to store remainder bits
|
int[] temp = new int[1]; // to store remainder bits
|
||||||
int index[] = new int[1];
|
int[] index = new int[1];
|
||||||
|
|
||||||
System.arraycopy(firstValue, 0, pred, 0, numComp);
|
System.arraycopy(firstValue, 0, pred, 0, numComp);
|
||||||
|
|
||||||
@@ -288,7 +278,7 @@ final class JPEGLosslessDecoder {
|
|||||||
private boolean useACForDC(final int dcTabSel) {
|
private boolean useACForDC(final int dcTabSel) {
|
||||||
if (isLossless()) {
|
if (isLossless()) {
|
||||||
for (HuffmanTable huffTable : huffTables) {
|
for (HuffmanTable huffTable : huffTables) {
|
||||||
if (huffTable.tc[dcTabSel][0] == 0 && huffTable.tc[dcTabSel][1] != 0) {
|
if (!huffTable.isPresent(dcTabSel, 0) && huffTable.isPresent(dcTabSel, 1)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -324,7 +314,7 @@ final class JPEGLosslessDecoder {
|
|||||||
return Scan.read(input, length);
|
return Scan.read(input, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
private int decode(final int prev[], final int temp[], final int index[]) throws IOException {
|
private int decode(final int[] prev, final int[] temp, final int[] index) throws IOException {
|
||||||
if (numComp == 1) {
|
if (numComp == 1) {
|
||||||
return decodeSingle(prev, temp, index);
|
return decodeSingle(prev, temp, index);
|
||||||
}
|
}
|
||||||
@@ -336,7 +326,7 @@ final class JPEGLosslessDecoder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private int decodeSingle(final int prev[], final int temp[], final int index[]) throws IOException {
|
private int decodeSingle(final int[] prev, final int[] temp, final int[] index) throws IOException {
|
||||||
// At the beginning of the first line and
|
// At the beginning of the first line and
|
||||||
// at the beginning of each restart interval the prediction value of 2P – 1 is used, where P is the input precision.
|
// at the beginning of each restart interval the prediction value of 2P – 1 is used, where P is the input precision.
|
||||||
if (restarting) {
|
if (restarting) {
|
||||||
@@ -390,7 +380,7 @@ final class JPEGLosslessDecoder {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
private int decodeRGB(final int prev[], final int temp[], final int index[]) throws IOException {
|
private int decodeRGB(final int[] prev, final int[] temp, final int[] index) throws IOException {
|
||||||
final int[] outputRedData = outputData[0];
|
final int[] outputRedData = outputData[0];
|
||||||
final int[] outputGreenData = outputData[1];
|
final int[] outputGreenData = outputData[1];
|
||||||
final int[] outputBlueData = outputData[2];
|
final int[] outputBlueData = outputData[2];
|
||||||
@@ -435,7 +425,7 @@ final class JPEGLosslessDecoder {
|
|||||||
return decode0(prev, temp, index);
|
return decode0(prev, temp, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
private int decodeAny(final int prev[], final int temp[], final int index[]) throws IOException {
|
private int decodeAny(final int[] prev, final int[] temp, final int[] index) throws IOException {
|
||||||
for (int componentIndex = 0; componentIndex < outputData.length; ++componentIndex) {
|
for (int componentIndex = 0; componentIndex < outputData.length; ++componentIndex) {
|
||||||
final int[] outputData = this.outputData[componentIndex];
|
final int[] outputData = this.outputData[componentIndex];
|
||||||
final int previous;
|
final int previous;
|
||||||
@@ -469,17 +459,17 @@ final class JPEGLosslessDecoder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private int decode0(int[] prev, int[] temp, int[] index) throws IOException {
|
private int decode0(int[] prev, int[] temp, int[] index) throws IOException {
|
||||||
int value, actab[], dctab[];
|
int value;
|
||||||
int qtab[];
|
int[] actab;
|
||||||
|
int[] dctab;
|
||||||
|
int[] qtab;
|
||||||
|
|
||||||
for (int ctrC = 0; ctrC < numComp; ctrC++) {
|
for (int ctrC = 0; ctrC < numComp; ctrC++) {
|
||||||
qtab = qTab[ctrC];
|
qtab = qTab[ctrC];
|
||||||
actab = acTab[ctrC];
|
actab = acTab[ctrC];
|
||||||
dctab = dcTab[ctrC];
|
dctab = dcTab[ctrC];
|
||||||
for (int i = 0; i < nBlock[ctrC]; i++) {
|
for (int i = 0; i < nBlock[ctrC]; i++) {
|
||||||
for (int k = 0; k < IDCT_Source.length; k++) {
|
Arrays.fill(IDCT_Source, 0);
|
||||||
IDCT_Source[k] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
value = getHuffmanValue(dctab, temp, index);
|
value = getHuffmanValue(dctab, temp, index);
|
||||||
|
|
||||||
@@ -545,7 +535,7 @@ final class JPEGLosslessDecoder {
|
|||||||
// and marker_index=9
|
// and marker_index=9
|
||||||
// If marker_index=9 then index is always > 8, or HuffmanValue()
|
// If marker_index=9 then index is always > 8, or HuffmanValue()
|
||||||
// will not be called
|
// will not be called
|
||||||
private int getHuffmanValue(final int table[], final int temp[], final int index[]) throws IOException {
|
private int getHuffmanValue(final int[] table, final int[] temp, final int[] index) throws IOException {
|
||||||
int code, input;
|
int code, input;
|
||||||
final int mask = 0xFFFF;
|
final int mask = 0xFFFF;
|
||||||
|
|
||||||
@@ -603,7 +593,7 @@ final class JPEGLosslessDecoder {
|
|||||||
return code & 0xFF;
|
return code & 0xFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
private int getn(final int[] pred, final int n, final int temp[], final int index[]) throws IOException {
|
private int getn(final int[] pred, final int n, final int[] temp, final int[] index) throws IOException {
|
||||||
int result;
|
int result;
|
||||||
final int one = 1;
|
final int one = 1;
|
||||||
final int n_one = -1;
|
final int n_one = -1;
|
||||||
@@ -688,7 +678,7 @@ final class JPEGLosslessDecoder {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private int getPreviousX(final int data[]) {
|
private int getPreviousX(final int[] data) {
|
||||||
if (xLoc > 0) {
|
if (xLoc > 0) {
|
||||||
return data[((yLoc * xDim) + xLoc) - 1];
|
return data[((yLoc * xDim) + xLoc) - 1];
|
||||||
}
|
}
|
||||||
@@ -700,7 +690,7 @@ final class JPEGLosslessDecoder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private int getPreviousXY(final int data[]) {
|
private int getPreviousXY(final int[] data) {
|
||||||
if ((xLoc > 0) && (yLoc > 0)) {
|
if ((xLoc > 0) && (yLoc > 0)) {
|
||||||
return data[(((yLoc - 1) * xDim) + xLoc) - 1];
|
return data[(((yLoc - 1) * xDim) + xLoc) - 1];
|
||||||
}
|
}
|
||||||
@@ -709,7 +699,7 @@ final class JPEGLosslessDecoder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private int getPreviousY(final int data[]) {
|
private int getPreviousY(final int[] data) {
|
||||||
if (yLoc > 0) {
|
if (yLoc > 0) {
|
||||||
return data[((yLoc - 1) * xDim) + xLoc];
|
return data[((yLoc - 1) * xDim) + xLoc];
|
||||||
}
|
}
|
||||||
@@ -722,7 +712,7 @@ final class JPEGLosslessDecoder {
|
|||||||
return (xLoc == (xDim - 1)) && (yLoc == (yDim - 1));
|
return (xLoc == (xDim - 1)) && (yLoc == (yDim - 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void output(final int pred[]) {
|
private void output(final int[] pred) {
|
||||||
if (numComp == 1) {
|
if (numComp == 1) {
|
||||||
outputSingle(pred);
|
outputSingle(pred);
|
||||||
}
|
}
|
||||||
@@ -734,7 +724,7 @@ final class JPEGLosslessDecoder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void outputSingle(final int pred[]) {
|
private void outputSingle(final int[] pred) {
|
||||||
if ((xLoc < xDim) && (yLoc < yDim)) {
|
if ((xLoc < xDim) && (yLoc < yDim)) {
|
||||||
outputData[0][(yLoc * xDim) + xLoc] = mask & pred[0];
|
outputData[0][(yLoc * xDim) + xLoc] = mask & pred[0];
|
||||||
xLoc++;
|
xLoc++;
|
||||||
@@ -746,7 +736,7 @@ final class JPEGLosslessDecoder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void outputRGB(final int pred[]) {
|
private void outputRGB(final int[] pred) {
|
||||||
if ((xLoc < xDim) && (yLoc < yDim)) {
|
if ((xLoc < xDim) && (yLoc < yDim)) {
|
||||||
final int index = (yLoc * xDim) + xLoc;
|
final int index = (yLoc * xDim) + xLoc;
|
||||||
outputData[0][index] = pred[0];
|
outputData[0][index] = pred[0];
|
||||||
@@ -761,7 +751,7 @@ final class JPEGLosslessDecoder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void outputAny(final int pred[]) {
|
private void outputAny(final int[] pred) {
|
||||||
if ((xLoc < xDim) && (yLoc < yDim)) {
|
if ((xLoc < xDim) && (yLoc < yDim)) {
|
||||||
final int index = (yLoc * xDim) + xLoc;
|
final int index = (yLoc * xDim) + xLoc;
|
||||||
for (int componentIndex = 0; componentIndex < outputData.length; ++componentIndex) {
|
for (int componentIndex = 0; componentIndex < outputData.length; ++componentIndex) {
|
||||||
|
|||||||
@@ -35,35 +35,42 @@ package com.twelvemonkeys.imageio.plugins.jpeg;
|
|||||||
import com.twelvemonkeys.imageio.metadata.jpeg.JPEG;
|
import com.twelvemonkeys.imageio.metadata.jpeg.JPEG;
|
||||||
|
|
||||||
import javax.imageio.IIOException;
|
import javax.imageio.IIOException;
|
||||||
|
import javax.imageio.plugins.jpeg.JPEGQTable;
|
||||||
import java.io.DataInput;
|
import java.io.DataInput;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
final class QuantizationTable extends Segment {
|
final class QuantizationTable extends Segment {
|
||||||
|
|
||||||
private final int precision[] = new int[4]; // Quantization precision 8 or 16
|
private static final int[] ZIGZAG = {
|
||||||
private final int[] tq = new int[4]; // 1: this table is presented
|
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
|
||||||
|
};
|
||||||
|
|
||||||
final int quantTables[][] = new int[4][64]; // Tables
|
private final int[] precision = new int[4]; // Quantization precision 8 or 16
|
||||||
|
private final boolean[] tq = new boolean[4]; // 1: this table is present
|
||||||
|
|
||||||
|
private final int[][] quantTables = new int[4][64]; // Tables
|
||||||
|
|
||||||
QuantizationTable() {
|
QuantizationTable() {
|
||||||
super(JPEG.DQT);
|
super(JPEG.DQT);
|
||||||
|
|
||||||
tq[0] = 0;
|
|
||||||
tq[1] = 0;
|
|
||||||
tq[2] = 0;
|
|
||||||
tq[3] = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Get rid of table param, make it a member?
|
// TODO: Consider creating a copy for the decoder here, as we need to keep the original values for the metadata
|
||||||
void enhanceTables(final int[] table) throws IOException {
|
void enhanceTables() {
|
||||||
for (int t = 0; t < 4; t++) {
|
for (int t = 0; t < 4; t++) {
|
||||||
if (tq[t] != 0) {
|
if (tq[t]) {
|
||||||
enhanceQuantizationTable(quantTables[t], table);
|
enhanceQuantizationTable(quantTables[t], ZIGZAG);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void enhanceQuantizationTable(final int qtab[], final int[] table) {
|
private void enhanceQuantizationTable(final int[] qtab, final int[] table) {
|
||||||
for (int i = 0; i < 8; i++) {
|
for (int i = 0; i < 8; i++) {
|
||||||
qtab[table[ i]] *= 90;
|
qtab[table[ i]] *= 90;
|
||||||
qtab[table[(4 * 8) + i]] *= 90;
|
qtab[table[(4 * 8) + i]] *= 90;
|
||||||
@@ -122,7 +129,7 @@ final class QuantizationTable extends Segment {
|
|||||||
throw new IIOException("Unexpected JPEG Quantization Table precision: " + table.precision[t]);
|
throw new IIOException("Unexpected JPEG Quantization Table precision: " + table.precision[t]);
|
||||||
}
|
}
|
||||||
|
|
||||||
table.tq[t] = 1;
|
table.tq[t] = true;
|
||||||
|
|
||||||
if (table.precision[t] == 8) {
|
if (table.precision[t] == 8) {
|
||||||
for (int i = 0; i < 64; i++) {
|
for (int i = 0; i < 64; i++) {
|
||||||
@@ -152,4 +159,28 @@ final class QuantizationTable extends Segment {
|
|||||||
|
|
||||||
return table;
|
return table;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isPresent(int tabelId) {
|
||||||
|
return tq[tabelId];
|
||||||
|
}
|
||||||
|
|
||||||
|
int precision(int tableId) {
|
||||||
|
return precision[tableId];
|
||||||
|
}
|
||||||
|
|
||||||
|
int[] qTable(int tabelId) {
|
||||||
|
return quantTables[tabelId];
|
||||||
|
}
|
||||||
|
|
||||||
|
JPEGQTable toNativeTable(int tableId) {
|
||||||
|
// TODO: Should de-zigzag (ie. "natural order") while reading
|
||||||
|
// TODO: ...and make sure the table isn't "enhanced"...
|
||||||
|
int[] qTable = new int[quantTables[tableId].length];
|
||||||
|
|
||||||
|
for (int i = 0; i < qTable.length; i++) {
|
||||||
|
qTable[i] = quantTables[tableId][ZIGZAG[i]];
|
||||||
|
}
|
||||||
|
|
||||||
|
return new JPEGQTable(qTable);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -85,12 +85,12 @@ public class JPEGImage10MetadataCleanerTest {
|
|||||||
reader.setInput(input);
|
reader.setInput(input);
|
||||||
|
|
||||||
IIOMetadata original = origReader.getImageMetadata(0);
|
IIOMetadata original = origReader.getImageMetadata(0);
|
||||||
IIOMetadataNode origTree = (IIOMetadataNode) original.getAsTree(JPEGImage10MetadataCleaner.JAVAX_IMAGEIO_JPEG_IMAGE_1_0);
|
IIOMetadataNode origTree = (IIOMetadataNode) original.getAsTree(JPEGImage10Metadata.JAVAX_IMAGEIO_JPEG_IMAGE_1_0);
|
||||||
|
|
||||||
JPEGImage10MetadataCleaner cleaner = new JPEGImage10MetadataCleaner((JPEGImageReader) reader);
|
JPEGImage10MetadataCleaner cleaner = new JPEGImage10MetadataCleaner((JPEGImageReader) reader);
|
||||||
IIOMetadata cleaned = cleaner.cleanMetadata(origReader.getImageMetadata(0));
|
IIOMetadata cleaned = cleaner.cleanMetadata(origReader.getImageMetadata(0));
|
||||||
|
|
||||||
IIOMetadataNode cleanTree = (IIOMetadataNode) cleaned.getAsTree(JPEGImage10MetadataCleaner.JAVAX_IMAGEIO_JPEG_IMAGE_1_0);
|
IIOMetadataNode cleanTree = (IIOMetadataNode) cleaned.getAsTree(JPEGImage10Metadata.JAVAX_IMAGEIO_JPEG_IMAGE_1_0);
|
||||||
|
|
||||||
NodeList origDHT = origTree.getElementsByTagName("dht");
|
NodeList origDHT = origTree.getElementsByTagName("dht");
|
||||||
assertEquals(1, origDHT.getLength());
|
assertEquals(1, origDHT.getLength());
|
||||||
|
|||||||
@@ -31,8 +31,9 @@
|
|||||||
package com.twelvemonkeys.imageio.plugins.jpeg;
|
package com.twelvemonkeys.imageio.plugins.jpeg;
|
||||||
|
|
||||||
import com.twelvemonkeys.imageio.util.ImageReaderAbstractTest;
|
import com.twelvemonkeys.imageio.util.ImageReaderAbstractTest;
|
||||||
|
import com.twelvemonkeys.lang.StringUtil;
|
||||||
|
|
||||||
import org.hamcrest.core.IsInstanceOf;
|
import org.hamcrest.core.IsInstanceOf;
|
||||||
import org.junit.Ignore;
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.mockito.internal.matchers.GreaterThan;
|
import org.mockito.internal.matchers.GreaterThan;
|
||||||
import org.w3c.dom.Element;
|
import org.w3c.dom.Element;
|
||||||
@@ -60,6 +61,7 @@ import java.util.List;
|
|||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
import static com.twelvemonkeys.imageio.util.IIOUtil.lookupProviderByName;
|
import static com.twelvemonkeys.imageio.util.IIOUtil.lookupProviderByName;
|
||||||
|
import static org.hamcrest.MatcherAssert.assertThat;
|
||||||
import static org.junit.Assert.*;
|
import static org.junit.Assert.*;
|
||||||
import static org.junit.Assume.assumeNoException;
|
import static org.junit.Assume.assumeNoException;
|
||||||
import static org.junit.Assume.assumeNotNull;
|
import static org.junit.Assume.assumeNotNull;
|
||||||
@@ -77,7 +79,10 @@ import static org.mockito.Mockito.*;
|
|||||||
*/
|
*/
|
||||||
public class JPEGImageReaderTest extends ImageReaderAbstractTest<JPEGImageReader> {
|
public class JPEGImageReaderTest extends ImageReaderAbstractTest<JPEGImageReader> {
|
||||||
|
|
||||||
private static final JPEGImageReaderSpi SPI = new JPEGImageReaderSpi(lookupDelegateProvider());
|
@Override
|
||||||
|
protected ImageReaderSpi createProvider() {
|
||||||
|
return new JPEGImageReaderSpi(lookupDelegateProvider());
|
||||||
|
}
|
||||||
|
|
||||||
private static ImageReaderSpi lookupDelegateProvider() {
|
private static ImageReaderSpi lookupDelegateProvider() {
|
||||||
return lookupProviderByName(IIORegistry.getDefaultInstance(), "com.sun.imageio.plugins.jpeg.JPEGImageReaderSpi", ImageReaderSpi.class);
|
return lookupProviderByName(IIORegistry.getDefaultInstance(), "com.sun.imageio.plugins.jpeg.JPEGImageReaderSpi", ImageReaderSpi.class);
|
||||||
@@ -133,26 +138,6 @@ public class JPEGImageReaderTest extends ImageReaderAbstractTest<JPEGImageReader
|
|||||||
// More test data in specific tests below
|
// More test data in specific tests below
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
protected ImageReaderSpi createProvider() {
|
|
||||||
return SPI;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected JPEGImageReader createReader() {
|
|
||||||
try {
|
|
||||||
return (JPEGImageReader) SPI.createReaderInstance();
|
|
||||||
}
|
|
||||||
catch (IOException e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Class<JPEGImageReader> getReaderClass() {
|
|
||||||
return JPEGImageReader.class;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean allowsNullRawImageType() {
|
protected boolean allowsNullRawImageType() {
|
||||||
return true;
|
return true;
|
||||||
@@ -182,26 +167,30 @@ public class JPEGImageReaderTest extends ImageReaderAbstractTest<JPEGImageReader
|
|||||||
public void testICCProfileCMYKClassOutputColors() throws IOException {
|
public void testICCProfileCMYKClassOutputColors() throws IOException {
|
||||||
// Make sure ICC profile with class output isn't converted to too bright values
|
// Make sure ICC profile with class output isn't converted to too bright values
|
||||||
JPEGImageReader reader = createReader();
|
JPEGImageReader reader = createReader();
|
||||||
reader.setInput(ImageIO.createImageInputStream(getClassLoaderResource("/jpeg/cmyk-sample-custom-icc-bright.jpg")));
|
|
||||||
|
|
||||||
ImageReadParam param = reader.getDefaultReadParam();
|
try (ImageInputStream stream = ImageIO.createImageInputStream(getClassLoaderResource("/jpeg/cmyk-sample-custom-icc-bright.jpg"))) {
|
||||||
param.setSourceRegion(new Rectangle(800, 800, 64, 8));
|
reader.setInput(stream);
|
||||||
param.setSourceSubsampling(8, 8, 2, 2);
|
|
||||||
|
|
||||||
BufferedImage image = reader.read(0, param);
|
ImageReadParam param = reader.getDefaultReadParam();
|
||||||
assertNotNull(image);
|
param.setSourceRegion(new Rectangle(800, 800, 64, 8));
|
||||||
|
param.setSourceSubsampling(8, 8, 2, 2);
|
||||||
|
|
||||||
byte[] data = ((DataBufferByte) image.getRaster().getDataBuffer()).getData();
|
BufferedImage image = reader.read(0, param);
|
||||||
byte[] expectedData = {34, 37, 34, 47, 47, 44, 22, 26, 28, 23, 26, 28, 20, 23, 26, 20, 22, 25, 22, 25, 27, 18, 21, 24};
|
assertNotNull(image);
|
||||||
|
|
||||||
assertEquals(expectedData.length, data.length);
|
byte[] data = ((DataBufferByte) image.getRaster().getDataBuffer()).getData();
|
||||||
|
byte[] expectedData = {34, 37, 34, 47, 47, 44, 22, 26, 28, 23, 26, 28, 20, 23, 26, 20, 22, 25, 22, 25, 27, 18, 21, 24};
|
||||||
|
|
||||||
assertJPEGPixelsEqual(expectedData, data, 0);
|
assertEquals(expectedData.length, data.length);
|
||||||
|
|
||||||
reader.dispose();
|
assertJPEGPixelsEqual(expectedData, data, 0);
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
reader.dispose();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void assertJPEGPixelsEqual(byte[] expected, byte[] actual, int actualOffset) {
|
private static void assertJPEGPixelsEqual(byte[] expected, byte[] actual, @SuppressWarnings("SameParameterValue") int actualOffset) {
|
||||||
for (int i = 0; i < expected.length; i++) {
|
for (int i = 0; i < expected.length; i++) {
|
||||||
assertEquals(String.format("Difference in pixel %d", i), expected[i], actual[i + actualOffset], 5);
|
assertEquals(String.format("Difference in pixel %d", i), expected[i], actual[i + actualOffset], 5);
|
||||||
}
|
}
|
||||||
@@ -211,38 +200,44 @@ public class JPEGImageReaderTest extends ImageReaderAbstractTest<JPEGImageReader
|
|||||||
public void testICCDuplicateSequence() throws IOException {
|
public void testICCDuplicateSequence() throws IOException {
|
||||||
// Variation of the above, file contains multiple ICC chunks, with all counts and sequence numbers == 1
|
// Variation of the above, file contains multiple ICC chunks, with all counts and sequence numbers == 1
|
||||||
JPEGImageReader reader = createReader();
|
JPEGImageReader reader = createReader();
|
||||||
reader.setInput(ImageIO.createImageInputStream(getClassLoaderResource("/jpeg/invalid-icc-duplicate-sequence-numbers-rgb-internal-kodak-srgb-jfif.jpg")));
|
try (ImageInputStream stream = ImageIO.createImageInputStream(getClassLoaderResource("/jpeg/invalid-icc-duplicate-sequence-numbers-rgb-internal-kodak-srgb-jfif.jpg"))) {
|
||||||
|
reader.setInput(stream);
|
||||||
|
|
||||||
assertEquals(345, reader.getWidth(0));
|
assertEquals(345, reader.getWidth(0));
|
||||||
assertEquals(540, reader.getHeight(0));
|
assertEquals(540, reader.getHeight(0));
|
||||||
|
|
||||||
BufferedImage image = reader.read(0);
|
BufferedImage image = reader.read(0);
|
||||||
|
|
||||||
assertNotNull(image);
|
assertNotNull(image);
|
||||||
assertEquals(345, image.getWidth());
|
assertEquals(345, image.getWidth());
|
||||||
assertEquals(540, image.getHeight());
|
assertEquals(540, image.getHeight());
|
||||||
|
}
|
||||||
reader.dispose();
|
finally {
|
||||||
|
reader.dispose();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testICCDuplicateSequenceZeroBased() throws IOException {
|
public void testICCDuplicateSequenceZeroBased() throws IOException {
|
||||||
// File contains multiple ICC chunks, with all counts and sequence numbers == 0
|
// File contains multiple ICC chunks, with all counts and sequence numbers == 0
|
||||||
JPEGImageReader reader = createReader();
|
JPEGImageReader reader = createReader();
|
||||||
reader.setInput(ImageIO.createImageInputStream(getClassLoaderResource("/jpeg/invalid-icc-duplicate-sequence-numbers-rgb-xerox-dc250-heavyweight-1-progressive-jfif.jpg")));
|
try (ImageInputStream stream = ImageIO.createImageInputStream(getClassLoaderResource("/jpeg/invalid-icc-duplicate-sequence-numbers-rgb-xerox-dc250-heavyweight-1-progressive-jfif.jpg"))) {
|
||||||
|
reader.setInput(stream);
|
||||||
|
|
||||||
assertEquals(3874, reader.getWidth(0));
|
assertEquals(3874, reader.getWidth(0));
|
||||||
assertEquals(5480, reader.getHeight(0));
|
assertEquals(5480, reader.getHeight(0));
|
||||||
|
|
||||||
ImageReadParam param = reader.getDefaultReadParam();
|
ImageReadParam param = reader.getDefaultReadParam();
|
||||||
param.setSourceRegion(new Rectangle(0, 0, 3874, 16)); // Save some memory
|
param.setSourceRegion(new Rectangle(0, 0, 3874, 16)); // Save some memory
|
||||||
BufferedImage image = reader.read(0, param);
|
BufferedImage image = reader.read(0, param);
|
||||||
|
|
||||||
assertNotNull(image);
|
assertNotNull(image);
|
||||||
assertEquals(3874, image.getWidth());
|
assertEquals(3874, image.getWidth());
|
||||||
assertEquals(16, image.getHeight());
|
assertEquals(16, image.getHeight());
|
||||||
|
}
|
||||||
reader.dispose();
|
finally {
|
||||||
|
reader.dispose();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -251,20 +246,23 @@ public class JPEGImageReaderTest extends ImageReaderAbstractTest<JPEGImageReader
|
|||||||
// Profile should have been about 550 000 bytes, split into multiple chunks. Written by GIMP 2.6.11
|
// Profile should have been about 550 000 bytes, split into multiple chunks. Written by GIMP 2.6.11
|
||||||
// See: https://bugzilla.redhat.com/show_bug.cgi?id=695246
|
// See: https://bugzilla.redhat.com/show_bug.cgi?id=695246
|
||||||
JPEGImageReader reader = createReader();
|
JPEGImageReader reader = createReader();
|
||||||
reader.setInput(ImageIO.createImageInputStream(getClassLoaderResource("/jpeg/cmm-exception-invalid-icc-profile-data.jpg")));
|
try (ImageInputStream stream = ImageIO.createImageInputStream(getClassLoaderResource("/jpeg/cmm-exception-invalid-icc-profile-data.jpg"))) {
|
||||||
|
reader.setInput(stream);
|
||||||
|
|
||||||
assertEquals(1993, reader.getWidth(0));
|
assertEquals(1993, reader.getWidth(0));
|
||||||
assertEquals(1038, reader.getHeight(0));
|
assertEquals(1038, reader.getHeight(0));
|
||||||
|
|
||||||
ImageReadParam param = reader.getDefaultReadParam();
|
ImageReadParam param = reader.getDefaultReadParam();
|
||||||
param.setSourceRegion(new Rectangle(reader.getWidth(0), 8));
|
param.setSourceRegion(new Rectangle(reader.getWidth(0), 8));
|
||||||
BufferedImage image = reader.read(0, param);
|
BufferedImage image = reader.read(0, param);
|
||||||
|
|
||||||
assertNotNull(image);
|
assertNotNull(image);
|
||||||
assertEquals(1993, image.getWidth());
|
assertEquals(1993, image.getWidth());
|
||||||
assertEquals(8, image.getHeight());
|
assertEquals(8, image.getHeight());
|
||||||
|
}
|
||||||
reader.dispose();
|
finally {
|
||||||
|
reader.dispose();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -272,19 +270,23 @@ public class JPEGImageReaderTest extends ImageReaderAbstractTest<JPEGImageReader
|
|||||||
// File contains CMYK ICC profile ("Coated FOGRA27 (ISO 12647-2:2004)"), but image data is 3 channel YCC/RGB
|
// File contains CMYK ICC profile ("Coated FOGRA27 (ISO 12647-2:2004)"), but image data is 3 channel YCC/RGB
|
||||||
// JFIF 1.1 with unknown origin.
|
// JFIF 1.1 with unknown origin.
|
||||||
JPEGImageReader reader = createReader();
|
JPEGImageReader reader = createReader();
|
||||||
reader.setInput(ImageIO.createImageInputStream(getClassLoaderResource("/jpeg/cco-illegalargument-rgb-coated-fogra27.jpg")));
|
try (ImageInputStream stream = ImageIO.createImageInputStream(getClassLoaderResource("/jpeg/cco-illegalargument-rgb-coated-fogra27.jpg"))) {
|
||||||
|
reader.setInput(stream);
|
||||||
|
|
||||||
assertEquals(281, reader.getWidth(0));
|
assertEquals(281, reader.getWidth(0));
|
||||||
assertEquals(449, reader.getHeight(0));
|
assertEquals(449, reader.getHeight(0));
|
||||||
|
|
||||||
BufferedImage image = reader.read(0);
|
BufferedImage image = reader.read(0);
|
||||||
|
|
||||||
assertNotNull(image);
|
assertNotNull(image);
|
||||||
assertEquals(281, image.getWidth());
|
assertEquals(281, image.getWidth());
|
||||||
assertEquals(449, image.getHeight());
|
assertEquals(449, image.getHeight());
|
||||||
|
|
||||||
// TODO: Need to test colors!
|
// TODO: Need to test colors!
|
||||||
reader.dispose();
|
}
|
||||||
|
finally {
|
||||||
|
reader.dispose();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -293,22 +295,27 @@ public class JPEGImageReaderTest extends ImageReaderAbstractTest<JPEGImageReader
|
|||||||
// but image data is plain 3 channel YCC/RGB.
|
// but image data is plain 3 channel YCC/RGB.
|
||||||
// EXIF/TIFF metadata says Software: "Microsoft Windows Photo Gallery 6.0.6001.18000"...
|
// EXIF/TIFF metadata says Software: "Microsoft Windows Photo Gallery 6.0.6001.18000"...
|
||||||
JPEGImageReader reader = createReader();
|
JPEGImageReader reader = createReader();
|
||||||
reader.setInput(ImageIO.createImageInputStream(getClassLoaderResource("/jpeg/no-image-types-rgb-us-web-coated-v2-ms-photogallery-exif.jpg")));
|
try (ImageInputStream stream = ImageIO.createImageInputStream(getClassLoaderResource("/jpeg/no-image-types-rgb-us-web-coated-v2-ms-photogallery-exif.jpg"))) {
|
||||||
|
reader.setInput(stream);
|
||||||
|
|
||||||
assertEquals(1743, reader.getWidth(0));
|
assertEquals(1743, reader.getWidth(0));
|
||||||
assertEquals(2551, reader.getHeight(0));
|
assertEquals(2551, reader.getHeight(0));
|
||||||
|
|
||||||
ImageReadParam param = reader.getDefaultReadParam();
|
ImageReadParam param = reader.getDefaultReadParam();
|
||||||
param.setSourceRegion(new Rectangle(0, 0, 1743, 16)); // Save some memory
|
param.setSourceRegion(new Rectangle(0, 0, 1743, 16)); // Save some memory
|
||||||
BufferedImage image = reader.read(0, param);
|
BufferedImage image = reader.read(0, param);
|
||||||
|
|
||||||
assertNotNull(image);
|
assertNotNull(image);
|
||||||
assertEquals(1743, image.getWidth());
|
assertEquals(1743, image.getWidth());
|
||||||
assertEquals(16, image.getHeight());
|
assertEquals(16, image.getHeight());
|
||||||
|
|
||||||
// TODO: Need to test colors!
|
// TODO: Need to test colors!
|
||||||
|
|
||||||
assertTrue(reader.hasThumbnails(0)); // Should not blow up!
|
assertTrue(reader.hasThumbnails(0)); // Should not blow up!
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
reader.dispose();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -316,107 +323,131 @@ public class JPEGImageReaderTest extends ImageReaderAbstractTest<JPEGImageReader
|
|||||||
// File contains JFIF (!), RGB ICC profile AND Adobe App14 specifying unknown conversion,
|
// File contains JFIF (!), RGB ICC profile AND Adobe App14 specifying unknown conversion,
|
||||||
// but image data is 4 channel CMYK (from SOF0 channel Ids 'C', 'M', 'Y', 'K').
|
// but image data is 4 channel CMYK (from SOF0 channel Ids 'C', 'M', 'Y', 'K').
|
||||||
JPEGImageReader reader = createReader();
|
JPEGImageReader reader = createReader();
|
||||||
reader.setInput(ImageIO.createImageInputStream(getClassLoaderResource("/jpeg/jfif-cmyk-invalid-icc-profile-srgb.jpg")));
|
try (ImageInputStream stream = ImageIO.createImageInputStream(getClassLoaderResource("/jpeg/jfif-cmyk-invalid-icc-profile-srgb.jpg"))) {
|
||||||
|
reader.setInput(stream);
|
||||||
|
|
||||||
assertEquals(493, reader.getWidth(0));
|
assertEquals(493, reader.getWidth(0));
|
||||||
assertEquals(500, reader.getHeight(0));
|
assertEquals(500, reader.getHeight(0));
|
||||||
|
|
||||||
ImageReadParam param = reader.getDefaultReadParam();
|
ImageReadParam param = reader.getDefaultReadParam();
|
||||||
param.setSourceRegion(new Rectangle(0, 0, 493, 16)); // Save some memory
|
param.setSourceRegion(new Rectangle(0, 0, 493, 16)); // Save some memory
|
||||||
BufferedImage image = reader.read(0, param);
|
BufferedImage image = reader.read(0, param);
|
||||||
|
|
||||||
assertNotNull(image);
|
assertNotNull(image);
|
||||||
assertEquals(493, image.getWidth());
|
assertEquals(493, image.getWidth());
|
||||||
assertEquals(16, image.getHeight());
|
assertEquals(16, image.getHeight());
|
||||||
|
|
||||||
// TODO: Need to test colors!
|
// TODO: Need to test colors!
|
||||||
|
|
||||||
assertFalse(reader.hasThumbnails(0)); // Should not blow up!
|
assertFalse(reader.hasThumbnails(0)); // Should not blow up!
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
reader.dispose();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testWarningEmbeddedColorProfileInvalidIgnored() throws IOException {
|
public void testWarningEmbeddedColorProfileInvalidIgnored() throws IOException {
|
||||||
JPEGImageReader reader = createReader();
|
JPEGImageReader reader = createReader();
|
||||||
reader.setInput(ImageIO.createImageInputStream(getClassLoaderResource("/jpeg/warning-embedded-color-profile-invalid-ignored-cmyk.jpg")));
|
try (ImageInputStream stream = ImageIO.createImageInputStream(getClassLoaderResource("/jpeg/warning-embedded-color-profile-invalid-ignored-cmyk.jpg"))) {
|
||||||
|
reader.setInput(stream);
|
||||||
|
|
||||||
assertEquals(183, reader.getWidth(0));
|
assertEquals(183, reader.getWidth(0));
|
||||||
assertEquals(283, reader.getHeight(0));
|
assertEquals(283, reader.getHeight(0));
|
||||||
|
|
||||||
BufferedImage image = reader.read(0);
|
BufferedImage image = reader.read(0);
|
||||||
|
|
||||||
assertNotNull(image);
|
assertNotNull(image);
|
||||||
assertEquals(183, image.getWidth());
|
assertEquals(183, image.getWidth());
|
||||||
assertEquals(283, image.getHeight());
|
assertEquals(283, image.getHeight());
|
||||||
|
|
||||||
// TODO: Need to test colors!
|
// TODO: Need to test colors!
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
reader.dispose();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testEOFSOSSegment() throws IOException {
|
public void testEOFSOSSegment() throws IOException {
|
||||||
// Regression...
|
// Regression...
|
||||||
JPEGImageReader reader = createReader();
|
JPEGImageReader reader = createReader();
|
||||||
reader.setInput(ImageIO.createImageInputStream(getClassLoaderResource("/jpeg/eof-sos-segment-bug.jpg")));
|
try (ImageInputStream stream = ImageIO.createImageInputStream(getClassLoaderResource("/jpeg/eof-sos-segment-bug.jpg"))) {
|
||||||
|
reader.setInput(stream);
|
||||||
|
|
||||||
assertEquals(266, reader.getWidth(0));
|
assertEquals(266, reader.getWidth(0));
|
||||||
assertEquals(400, reader.getHeight(0));
|
assertEquals(400, reader.getHeight(0));
|
||||||
|
|
||||||
BufferedImage image = reader.read(0);
|
BufferedImage image = reader.read(0);
|
||||||
|
|
||||||
assertNotNull(image);
|
assertNotNull(image);
|
||||||
assertEquals(266, image.getWidth());
|
assertEquals(266, image.getWidth());
|
||||||
assertEquals(400, image.getHeight());
|
assertEquals(400, image.getHeight());
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
reader.dispose();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testInvalidICCSingleChunkBadSequence() throws IOException {
|
public void testInvalidICCSingleChunkBadSequence() throws IOException {
|
||||||
// Regression
|
// Regression
|
||||||
// Single segment ICC profile, with chunk index/count == 0
|
// Single segment ICC profile, with chunk index/count == 0
|
||||||
|
|
||||||
JPEGImageReader reader = createReader();
|
JPEGImageReader reader = createReader();
|
||||||
reader.setInput(ImageIO.createImageInputStream(getClassLoaderResource("/jpeg/invalid-icc-single-chunk-bad-sequence-number.jpg")));
|
try (ImageInputStream stream = ImageIO.createImageInputStream(getClassLoaderResource("/jpeg/invalid-icc-single-chunk-bad-sequence-number.jpg"))) {
|
||||||
|
reader.setInput(stream);
|
||||||
|
|
||||||
assertEquals(1772, reader.getWidth(0));
|
assertEquals(1772, reader.getWidth(0));
|
||||||
assertEquals(2126, reader.getHeight(0));
|
assertEquals(2126, reader.getHeight(0));
|
||||||
|
|
||||||
ImageReadParam param = reader.getDefaultReadParam();
|
ImageReadParam param = reader.getDefaultReadParam();
|
||||||
param.setSourceRegion(new Rectangle(reader.getWidth(0), 8));
|
param.setSourceRegion(new Rectangle(reader.getWidth(0), 8));
|
||||||
|
|
||||||
IIOReadWarningListener warningListener = mock(IIOReadWarningListener.class);
|
IIOReadWarningListener warningListener = mock(IIOReadWarningListener.class);
|
||||||
reader.addIIOReadWarningListener(warningListener);
|
reader.addIIOReadWarningListener(warningListener);
|
||||||
|
|
||||||
BufferedImage image = reader.read(0, param);
|
BufferedImage image = reader.read(0, param);
|
||||||
|
|
||||||
assertNotNull(image);
|
assertNotNull(image);
|
||||||
assertEquals(1772, image.getWidth());
|
assertEquals(1772, image.getWidth());
|
||||||
assertEquals(8, image.getHeight());
|
assertEquals(8, image.getHeight());
|
||||||
|
|
||||||
verify(warningListener, atLeast(1)).warningOccurred(eq(reader), anyString());
|
verify(warningListener, atLeast(1)).warningOccurred(eq(reader), anyString());
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
reader.dispose();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testYCbCrNotSubsampledNonstandardChannelIndexes() throws IOException {
|
public void testYCbCrNotSubsampledNonstandardChannelIndexes() throws IOException {
|
||||||
// Regression: Make sure 3 channel, non-subsampled JFIF, defaults to YCbCr, even if unstandard channel indexes
|
// Regression: Make sure 3 channel, non-subsampled JFIF, defaults to YCbCr, even if unstandard channel indexes
|
||||||
JPEGImageReader reader = createReader();
|
JPEGImageReader reader = createReader();
|
||||||
reader.setInput(ImageIO.createImageInputStream(getClassLoaderResource("/jpeg/jfif-ycbcr-no-subsampling-intel.jpg")));
|
try (ImageInputStream stream = ImageIO.createImageInputStream(getClassLoaderResource("/jpeg/jfif-ycbcr-no-subsampling-intel.jpg"))) {
|
||||||
|
reader.setInput(stream);
|
||||||
|
|
||||||
assertEquals(600, reader.getWidth(0));
|
assertEquals(600, reader.getWidth(0));
|
||||||
assertEquals(600, reader.getHeight(0));
|
assertEquals(600, reader.getHeight(0));
|
||||||
|
|
||||||
ImageReadParam param = reader.getDefaultReadParam();
|
ImageReadParam param = reader.getDefaultReadParam();
|
||||||
param.setSourceRegion(new Rectangle(8, 8));
|
param.setSourceRegion(new Rectangle(8, 8));
|
||||||
|
|
||||||
BufferedImage image = reader.read(0, param);
|
BufferedImage image = reader.read(0, param);
|
||||||
|
|
||||||
assertNotNull(image);
|
assertNotNull(image);
|
||||||
assertEquals(8, image.getWidth());
|
assertEquals(8, image.getWidth());
|
||||||
assertEquals(8, image.getHeight());
|
assertEquals(8, image.getHeight());
|
||||||
|
|
||||||
// QnD test: Make sure all pixels are white (if treated as RGB, they will be pink-ish)
|
// QnD test: Make sure all pixels are white (if treated as RGB, they will be pink-ish)
|
||||||
for (int y = 0; y < image.getHeight(); y++) {
|
for (int y = 0; y < image.getHeight(); y++) {
|
||||||
for (int x = 0; x < image.getWidth(); x++) {
|
for (int x = 0; x < image.getWidth(); x++) {
|
||||||
assertEquals(0xffffff, image.getRGB(x, y) & 0xffffff);
|
assertEquals(0xffffff, image.getRGB(x, y) & 0xffffff);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
finally {
|
||||||
|
reader.dispose();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -424,32 +455,83 @@ public class JPEGImageReaderTest extends ImageReaderAbstractTest<JPEGImageReader
|
|||||||
// Special case, throws exception below without special treatment
|
// Special case, throws exception below without special treatment
|
||||||
// java.awt.color.CMMException: General CMM error517
|
// java.awt.color.CMMException: General CMM error517
|
||||||
JPEGImageReader reader = createReader();
|
JPEGImageReader reader = createReader();
|
||||||
reader.setInput(ImageIO.createImageInputStream(getClassLoaderResource("/jpeg/cmm-exception-corbis-rgb.jpg")));
|
try (ImageInputStream stream = ImageIO.createImageInputStream(getClassLoaderResource("/jpeg/cmm-exception-corbis-rgb.jpg"))) {
|
||||||
|
reader.setInput(stream);
|
||||||
|
|
||||||
assertEquals(512, reader.getWidth(0));
|
assertEquals(512, reader.getWidth(0));
|
||||||
assertEquals(384, reader.getHeight(0));
|
assertEquals(384, reader.getHeight(0));
|
||||||
|
|
||||||
BufferedImage image = reader.read(0);
|
BufferedImage image = reader.read(0);
|
||||||
|
|
||||||
assertNotNull(image);
|
assertNotNull(image);
|
||||||
assertEquals(512, image.getWidth());
|
assertEquals(512, image.getWidth());
|
||||||
assertEquals(384, image.getHeight());
|
assertEquals(384, image.getHeight());
|
||||||
|
}
|
||||||
reader.dispose();
|
finally {
|
||||||
|
reader.dispose();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Ignore("Known issue in com.sun...JPEGMetadata")
|
|
||||||
@Test
|
@Test
|
||||||
public void testStandardMetadataColorSpaceTypeRGBForYCbCr() {
|
public void testStandardMetadataColorSpaceTypeRGBForYCbCr() throws IOException {
|
||||||
// These reports RGB in standard metadata, while the data is really YCbCr.
|
List<TestData> ycbcr = Arrays.asList(
|
||||||
// Exif files are always YCbCr AFAIK.
|
// This reports RGB in standard metadata, while the data is really YCbCr.
|
||||||
fail("/jpeg/exif-jpeg-thumbnail-sony-dsc-p150-inverted-colors.jpg");
|
// Exif files are always YCbCr AFAIK.
|
||||||
fail("/jpeg/exif-pspro-13-inverted-colors.jpg");
|
new TestData(getClassLoaderResource("/jpeg/exif-jpeg-thumbnail-sony-dsc-p150-inverted-colors.jpg"), new Dimension(2437, 1662)),
|
||||||
// Not Exif, but same issue: SOF comp ids are JFIF standard 1-3 and
|
// Not Exif, but same issue: SOF comp ids are JFIF standard 1-3 and
|
||||||
// *should* be interpreted as YCbCr but isn't.
|
// *should* be interpreted as YCbCr but isn't.
|
||||||
// Possible fix for this, is to insert a fake JFIF segment, as this image
|
// Possible fix for this, is to insert a fake JFIF segment, as this image
|
||||||
// conforms to the JFIF spec (but it won't work for the Exif samples)
|
// conforms to the JFIF spec (but it won't work for the Exif samples)
|
||||||
fail("/jpeg/no-jfif-ycbcr.jpg");
|
new TestData(getClassLoaderResource("/jpeg/no-jfif-ycbcr.jpg"), new Dimension(310, 206))
|
||||||
|
);
|
||||||
|
|
||||||
|
JPEGImageReader reader = createReader();
|
||||||
|
|
||||||
|
try {
|
||||||
|
for (TestData broken : ycbcr) {
|
||||||
|
reader.setInput(broken.getInputStream());
|
||||||
|
|
||||||
|
IIOMetadata metadata = reader.getImageMetadata(0);
|
||||||
|
|
||||||
|
IIOMetadataNode root = (IIOMetadataNode) metadata.getAsTree(IIOMetadataFormatImpl.standardMetadataFormatName);
|
||||||
|
NodeList colorSpaceTypes = root.getElementsByTagName("ColorSpaceType");
|
||||||
|
assertEquals(1, colorSpaceTypes.getLength());
|
||||||
|
IIOMetadataNode csType = (IIOMetadataNode) colorSpaceTypes.item(0);
|
||||||
|
assertEquals("YCbCr", csType.getAttribute("name"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
reader.dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetExifOrientationFromMetadata() throws IOException {
|
||||||
|
JPEGImageReader reader = createReader();
|
||||||
|
|
||||||
|
// TODO: Find better sample data. Should have an uppercase F ;-)
|
||||||
|
// Test all 9 mutations + missing Exif
|
||||||
|
List<String> expectedOrientations = Arrays.asList("Normal", "Normal", "FlipH", "Rotate180", "FlipV", "FlipVRotate90", "Rotate270", "FlipHRotate90", "Rotate90");
|
||||||
|
try {
|
||||||
|
for (int i = 0; i < 9; i++) {
|
||||||
|
try (ImageInputStream stream = ImageIO.createImageInputStream(getClassLoaderResource(String.format("/exif/Landscape_%d.jpg", i)))) {
|
||||||
|
reader.setInput(stream);
|
||||||
|
|
||||||
|
IIOMetadata metadata = reader.getImageMetadata(0);
|
||||||
|
IIOMetadataNode root = (IIOMetadataNode) metadata.getAsTree(IIOMetadataFormatImpl.standardMetadataFormatName);
|
||||||
|
|
||||||
|
NodeList orientationNodes = root.getElementsByTagName("ImageOrientation");
|
||||||
|
assertEquals(1, orientationNodes.getLength());
|
||||||
|
|
||||||
|
IIOMetadataNode orientationNode = (IIOMetadataNode) orientationNodes.item(0);
|
||||||
|
String orientationValue = orientationNode.getAttribute("value");
|
||||||
|
assertEquals(expectedOrientations.get(i), orientationValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
reader.dispose();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -488,7 +570,6 @@ public class JPEGImageReaderTest extends ImageReaderAbstractTest<JPEGImageReader
|
|||||||
public void testSPIRecognizesBrokenJPEG() throws IOException {
|
public void testSPIRecognizesBrokenJPEG() throws IOException {
|
||||||
// TODO: There's a bug in com.sun.imageio.plugins.png.PNGImageReaderSpi.canDecode
|
// TODO: There's a bug in com.sun.imageio.plugins.png.PNGImageReaderSpi.canDecode
|
||||||
// causing files < 8 bytes to not be recognized as anything...
|
// causing files < 8 bytes to not be recognized as anything...
|
||||||
ImageReaderSpi provider = createProvider();
|
|
||||||
for (TestData data : getBrokenTestData()) {
|
for (TestData data : getBrokenTestData()) {
|
||||||
assertTrue(data.toString(), provider.canDecodeInput(data.getInputStream()));
|
assertTrue(data.toString(), provider.canDecodeInput(data.getInputStream()));
|
||||||
}
|
}
|
||||||
@@ -1284,6 +1365,9 @@ public class JPEGImageReaderTest extends ImageReaderAbstractTest<JPEGImageReader
|
|||||||
|
|
||||||
// Assume that the aspect ratio is 1 if both x/y density is 0.
|
// Assume that the aspect ratio is 1 if both x/y density is 0.
|
||||||
IIOMetadataNode tree = (IIOMetadataNode) imageMetadata.getAsTree(IIOMetadataFormatImpl.standardMetadataFormatName);
|
IIOMetadataNode tree = (IIOMetadataNode) imageMetadata.getAsTree(IIOMetadataFormatImpl.standardMetadataFormatName);
|
||||||
|
|
||||||
|
// new XMLSerializer(System.out, System.getProperty("file.encoding")).serialize(imageMetadata.getAsTree(imageMetadata.getNativeMetadataFormatName()), false);
|
||||||
|
// new XMLSerializer(System.out, System.getProperty("file.encoding")).serialize(tree, false);
|
||||||
NodeList dimensions = tree.getElementsByTagName("Dimension");
|
NodeList dimensions = tree.getElementsByTagName("Dimension");
|
||||||
assertEquals(1, dimensions.getLength());
|
assertEquals(1, dimensions.getLength());
|
||||||
assertEquals("PixelAspectRatio", dimensions.item(0).getFirstChild().getNodeName());
|
assertEquals("PixelAspectRatio", dimensions.item(0).getFirstChild().getNodeName());
|
||||||
@@ -1321,7 +1405,7 @@ public class JPEGImageReaderTest extends ImageReaderAbstractTest<JPEGImageReader
|
|||||||
|
|
||||||
NodeList markerSequences = iioTree.getElementsByTagName("markerSequence");
|
NodeList markerSequences = iioTree.getElementsByTagName("markerSequence");
|
||||||
assertTrue(markerSequences.getLength() == 1 || markerSequences.getLength() == 2); // In case of JPEG encoded thumbnail, there will be 2
|
assertTrue(markerSequences.getLength() == 1 || markerSequences.getLength() == 2); // In case of JPEG encoded thumbnail, there will be 2
|
||||||
IIOMetadataNode markerSequence = (IIOMetadataNode) markerSequences.item(0);
|
IIOMetadataNode markerSequence = (IIOMetadataNode) markerSequences.item(markerSequences.getLength() - 1); // The last will be the "main" image
|
||||||
assertNotNull(markerSequence);
|
assertNotNull(markerSequence);
|
||||||
assertThat(markerSequence.getChildNodes().getLength(), new GreaterThan<>(0));
|
assertThat(markerSequence.getChildNodes().getLength(), new GreaterThan<>(0));
|
||||||
|
|
||||||
@@ -1379,6 +1463,7 @@ public class JPEGImageReaderTest extends ImageReaderAbstractTest<JPEGImageReader
|
|||||||
|
|
||||||
for (TestData testData : getTestData()) {
|
for (TestData testData : getTestData()) {
|
||||||
reader.setInput(testData.getInputStream());
|
reader.setInput(testData.getInputStream());
|
||||||
|
assert referenceReader != null;
|
||||||
referenceReader.setInput(testData.getInputStream());
|
referenceReader.setInput(testData.getInputStream());
|
||||||
|
|
||||||
for (int i = 0; i < reader.getNumImages(true); i++) {
|
for (int i = 0; i < reader.getNumImages(true); i++) {
|
||||||
@@ -1393,6 +1478,8 @@ public class JPEGImageReaderTest extends ImageReaderAbstractTest<JPEGImageReader
|
|||||||
Node referenceTree = reference.getAsTree(formatName);
|
Node referenceTree = reference.getAsTree(formatName);
|
||||||
Node actualTree = metadata.getAsTree(formatName);
|
Node actualTree = metadata.getAsTree(formatName);
|
||||||
|
|
||||||
|
// new XMLSerializer(System.out, System.getProperty("file.encoding")).serialize(referenceTree, false);
|
||||||
|
// System.out.println("--------");
|
||||||
// new XMLSerializer(System.out, System.getProperty("file.encoding")).serialize(actualTree, false);
|
// new XMLSerializer(System.out, System.getProperty("file.encoding")).serialize(actualTree, false);
|
||||||
assertTreesEquals(String.format("Metadata differs for %s image %s ", testData, i), referenceTree, actualTree);
|
assertTreesEquals(String.format("Metadata differs for %s image %s ", testData, i), referenceTree, actualTree);
|
||||||
}
|
}
|
||||||
@@ -1401,9 +1488,9 @@ public class JPEGImageReaderTest extends ImageReaderAbstractTest<JPEGImageReader
|
|||||||
throw new AssertionError(String.format("Reading metadata failed for %s image %s: %s", testData, i, e.getMessage()), e);
|
throw new AssertionError(String.format("Reading metadata failed for %s image %s: %s", testData, i, e.getMessage()), e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (IIOException ignore) {
|
catch (IIOException warn) {
|
||||||
// The reference reader will fail on certain images, we'll just ignore that
|
// The reference reader will fail on certain images, we'll just ignore that
|
||||||
System.err.println(String.format("WARNING: Reading reference metadata failed for %s image %s: %s", testData, i, ignore.getMessage()));
|
System.err.printf("WARNING: Reading reference metadata failed for %s image %s: %s%n", testData, i, warn.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1432,8 +1519,7 @@ public class JPEGImageReaderTest extends ImageReaderAbstractTest<JPEGImageReader
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (expectedTree == null) {
|
if (expectedTree == null) {
|
||||||
assertNull(actualTree);
|
fail("Expected tree is null, actual tree is non-null");
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
assertEquals(String.format("%s: Node names differ", message), expectedTree.getNodeName(), actualTree.getNodeName());
|
assertEquals(String.format("%s: Node names differ", message), expectedTree.getNodeName(), actualTree.getNodeName());
|
||||||
@@ -1443,7 +1529,14 @@ public class JPEGImageReaderTest extends ImageReaderAbstractTest<JPEGImageReader
|
|||||||
assertEquals(String.format("%s: Number of attributes for <%s> differ", message, expectedTree.getNodeName()), expectedAttributes.getLength(), actualAttributes.getLength());
|
assertEquals(String.format("%s: Number of attributes for <%s> differ", message, expectedTree.getNodeName()), expectedAttributes.getLength(), actualAttributes.getLength());
|
||||||
for (int i = 0; i < expectedAttributes.getLength(); i++) {
|
for (int i = 0; i < expectedAttributes.getLength(); i++) {
|
||||||
Node item = expectedAttributes.item(i);
|
Node item = expectedAttributes.item(i);
|
||||||
assertEquals(String.format("%s: \"%s\" attribute for <%s> differ", message, item.getNodeName(), expectedTree.getNodeName()), item.getNodeValue(), actualAttributes.getNamedItem(item.getNodeName()).getNodeValue());
|
String nodeValue = item.getNodeValue();
|
||||||
|
|
||||||
|
// NOTE: com.sun...JPEGMetadata javax_imageio_1.0 format bug: Uses "normal" instead of "Normal" ImageOrientation
|
||||||
|
if ("ImageOrientation".equals(expectedTree.getNodeName()) && "value".equals(item.getNodeName())) {
|
||||||
|
nodeValue = StringUtil.capitalize(nodeValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
assertEquals(String.format("%s: \"%s\" attribute for <%s> differ", message, item.getNodeName(), expectedTree.getNodeName()), nodeValue, actualAttributes.getNamedItem(item.getNodeName()).getNodeValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test for equal user objects.
|
// Test for equal user objects.
|
||||||
@@ -1460,6 +1553,11 @@ public class JPEGImageReaderTest extends ImageReaderAbstractTest<JPEGImageReader
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ("markerSequence".equals(expectedTree.getNodeName()) && "JFIFthumbJPEG".equals(expectedTree.getParentNode().getNodeName())) {
|
||||||
|
// TODO: We haven't implemented this yet
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Sort nodes to make sure that sequence of equally named tags does not matter
|
// Sort nodes to make sure that sequence of equally named tags does not matter
|
||||||
List<IIOMetadataNode> expectedChildren = sortNodes(expectedTree.getChildNodes());
|
List<IIOMetadataNode> expectedChildren = sortNodes(expectedTree.getChildNodes());
|
||||||
List<IIOMetadataNode> actualChildren = sortNodes(actualTree.getChildNodes());
|
List<IIOMetadataNode> actualChildren = sortNodes(actualTree.getChildNodes());
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ package com.twelvemonkeys.imageio.plugins.jpeg;
|
|||||||
import com.twelvemonkeys.imageio.stream.ByteArrayImageInputStream;
|
import com.twelvemonkeys.imageio.stream.ByteArrayImageInputStream;
|
||||||
import com.twelvemonkeys.imageio.util.IIOUtil;
|
import com.twelvemonkeys.imageio.util.IIOUtil;
|
||||||
import com.twelvemonkeys.imageio.util.ImageWriterAbstractTest;
|
import com.twelvemonkeys.imageio.util.ImageWriterAbstractTest;
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.w3c.dom.NodeList;
|
import org.w3c.dom.NodeList;
|
||||||
|
|
||||||
@@ -47,17 +48,23 @@ import javax.imageio.stream.ImageOutputStream;
|
|||||||
import javax.imageio.stream.MemoryCacheImageOutputStream;
|
import javax.imageio.stream.MemoryCacheImageOutputStream;
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.awt.color.ColorSpace;
|
import java.awt.color.ColorSpace;
|
||||||
|
import java.awt.color.ICC_Profile;
|
||||||
import java.awt.image.BufferedImage;
|
import java.awt.image.BufferedImage;
|
||||||
|
import java.awt.image.ComponentColorModel;
|
||||||
|
import java.awt.image.DataBuffer;
|
||||||
import java.awt.image.RenderedImage;
|
import java.awt.image.RenderedImage;
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
import static org.junit.Assert.assertNotNull;
|
import static org.junit.Assert.assertNotNull;
|
||||||
|
import static org.mockito.Mockito.mock;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* JPEGImageWriterTest
|
* JPEGImageWriterTest
|
||||||
@@ -66,22 +73,14 @@ import static org.junit.Assert.assertNotNull;
|
|||||||
* @author last modified by $Author: haraldk$
|
* @author last modified by $Author: haraldk$
|
||||||
* @version $Id: JPEGImageWriterTest.java,v 1.0 06.02.12 17:05 haraldk Exp$
|
* @version $Id: JPEGImageWriterTest.java,v 1.0 06.02.12 17:05 haraldk Exp$
|
||||||
*/
|
*/
|
||||||
public class JPEGImageWriterTest extends ImageWriterAbstractTest {
|
public class JPEGImageWriterTest extends ImageWriterAbstractTest<JPEGImageWriter> {
|
||||||
|
|
||||||
private static final JPEGImageWriterSpi SPI = new JPEGImageWriterSpi(lookupDelegateProvider());
|
|
||||||
|
|
||||||
private static ImageWriterSpi lookupDelegateProvider() {
|
private static ImageWriterSpi lookupDelegateProvider() {
|
||||||
return IIOUtil.lookupProviderByName(IIORegistry.getDefaultInstance(), "com.sun.imageio.plugins.jpeg.JPEGImageWriterSpi", ImageWriterSpi.class);
|
return IIOUtil.lookupProviderByName(IIORegistry.getDefaultInstance(), "com.sun.imageio.plugins.jpeg.JPEGImageWriterSpi", ImageWriterSpi.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected ImageWriter createImageWriter() {
|
protected ImageWriterSpi createProvider() {
|
||||||
try {
|
return new JPEGImageWriterSpi(lookupDelegateProvider());
|
||||||
return SPI.createWriterInstance();
|
|
||||||
}
|
|
||||||
catch (IOException e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -97,14 +96,18 @@ public class JPEGImageWriterTest extends ImageWriterAbstractTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testReaderForWriter() {
|
public void testReaderForWriter() throws IOException {
|
||||||
ImageWriter writer = createImageWriter();
|
ImageWriter writer = createWriter();
|
||||||
ImageReader reader = ImageIO.getImageReader(writer);
|
ImageReader reader = ImageIO.getImageReader(writer);
|
||||||
assertNotNull(reader);
|
assertNotNull(reader);
|
||||||
assertEquals(writer.getClass().getPackage(), reader.getClass().getPackage());
|
assertEquals(writer.getClass().getPackage(), reader.getClass().getPackage());
|
||||||
}
|
}
|
||||||
|
|
||||||
private ByteArrayOutputStream transcode(final ImageReader reader, final URL resource, final ImageWriter writer, int outCSType) throws IOException {
|
private ByteArrayOutputStream transcode(final ImageReader reader, final URL resource, final ImageWriter writer, int outCSType) throws IOException {
|
||||||
|
return transcode(reader, resource, writer, outCSType, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private ByteArrayOutputStream transcode(final ImageReader reader, final URL resource, final ImageWriter writer, int outCSType, boolean embedICCProfile) throws IOException {
|
||||||
try (ImageInputStream input = ImageIO.createImageInputStream(resource)) {
|
try (ImageInputStream input = ImageIO.createImageInputStream(resource)) {
|
||||||
reader.setInput(input);
|
reader.setInput(input);
|
||||||
ImageTypeSpecifier specifier = null;
|
ImageTypeSpecifier specifier = null;
|
||||||
@@ -125,6 +128,14 @@ public class JPEGImageWriterTest extends ImageWriterAbstractTest {
|
|||||||
readParam.setDestinationType(specifier);
|
readParam.setDestinationType(specifier);
|
||||||
IIOImage image = reader.readAll(0, readParam);
|
IIOImage image = reader.readAll(0, readParam);
|
||||||
|
|
||||||
|
if (!embedICCProfile) {
|
||||||
|
// Get rid of the color model/icc profile
|
||||||
|
ColorSpace fakeCS = mock(ColorSpace.class);
|
||||||
|
when(fakeCS.getType()).thenReturn(ColorSpace.TYPE_CMYK);
|
||||||
|
when(fakeCS.getNumComponents()).thenReturn(4);
|
||||||
|
specifier = new ImageTypeSpecifier(new ComponentColorModel(fakeCS, false, false, Transparency.OPAQUE, DataBuffer.TYPE_BYTE), image.getRenderedImage().getSampleModel());
|
||||||
|
}
|
||||||
|
|
||||||
// Write it back
|
// Write it back
|
||||||
ByteArrayOutputStream bytes = new ByteArrayOutputStream(1024);
|
ByteArrayOutputStream bytes = new ByteArrayOutputStream(1024);
|
||||||
try (ImageOutputStream output = new MemoryCacheImageOutputStream(bytes)) {
|
try (ImageOutputStream output = new MemoryCacheImageOutputStream(bytes)) {
|
||||||
@@ -140,7 +151,7 @@ public class JPEGImageWriterTest extends ImageWriterAbstractTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testTranscodeWithMetadataRGBtoRGB() throws IOException {
|
public void testTranscodeWithMetadataRGBtoRGB() throws IOException {
|
||||||
ImageWriter writer = createImageWriter();
|
ImageWriter writer = createWriter();
|
||||||
ImageReader reader = ImageIO.getImageReader(writer);
|
ImageReader reader = ImageIO.getImageReader(writer);
|
||||||
|
|
||||||
ByteArrayOutputStream stream = transcode(reader, getClassLoaderResource("/jpeg/jfif-jfxx-thumbnail-olympus-d320l.jpg"), writer, ColorSpace.TYPE_RGB);
|
ByteArrayOutputStream stream = transcode(reader, getClassLoaderResource("/jpeg/jfif-jfxx-thumbnail-olympus-d320l.jpg"), writer, ColorSpace.TYPE_RGB);
|
||||||
@@ -151,11 +162,18 @@ public class JPEGImageWriterTest extends ImageWriterAbstractTest {
|
|||||||
reader.setInput(new ByteArrayImageInputStream(stream.toByteArray()));
|
reader.setInput(new ByteArrayImageInputStream(stream.toByteArray()));
|
||||||
BufferedImage image = reader.read(0);
|
BufferedImage image = reader.read(0);
|
||||||
assertNotNull(image);
|
assertNotNull(image);
|
||||||
|
|
||||||
|
// Test color space type RGB (encoded as YCbCr) in standard metadata
|
||||||
|
IIOMetadata metadata = reader.getImageMetadata(0);
|
||||||
|
IIOMetadataNode standard = (IIOMetadataNode) metadata.getAsTree(IIOMetadataFormatImpl.standardMetadataFormatName);
|
||||||
|
NodeList colorSpaceType = standard.getElementsByTagName("ColorSpaceType");
|
||||||
|
assertEquals(1, colorSpaceType.getLength());
|
||||||
|
assertEquals("YCbCr", ((IIOMetadataNode) colorSpaceType.item(0)).getAttribute("name"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testTranscodeWithMetadataCMYKtoCMYK() throws IOException {
|
public void testTranscodeWithMetadataCMYKtoCMYK() throws IOException {
|
||||||
ImageWriter writer = createImageWriter();
|
ImageWriter writer = createWriter();
|
||||||
ImageReader reader = ImageIO.getImageReader(writer);
|
ImageReader reader = ImageIO.getImageReader(writer);
|
||||||
|
|
||||||
ByteArrayOutputStream stream = transcode(reader, getClassLoaderResource("/jpeg/cmyk-sample-multiple-chunk-icc.jpg"), writer, ColorSpace.TYPE_CMYK);
|
ByteArrayOutputStream stream = transcode(reader, getClassLoaderResource("/jpeg/cmyk-sample-multiple-chunk-icc.jpg"), writer, ColorSpace.TYPE_CMYK);
|
||||||
@@ -168,11 +186,65 @@ public class JPEGImageWriterTest extends ImageWriterAbstractTest {
|
|||||||
assertEquals(100, image.getWidth());
|
assertEquals(100, image.getWidth());
|
||||||
assertEquals(100, image.getHeight());
|
assertEquals(100, image.getHeight());
|
||||||
|
|
||||||
|
// Test color space type CMYK in standard metadata
|
||||||
IIOMetadata metadata = reader.getImageMetadata(0);
|
IIOMetadata metadata = reader.getImageMetadata(0);
|
||||||
IIOMetadataNode standard = (IIOMetadataNode) metadata.getAsTree(IIOMetadataFormatImpl.standardMetadataFormatName);
|
IIOMetadataNode standard = (IIOMetadataNode) metadata.getAsTree(IIOMetadataFormatImpl.standardMetadataFormatName);
|
||||||
NodeList colorSpaceType = standard.getElementsByTagName("ColorSpaceType");
|
NodeList colorSpaceType = standard.getElementsByTagName("ColorSpaceType");
|
||||||
assertEquals(1, colorSpaceType.getLength());
|
assertEquals(1, colorSpaceType.getLength());
|
||||||
assertEquals("CMYK", ((IIOMetadataNode) colorSpaceType.item(0)).getAttribute("name"));
|
assertEquals("CMYK", ((IIOMetadataNode) colorSpaceType.item(0)).getAttribute("name"));
|
||||||
|
|
||||||
|
// Test APP2/ICC_PROFILE segments form native metadata
|
||||||
|
IIOMetadataNode nativeMeta = (IIOMetadataNode) metadata.getAsTree(JPEGImage10Metadata.JAVAX_IMAGEIO_JPEG_IMAGE_1_0);
|
||||||
|
NodeList unknown = nativeMeta.getElementsByTagName("unknown");
|
||||||
|
assertEquals(11, unknown.getLength()); // We write longer segments than the original, so we get less segments
|
||||||
|
|
||||||
|
ByteArrayOutputStream iccSegments = new ByteArrayOutputStream(1024 * 1024);
|
||||||
|
|
||||||
|
for (int i = 0; i < unknown.getLength(); i++) {
|
||||||
|
IIOMetadataNode node = (IIOMetadataNode) unknown.item(i);
|
||||||
|
byte[] data = (byte[]) node.getUserObject();
|
||||||
|
|
||||||
|
// 226 -> E2, FFE2 -> APP2 marker, ICC_PROFILE
|
||||||
|
String markerId = "ICC_PROFILE";
|
||||||
|
if (node.getAttribute("MarkerTag").equals("226")
|
||||||
|
&& markerId.equals(new String(data, 0, markerId.length(), StandardCharsets.US_ASCII))) {
|
||||||
|
int offset = markerId.length() + 3; // ICC_PROFILE + null + index + count
|
||||||
|
iccSegments.write(Arrays.copyOfRange(data, offset, data.length));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ICC_Profile profile = ICC_Profile.getInstance(iccSegments.toByteArray());
|
||||||
|
assertNotNull(profile); // Assumption, we either have a valid profile, or getInstance blew up...
|
||||||
|
assertEquals(ColorSpace.TYPE_CMYK, profile.getColorSpaceType());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testTranscodeWithMetadataCMYKtoCMYKNoProfile() throws IOException {
|
||||||
|
ImageWriter writer = createWriter();
|
||||||
|
ImageReader reader = ImageIO.getImageReader(writer);
|
||||||
|
|
||||||
|
// TODO: Add flag to allow removing the ICC profile from image
|
||||||
|
ByteArrayOutputStream stream = transcode(reader, getClassLoaderResource("/jpeg/cmyk-sample-multiple-chunk-icc.jpg"), writer, ColorSpace.TYPE_CMYK, false);
|
||||||
|
|
||||||
|
reader.reset();
|
||||||
|
reader.setInput(new ByteArrayImageInputStream(stream.toByteArray()));
|
||||||
|
|
||||||
|
BufferedImage image = reader.read(0);
|
||||||
|
assertNotNull(image);
|
||||||
|
assertEquals(100, image.getWidth());
|
||||||
|
assertEquals(100, image.getHeight());
|
||||||
|
|
||||||
|
// Test color space type CMYK in standard metadata
|
||||||
|
IIOMetadata metadata = reader.getImageMetadata(0);
|
||||||
|
IIOMetadataNode standard = (IIOMetadataNode) metadata.getAsTree(IIOMetadataFormatImpl.standardMetadataFormatName);
|
||||||
|
NodeList colorSpaceType = standard.getElementsByTagName("ColorSpaceType");
|
||||||
|
assertEquals(1, colorSpaceType.getLength());
|
||||||
|
assertEquals("CMYK", ((IIOMetadataNode) colorSpaceType.item(0)).getAttribute("name"));
|
||||||
|
|
||||||
|
// Test APP2/ICC_PROFILE segments form native metadata
|
||||||
|
IIOMetadataNode nativeMeta = (IIOMetadataNode) metadata.getAsTree(JPEGImage10Metadata.JAVAX_IMAGEIO_JPEG_IMAGE_1_0);
|
||||||
|
NodeList unknown = nativeMeta.getElementsByTagName("unknown");
|
||||||
|
assertEquals(0, unknown.getLength());
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: YCCK
|
// TODO: YCCK
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ import com.twelvemonkeys.imageio.metadata.jpeg.JPEG;
|
|||||||
import com.twelvemonkeys.imageio.metadata.jpeg.JPEGSegment;
|
import com.twelvemonkeys.imageio.metadata.jpeg.JPEGSegment;
|
||||||
import com.twelvemonkeys.imageio.metadata.jpeg.JPEGSegmentUtil;
|
import com.twelvemonkeys.imageio.metadata.jpeg.JPEGSegmentUtil;
|
||||||
import com.twelvemonkeys.imageio.stream.URLImageInputStreamSpi;
|
import com.twelvemonkeys.imageio.stream.URLImageInputStreamSpi;
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.mockito.internal.matchers.LessOrEqual;
|
import org.mockito.internal.matchers.LessOrEqual;
|
||||||
|
|
||||||
@@ -46,7 +47,9 @@ import java.io.IOException;
|
|||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import static org.junit.Assert.*;
|
import static org.hamcrest.MatcherAssert.assertThat;
|
||||||
|
import static org.junit.Assert.assertArrayEquals;
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* JPEGSegmentImageInputStreamTest
|
* JPEGSegmentImageInputStreamTest
|
||||||
|
|||||||
@@ -0,0 +1,19 @@
|
|||||||
|
Copyright (c) 2010 Dave Perrett, http://recursive-design.com/
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
||||||
|
After Width: | Height: | Size: 342 KiB |
|
After Width: | Height: | Size: 339 KiB |
|
After Width: | Height: | Size: 341 KiB |
|
After Width: | Height: | Size: 341 KiB |
|
After Width: | Height: | Size: 340 KiB |
|
After Width: | Height: | Size: 343 KiB |
|
After Width: | Height: | Size: 344 KiB |