Compare commits

...

52 Commits

Author SHA1 Message Date
Harald Kuhr 26d3de45a7 [maven-release-plugin] prepare for next development iteration 2020-01-09 19:40:24 +01:00
Harald Kuhr 13507ce303 [maven-release-plugin] prepare release twelvemonkeys-3.4.3 2020-01-09 19:40:16 +01:00
Harald Kuhr a8508dc234 Stick to the git user, when using ssh
(cherry picked from commit b6aec25f00)
2020-01-09 19:28:35 +01:00
Harald Kuhr b3cf467f0b log4j removal
(cherry picked from commit ae213dcf5e)
2020-01-09 19:25:48 +01:00
Harald Kuhr b0e6fbed9f #510: Fixes possible hang situation
(cherry picked from commit 5501c0e709)
2020-01-09 19:25:48 +01:00
Harald Kuhr c087addb76 #501: Fix for TYPE_USHORT_555/565_RGB, ColorModel now 16 bits
(cherry picked from commit 42e17f2063)
2020-01-09 19:25:48 +01:00
Harald Kuhr 250c58cc2e #289, #493: Finally implemented subsampling for < 8 bit samples
(cherry picked from commit 0c2433dc9f)
2020-01-09 19:25:48 +01:00
Oliver Schmidtmer c33b3a76f4 Test correction for ViewBox based svg sizes
(cherry picked from commit 810b7197ab)
2020-01-09 19:24:58 +01:00
Oliver Schmidtmer f14e6823bd When rescaling SVGs use the ViewBox, if defined, for default sizes
(cherry picked from commit 24a0786d64)
2020-01-09 19:24:58 +01:00
Harald Kuhr cae72336a2 [maven-release-plugin] prepare for next development iteration 2019-08-12 21:05:55 +02:00
Harald Kuhr c5bf0a6f0b [maven-release-plugin] prepare release twelvemonkeys-3.4.2 2019-08-12 21:03:23 +02:00
Harald Kuhr 691b7560db Switched Maven SCM to use ssh.
(cherry picked from commit c1834dc78d)
2019-08-12 20:42:24 +02:00
Harald Kuhr e1025f9540 Fixed JavaDoc errors to enable Java 8 build.
(cherry picked from commit 9e23413456)
2019-08-10 00:58:08 +02:00
Harald Kuhr fa09099da0 Fixed encoding issues in readme.
(cherry picked from commit 7d2c692663)
2019-08-09 21:04:41 +02:00
Harald Kuhr 140b074ac6 #398: Better exception message when BufferedImage size > Integer.MAX
(cherry picked from commit 9ce1a86cae)
2019-08-09 21:04:41 +02:00
Harald Kuhr 59c6c18cbb #477: Better tests to for cyclic loops in IFDs.
(cherry picked from commit b0b5de5fa4)
2019-08-09 21:04:41 +02:00
Harald Kuhr c48e17dabf #474: Fix java.awt.color.CMMException: Can not access specified profile
(cherry picked from commit 64178bd636)
2019-08-09 21:04:41 +02:00
Harald Kuhr 22a842eb78 449# Missing test to verify that we ignore bogus 0 byte counts.
(cherry picked from commit 7985cdd4a7)
2019-08-09 21:04:41 +02:00
Harald Kuhr bdd7f5b228 #492: Now correctly parses multiple strings for ASCII fields.
(cherry picked from commit 8247861095)
2019-08-09 21:04:40 +02:00
Harald Kuhr 0e41d4a5f7 #477: Avoid cyclic loops in IFDs.
(cherry picked from commit 8480c929c1)
2019-08-09 21:04:40 +02:00
Harald Kuhr 653360e054 Moving travis build to trusty, to fix JDK8 build
(cherry picked from commit e6f437f55b)
2019-08-09 21:04:40 +02:00
Harald Kuhr 4f193d543c #488: Fix for AIOOBE in getEmbeddedICCProfile when ICC profile is empty
(cherry picked from commit ee049d9465)
2019-08-09 21:04:40 +02:00
Harald Kuhr 1d0cc43476 #489 Fix for Unexpected End of PackBits Stream for padded streams.
(cherry picked from commit f6aa810f8b)
2019-08-09 21:04:40 +02:00
Harald Kuhr 9791a251ed #469 Fix for OOME while reading Exif with corrupted IFDs/counts
(cherry picked from commit e8d1b999a2)
2019-08-09 21:04:40 +02:00
Harald Kuhr 0bc30f4d18 JPEG Exif parsing optimization.
(cherry picked from commit d7fbd6594e)
2019-08-09 21:04:40 +02:00
Harald Kuhr 022fc03fbb XMLSerializer speedup.
(cherry picked from commit caef9b6a9e)
2019-08-09 21:04:39 +02:00
Harald Kuhr 8b66842859 #475: Fix support for writing TIFF > 2 GB
(cherry picked from commit 7fad4d5cd8)
2019-08-09 21:04:39 +02:00
Harald Kuhr 5251f4665e #473: Fix for ColorMap (Indexed) TIFF with non-alpha ExtraSamples.
(cherry picked from commit 3e4b14f984)
2019-08-09 21:04:39 +02:00
Paul Verest b98b81b877 colorize code snippets in README using GFM ``java, ``xml
(cherry picked from commit 51b0734462)
2019-08-09 21:03:01 +02:00
Harald Kuhr 774b494fec Updated commons-fileupload dependency to safe version, even if in scope provided, just in case.
(cherry picked from commit 8e3cd5aedb)
2019-08-09 21:03:00 +02:00
Oliver Schmidtmer 90ef605b0c Fix for #455: Ignore profiles PhotometricInterpretation MinIsWhite with 1bit/pixel
(cherry picked from commit cbaa0dc688)
2019-08-09 21:03:00 +02:00
Harald Kuhr b40eea0fc4 Fix test case for #446 in case of "Gerenic CMYK" profile not being available.
(cherry picked from commit 61bac97933)
2019-08-09 21:03:00 +02:00
Harald Kuhr 9ac2013965 Better assertion failed messages.
(cherry picked from commit 3e9be32279)
2019-08-09 21:03:00 +02:00
Harald Kuhr 4740a39cd2 Test case for #446.
(cherry picked from commit a0955875d8)
2019-08-09 21:03:00 +02:00
Harald Kuhr 7ebcc437c3 Various Java 9 and beyond fixes:
- ExtraSamplesColorModel now overrides getComponentSize for correct size
 - TIFFImageReader/WriterSpi now recognizes the JEP 262 TIFF plugin
 - CCITTFaxEncoderStreamTest now directly creates writer (not JDK one)

(cherry picked from commit 7e0de14783)
2019-08-09 21:02:30 +02:00
Harald Kuhr 70c16dfdd9 Various Java 9 and beyond fixes.
(cherry picked from commit de34d4642e)
2019-08-09 21:02:30 +02:00
Harald Kuhr c9e2e21727 Equals method for DiscreteAlphaIndexColorModel, needed for Java 10.
(cherry picked from commit b86bad2bf9)
2019-08-09 21:02:30 +02:00
Harald Kuhr 230ac33283 #442 SVG BaseURI issue fix
(cherry picked from commit cc5af0134c)
2019-08-09 21:02:30 +02:00
Bernhard Fey 66e0acb668 Added test file for non-alpha extra channel
Added test file for CMYK TIFF with non-alpha extra channel

(cherry picked from commit edcac25f5e)
2019-08-09 21:02:30 +02:00
Bernhard Fey 7d8858c177 Modified new create[ImageTypeSpecifier] method according to suggestions by @haraldk
Renamed "create" method to "createImageTypeSpecifier".
Added exception thrown for unsupported planarConfiguration values.

(cherry picked from commit 5a5c1f996b)
2019-08-09 21:02:30 +02:00
Bernhard Fey faab9517dd Fix for non-RGB images with extra sample
Added "create" method to TIFFImageReader that centralizes the use of "createBanded" and "createInterleaved" as well as the "extra samples" special case and fixes non-RGB images with non-alpha extra samples

(cherry picked from commit f9b8cae0ea)
2019-08-09 21:02:30 +02:00
Harald Kuhr 2433777b6d Updated readme
(cherry picked from commit 62538c3db9)
2019-08-09 21:02:13 +02:00
Harald Kuhr 3980c937cf Fixed release date.
(cherry picked from commit 48aa504be4)
2019-08-09 21:02:13 +02:00
Harald Kuhr 468ffb891d Updated versions from 3.4 to 3.4.1.
(cherry picked from commit ed2eb7642a)
2019-08-09 21:02:13 +02:00
Harald Kuhr e27e8a7ccb #408 Added servlet JAR to dependency example.
(cherry picked from commit 24ec5ae34d)
2019-08-09 21:02:03 +02:00
Harald Kuhr f2dba604da #311 Updated some more license headers that was left out in the initial change.
(cherry picked from commit a7b374e51a)
2019-08-09 21:01:29 +02:00
Harald Kuhr 04f27a1694 #438 CompoundDocument file descriptor fix 2018-09-08 16:21:01 +02:00
Harald Kuhr 2630a6a795 [maven-release-plugin] prepare for next development iteration 2018-09-07 19:48:17 +02:00
Harald Kuhr ab2f1f7e91 [maven-release-plugin] prepare release twelvemonkeys-3.4.1 2018-09-07 19:48:10 +02:00
Harald Kuhr 7110e89bda Prepare next release 2018-09-07 19:42:06 +02:00
Harald Kuhr a06cbfd6f4 #437 Catching exception from static init, prints a warning and moves on.
(cherry picked from commit d8d0131)
2018-08-30 15:04:55 +02:00
Harald Kuhr 3b68d676f3 #439: Unclear exception message when passing image metadata as stream metadata
(cherry picked from commit 6018093)
2018-08-30 15:04:52 +02:00
246 changed files with 36615 additions and 35468 deletions
+1
View File
@@ -1,3 +1,4 @@
dist: trusty
language: java
jdk:
- oraclejdk8
+81 -58
View File
@@ -2,7 +2,7 @@
Master branch build status: [![Build Status](https://travis-ci.org/haraldk/TwelveMonkeys.svg?branch=master)](https://travis-ci.org/haraldk/TwelveMonkeys)
Latest release is TwelveMonkeys ImageIO [3.3.2](http://search.maven.org/#search%7Cga%7C1%7Cg%3Acom.twelvemonkeys*%20AND%20v%3A%223.3.2%22) (Feb. 2nd, 2017).
Latest release is TwelveMonkeys ImageIO [3.4.1](https://search.maven.org/search?q=g:com.twelvemonkeys.imageio%20AND%20v:3.4.1) (Sep. 7th, 2018).
[Release notes](https://github.com/haraldk/TwelveMonkeys/releases/latest).
## About
@@ -56,9 +56,9 @@ Mainstream format support
* `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 in progress:
* Extended write support:
* CMYK JPEGs
* YCCK JPEGs
* YCCK JPEGs in progress
#### JPEG-2000
@@ -206,6 +206,7 @@ Legacy formats
* Uncompressed
* RLE compressed
* Standard metadata support
* Write support
Icon/other formats
@@ -215,6 +216,7 @@ Icon/other formats
* 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
@@ -223,6 +225,7 @@ Icon/other formats
* 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
@@ -265,6 +268,7 @@ 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:
```java
// Create input stream
ImageInputStream input = ImageIO.createImageInputStream(file);
@@ -309,6 +313,7 @@ If you need more control of read parameters and the reading process, the common
// 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
entire image into memory first.
@@ -318,6 +323,7 @@ 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:
```java
// Get the writer
Iterator<ImageWriter> writers = ImageIO.getImageWritersByFormatName(format);
@@ -353,6 +359,7 @@ If you need more control of write parameters and the writing process, the common
// 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
[Java Image I/O API Guide](http://docs.oracle.com/javase/7/docs/technotes/guides/imageio/spec/imageio_guideTOC.fm.html)
@@ -376,6 +383,7 @@ 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 ...>
...
@@ -388,6 +396,7 @@ dynamic loading and unloading of ImageIO plugins for web applications.
...
</web-app>
```
Loading plugins from `WEB-INF/lib` without the context listener installed is unsupported and will not work correctly.
@@ -401,6 +410,7 @@ Another safe option, is to place the JAR files in the application server's share
The library comes with a resampling (image resizing) operation, that contains many different algorithms
to provide excellent results at reasonable speed.
```java
import com.twelvemonkeys.image.ResampleOp;
...
@@ -410,13 +420,14 @@ to provide excellent results at reasonable speed.
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);
```
#### Using the DiffusionDither
The library comes with a dithering operation, that can be used to convert `BufferedImage`s to `IndexColorModel` using
Floyd-Steinberg error-diffusion dither.
```java
import com.twelvemonkeys.image.DiffusionDither;
...
@@ -425,7 +436,7 @@ Floyd-Steinberg error-diffusion dither.
BufferedImageOp ditherer = new DiffusionDither();
BufferedImage output = ditherer.filter(input, null);
```
## Building
@@ -461,10 +472,12 @@ 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:
```java
Iterator<ImageReader> readers = ImageIO.getImageReadersByFormatName("JPEG");
while (readers.hasNext()) {
System.out.println("reader: " + readers.next());
}
```
The first line should print:
@@ -474,71 +487,83 @@ The first line should print:
To depend on the JPEG and TIFF plugin using Maven, add the following to your POM:
```xml
...
<dependencies>
...
<dependency>
<groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio-jpeg</artifactId>
<version>3.3.2</version> <!-- Alternatively, build your own version -->
<version>3.4.1</version>
</dependency>
<dependency>
<groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio-tiff</artifactId>
<version>3.3.2</version> <!-- Alternatively, build your own version -->
<version>3.4.1</version>
</dependency>
<!--
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.
-->
<dependency>
<groupId>com.twelvemonkeys.servlet</groupId>
<artifactId>servlet</artifactId>
<version>3.4.1</version>
</dependency>
</dependencies>
```
#### 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:
twelvemonkeys-common-lang-3.3.2.jar
twelvemonkeys-common-io-3.3.2.jar
twelvemonkeys-common-image-3.3.2.jar
twelvemonkeys-imageio-core-3.3.2.jar
twelvemonkeys-imageio-metadata-3.3.2.jar
twelvemonkeys-imageio-jpeg-3.3.2.jar
twelvemonkeys-imageio-tiff-3.3.2.jar
twelvemonkeys-common-lang-3.4.1.jar
twelvemonkeys-common-io-3.4.1.jar
twelvemonkeys-common-image-3.4.1.jar
twelvemonkeys-imageio-core-3.4.1.jar
twelvemonkeys-imageio-metadata-3.4.1.jar
twelvemonkeys-imageio-jpeg-3.4.1.jar
twelvemonkeys-imageio-tiff-3.4.1.jar
### Links to prebuilt binaries
##### Latest version (3.2.x)
##### Latest version (3.4.1)
Requires Java 7 or later.
Common dependencies
* [common-lang-3.3.2.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/common/common-lang/3.3.2/common-lang-3.3.2.jar)
* [common-io-3.3.2.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/common/common-io/3.3.2/common-io-3.3.2.jar)
* [common-image-3.3.2.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/common/common-image/3.3.2/common-image-3.3.2.jar)
* [common-lang-3.4.1.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/common/common-lang/3.4.1/common-lang-3.4.1.jar)
* [common-io-3.4.1.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/common/common-io/3.4.1/common-io-3.4.1.jar)
* [common-image-3.4.1.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/common/common-image/3.4.1/common-image-3.4.1.jar)
ImageIO dependencies
* [imageio-core-3.3.2.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-core/3.3.2/imageio-core-3.3.2.jar)
* [imageio-metadata-3.3.2.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-metadata/3.3.2/imageio-metadata-3.3.2.jar)
* [imageio-core-3.4.1.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-core/3.4.1/imageio-core-3.4.1.jar)
* [imageio-metadata-3.4.1.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-metadata/3.4.1/imageio-metadata-3.4.1.jar)
ImageIO plugins
* [imageio-bmp-3.3.2.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-bmp/3.3.2/imageio-bmp-3.3.2.jar)
* [imageio-jpeg-3.3.2.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-jpeg/3.3.2/imageio-jpeg-3.3.2.jar)
* [imageio-tiff-3.3.2.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-tiff/3.3.2/imageio-tiff-3.3.2.jar)
* [imageio-pnm-3.3.2.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-pnm/3.3.2/imageio-pnm-3.3.2.jar)
* [imageio-psd-3.3.2.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-psd/3.3.2/imageio-psd-3.3.2.jar)
* [imageio-hdr-3.3.2.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-hdr/3.3.2/imageio-hdr-3.3.2.jar)
* [imageio-iff-3.3.2.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-iff/3.3.2/imageio-iff-3.3.2.jar)
* [imageio-pcx-3.3.2.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-pcx/3.3.2/imageio-pcx-3.3.2.jar)
* [imageio-pict-3.3.2.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-pict/3.3.2/imageio-pict-3.3.2.jar)
* [imageio-sgi-3.3.2.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-sgi/3.3.2/imageio-sgi-3.3.2.jar)
* [imageio-tga-3.3.2.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-tga/3.3.2/imageio-tga-3.3.2.jar)
* [imageio-icns-3.3.2.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-icns/3.3.2/imageio-icns-3.3.2.jar)
* [imageio-thumbsdb-3.3.2.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-thumbsdb/3.3.2/imageio-thumbsdb-3.3.2.jar)
* [imageio-bmp-3.4.1.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-bmp/3.4.1/imageio-bmp-3.4.1.jar)
* [imageio-jpeg-3.4.1.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-jpeg/3.4.1/imageio-jpeg-3.4.1.jar)
* [imageio-tiff-3.4.1.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-tiff/3.4.1/imageio-tiff-3.4.1.jar)
* [imageio-pnm-3.4.1.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-pnm/3.4.1/imageio-pnm-3.4.1.jar)
* [imageio-psd-3.4.1.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-psd/3.4.1/imageio-psd-3.4.1.jar)
* [imageio-hdr-3.4.1.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-hdr/3.4.1/imageio-hdr-3.4.1.jar)
* [imageio-iff-3.4.1.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-iff/3.4.1/imageio-iff-3.4.1.jar)
* [imageio-pcx-3.4.1.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-pcx/3.4.1/imageio-pcx-3.4.1.jar)
* [imageio-pict-3.4.1.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-pict/3.4.1/imageio-pict-3.4.1.jar)
* [imageio-sgi-3.4.1.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-sgi/3.4.1/imageio-sgi-3.4.1.jar)
* [imageio-tga-3.4.1.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-tga/3.4.1/imageio-tga-3.4.1.jar)
* [imageio-icns-3.4.1.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-icns/3.4.1/imageio-icns-3.4.1.jar)
* [imageio-thumbsdb-3.4.1.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-thumbsdb/3.4.1/imageio-thumbsdb-3.4.1.jar)
ImageIO plugins requiring 3rd party libs
* [imageio-batik-3.3.2.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-batik/3.3.2/imageio-batik-3.3.2.jar)
* [imageio-batik-3.4.1.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-batik/3.4.1/imageio-batik-3.4.1.jar)
Photoshop Path support for ImageIO
* [imageio-clippath-3.3.2.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-clippath/3.3.2/imageio-clippath-3.3.2.jar)
* [imageio-clippath-3.4.1.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-clippath/3.4.1/imageio-clippath-3.4.1.jar)
Servlet support
* [servlet-3.3.2.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/servlet/servlet/3.3.2/servlet-3.3.2.jar)
* [servlet-3.4.1.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/servlet/servlet/3.4.1/servlet-3.4.1.jar)
##### Old version (3.0.x)
@@ -575,35 +600,33 @@ Servlet support
The project is distributed under the OSI approved [BSD license](http://opensource.org/licenses/BSD-3-Clause):
Copyright (c) 2008-2015, Harald Kuhr
Copyright (c) 2008-2018, Harald Kuhr
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
o Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
o Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
o Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
o Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
o Neither the name "TwelveMonkeys" nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
o Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
## FAQ
@@ -649,7 +672,7 @@ Native libs does not exist for several popular platforms/architectures, and furt
Some environments may also prevent deployment of native libs, which brings us back to square one.
q: What about JMagick or IM4Java? Can't you just use what´s already available?
q: What about JMagick or IM4Java? Can't you just use what's already available?
a: While great libraries with a wide range of formats support, the ImageMagick-based libraries has some disadvantages
compared to ImageIO.
+1 -1
View File
@@ -5,7 +5,7 @@
<parent>
<groupId>com.twelvemonkeys</groupId>
<artifactId>twelvemonkeys</artifactId>
<version>3.4</version>
<version>3.4.4-SNAPSHOT</version>
</parent>
<groupId>com.twelvemonkeys.bom</groupId>
+1 -1
View File
@@ -4,7 +4,7 @@
<parent>
<groupId>com.twelvemonkeys.common</groupId>
<artifactId>common</artifactId>
<version>3.4</version>
<version>3.4.4-SNAPSHOT</version>
</parent>
<artifactId>common-image</artifactId>
<packaging>jar</packaging>
@@ -37,7 +37,6 @@ import java.util.List;
/**
* AbstractImageSource
* <p/>
*
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-core/src/main/java/com/twelvemonkeys/image/AbstractImageSource.java#1 $
@@ -35,14 +35,15 @@ import java.awt.image.RGBImageFilter;
/**
* Adjusts the contrast and brightness of an image.
* <p/>
* <p>
* For brightness, the valid range is {@code -2.0,..,0.0,..,2.0}.
* A value of {@code 0.0} means no change.
* Negative values will make the pixels darker.
* Maximum negative value ({@code -2}) will make all filtered pixels black.
* Positive values will make the pixels brighter.
* Maximum positive value ({@code 2}) will make all filtered pixels white.
* <p/>
* </p>
* <p>
* For contrast, the valid range is {@code -1.0,..,0.0,..,1.0}.
* A value of {@code 0.0} means no change.
* Negative values will reduce contrast.
@@ -51,15 +52,14 @@ import java.awt.image.RGBImageFilter;
* Positive values will increase contrast.
* Maximum positive value ({@code 1}) will make all filtered pixels primary
* colors (either black, white, cyan, magenta, yellow, red, blue or green).
* </p>
*
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
* @author last modified by $Author: haku $
*
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-core/src/main/java/com/twelvemonkeys/image/BrightnessContrastFilter.java#1 $
*
* @todo consider doing something similar to http://archives.java.sun.com/cgi-bin/wa?A2=ind0302&L=jai-interest&F=&S=&P=15947
*/
// TODO: consider doing something similar to http://archives.java.sun.com/cgi-bin/wa?A2=ind0302&L=jai-interest&F=&S=&P=15947
public class BrightnessContrastFilter extends RGBImageFilter {
// TODO: Replace with RescaleOp?
@@ -76,8 +76,9 @@ public class BrightnessContrastFilter extends RGBImageFilter {
/**
* Creates a BrightnessContrastFilter with default values
* ({@code brightness=0.3, contrast=0.3}).
* <p/>
* <p>
* This will slightly increase both brightness and contrast.
* </p>
*/
public BrightnessContrastFilter() {
this(0.3f, 0.3f);
@@ -86,14 +87,15 @@ public class BrightnessContrastFilter extends RGBImageFilter {
/**
* Creates a BrightnessContrastFilter with the given values for brightness
* and contrast.
* <p/>
* <p>
* For brightness, the valid range is {@code -2.0,..,0.0,..,2.0}.
* A value of {@code 0.0} means no change.
* Negative values will make the pixels darker.
* Maximum negative value ({@code -2}) will make all filtered pixels black.
* Positive values will make the pixels brighter.
* Maximum positive value ({@code 2}) will make all filtered pixels white.
* <p/>
* </p>
* <p>
* For contrast, the valid range is {@code -1.0,..,0.0,..,1.0}.
* A value of {@code 0.0} means no change.
* Negative values will reduce contrast.
@@ -102,6 +104,7 @@ public class BrightnessContrastFilter extends RGBImageFilter {
* Positive values will increase contrast.
* Maximum positive value ({@code 1}) will make all filtered pixels primary
* colors (either black, white, cyan, magenta, yellow, red, blue or green).
* </p>
*
* @param pBrightness adjust the brightness of the image, in the range
* {@code -2.0,..,0.0,..,2.0}.
@@ -44,14 +44,16 @@ import java.util.concurrent.CopyOnWriteArrayList;
* A faster, lighter and easier way to convert an {@code Image} to a
* {@code BufferedImage} than using a {@code PixelGrabber}.
* Clients may provide progress listeners to monitor conversion progress.
* <p/>
* <p>
* Supports source image subsampling and source region extraction.
* Supports source images with 16 bit {@link ColorModel} and
* {@link DataBuffer#TYPE_USHORT} transfer type, without converting to
* 32 bit/TYPE_INT.
* <p/>
* </p>
* <p>
* NOTE: Does not support images with more than one {@code ColorModel} or
* different types of pixel data. This is not very common.
* </p>
*
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-core/src/main/java/com/twelvemonkeys/image/BufferedImageFactory.java#1 $
@@ -39,7 +39,6 @@ import java.awt.image.BufferedImage;
/**
* An {@code Icon} implementation backed by a {@code BufferedImage}.
* <p/>
*
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-core/src/main/java/com/twelvemonkeys/image/BufferedImageIcon.java#2 $
@@ -39,22 +39,24 @@ import java.util.Random;
/**
* This {@code BufferedImageOp/RasterOp} implements basic
* Floyd-Steinberg error-diffusion algorithm for dithering.
* <P/>
* <p>
* The weights used are 7/16, 3/16, 5/16 and 1/16, distributed like this:
* <!-- - -
* | |x|7|
* - - - -
* |3|5|1|
* - - -->
* <P/>
* <TABLE border="1" cellpadding="4" cellspacing="0">
* <TR><TD bgcolor="#000000">&nbsp;</TD><TD class="TableHeadingColor"
* align="center">X</TD><TD>7/16</TD></TR>
* <TR><TD>3/16</TD><TD>5/16</TD><TD>1/16</TD></TR>
* </TABLE>
* <P/>
* </p>
* <table border="1" cellpadding="4" cellspacing="0">
* <caption>Floyd-Steinberg error-diffusion weights</caption>
* <tr><td bgcolor="#000000">&nbsp;</td><td class="TableHeadingColor"
* align="center">x</td><td>7/16</td></tr>
* <tr><td>3/16</td><td>5/16</td><td>1/16</td></tr>
* </table>
* <p>
* See <A href="http://www.awprofessional.com/bookstore/product.asp?isbn=0201848406&rl=1">Computer Graphics (Foley et al.)</a>
* for more information.
* </p>
*
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
* @author last modified by $Author: haku $
@@ -43,10 +43,11 @@ public final class GraphicsUtil {
/**
* Enables anti-aliasing in the {@code Graphics} object.
* <p/>
* <p>
* Anti-aliasing is enabled by casting to {@code Graphics2D} and setting
* the rendering hint {@code RenderingHints.KEY_ANTIALIASING} to
* {@code RenderingHints.VALUE_ANTIALIAS_ON}.
* </p>
*
* @param pGraphics the graphics object
* @throws ClassCastException if {@code pGraphics} is not an instance of
@@ -62,10 +63,11 @@ public final class GraphicsUtil {
/**
* Sets the alpha in the {@code Graphics} object.
* <p/>
* <p>
* Alpha is set by casting to {@code Graphics2D} and setting the composite
* to the rule {@code AlphaComposite.SRC_OVER} multiplied by the given
* alpha.
* </p>
*
* @param pGraphics the graphics object
* @param pAlpha the alpha level, {@code alpha} must be a floating point
@@ -34,8 +34,9 @@ import java.awt.image.RGBImageFilter;
/**
* This class can convert a color image to grayscale.
* <P/>
* <p>
* Uses ITU standard conversion: (222 * Red + 707 * Green + 71 * Blue) / 1000.
* </p>
*
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
* @author last modified by $Author: haku $
@@ -64,7 +65,7 @@ public class GrayFilter extends RGBImageFilter {
* pLow and pHigh.
*
* @param pLow float in the range 0..1
* @param pHigh float in the range 0..1 and >= pLow
* @param pHigh float in the range 0..1 and &gt;= pLow
*/
public GrayFilter(float pLow, float pHigh) {
if (pLow > pHigh) {
@@ -94,7 +95,7 @@ public class GrayFilter extends RGBImageFilter {
* range between pLow and pHigh.
*
* @param pLow integer in the range 0..255
* @param pHigh inteeger in the range 0..255 and >= pLow
* @param pHigh integer in the range 0..255 and &gt;= pLow
*/
public GrayFilter(int pLow, int pHigh) {
this(pLow / 255f, pHigh / 255f);
@@ -162,11 +162,12 @@ public final class ImageUtil {
/**
* The sharpen kernel. Uses the following 3 by 3 matrix:
* <TABLE border="1" cellspacing="0">
* <TR><TD>0.0</TD><TD>-0.3</TD><TD>0.0</TD></TR>
* <TR><TD>-0.3</TD><TD>2.2</TD><TD>-0.3</TD></TR>
* <TR><TD>0.0</TD><TD>-0.3</TD><TD>0.0</TD></TR>
* </TABLE>
* <table border="1" cellspacing="0">
* <caption>Sharpen Kernel Matrix</caption>
* <tr><td>0.0</td><td>-0.3</td><td>0.0</td></tr>
* <tr><td>-0.3</td><td>2.2</td><td>-0.3</td></tr>
* <tr><td>0.0</td><td>-0.3</td><td>0.0</td></tr>
* </table>
*/
private static final Kernel SHARPEN_KERNEL = new Kernel(3, 3, SHARPEN_MATRIX);
@@ -208,9 +209,10 @@ public final class ImageUtil {
* Converts the {@code RenderedImage} to a {@code BufferedImage}.
* The new image will have the <em>same</em> {@code ColorModel},
* {@code Raster} and properties as the original image, if possible.
* <p/>
* <p>
* If the image is already a {@code BufferedImage}, it is simply returned
* and no conversion takes place.
* </p>
*
* @param pOriginal the image to convert.
*
@@ -262,9 +264,10 @@ public final class ImageUtil {
/**
* Converts the {@code RenderedImage} to a {@code BufferedImage} of the
* given type.
* <p/>
* <p>
* If the image is already a {@code BufferedImage} of the given type, it
* is simply returned and no conversion takes place.
* </p>
*
* @param pOriginal the image to convert.
* @param pType the type of buffered image
@@ -308,12 +311,14 @@ public final class ImageUtil {
* Converts the {@code BufferedImage} to a {@code BufferedImage} of the
* given type. The new image will have the same {@code ColorModel},
* {@code Raster} and properties as the original image, if possible.
* <p/>
* <p>
* If the image is already a {@code BufferedImage} of the given type, it
* is simply returned and no conversion takes place.
* <p/>
* </p>
* <p>
* This method simply invokes
* {@link #toBuffered(RenderedImage,int) toBuffered((RenderedImage) pOriginal, pType)}.
* </p>
*
* @param pOriginal the image to convert.
* @param pType the type of buffered image
@@ -333,9 +338,10 @@ public final class ImageUtil {
* Converts the {@code Image} to a {@code BufferedImage}.
* The new image will have the same {@code ColorModel}, {@code Raster} and
* properties as the original image, if possible.
* <p/>
* <p>
* If the image is already a {@code BufferedImage}, it is simply returned
* and no conversion takes place.
* </p>
*
* @param pOriginal the image to convert.
*
@@ -389,19 +395,22 @@ public final class ImageUtil {
/**
* Creates a {@code WritableRaster} for the given {@code ColorModel} and
* pixel data.
* <p/>
* <p>
* This method is optimized for the most common cases of {@code ColorModel}
* and pixel data combinations. The raster's backing {@code DataBuffer} is
* created directly from the pixel data, as this is faster and more
* resource-friendly than using
* {@code ColorModel.createCompatibleWritableRaster(w, h)}.
* <p/>
* </p>
* <p>
* For uncommon combinations, the method will fallback to using
* {@code ColorModel.createCompatibleWritableRaster(w, h)} and
* {@code WritableRaster.setDataElements(w, h, pixels)}
* <p/>
* </p>
* <p>
* Note that the {@code ColorModel} and pixel data are <em>not</em> cloned
* (in most cases).
* </p>
*
* @param pWidth the requested raster width
* @param pHeight the requested raster height
@@ -543,9 +552,10 @@ public final class ImageUtil {
* Converts the {@code Image} to a {@code BufferedImage} of the given type.
* The new image will have the same {@code ColorModel}, {@code Raster} and
* properties as the original image, if possible.
* <p/>
* <p>
* If the image is already a {@code BufferedImage} of the given type, it
* is simply returned and no conversion takes place.
* </p>
*
* @param pOriginal the image to convert.
* @param pType the type of buffered image
@@ -656,9 +666,10 @@ public final class ImageUtil {
* Rotates the image 90 degrees, clockwise (aka "rotate right"),
* counter-clockwise (aka "rotate left") or 180 degrees, depending on the
* {@code pDirection} argument.
* <p/>
* <p>
* The new image will be completely covered with pixels from the source
* image.
* </p>
*
* @param pImage the source image.
* @param pDirection the direction, must be either {@link #ROTATE_90_CW},
@@ -1067,14 +1078,16 @@ public final class ImageUtil {
/**
* Sharpens an image using a convolution matrix.
* The sharpen kernel used, is defined by the following 3 by 3 matrix:
* <TABLE border="1" cellspacing="0">
* <TR><TD>0.0</TD><TD>-0.3</TD><TD>0.0</TD></TR>
* <TR><TD>-0.3</TD><TD>2.2</TD><TD>-0.3</TD></TR>
* <TR><TD>0.0</TD><TD>-0.3</TD><TD>0.0</TD></TR>
* </TABLE>
* <P/>
* <table border="1" cellspacing="0">
* <caption>Sharpen Kernel Matrix</caption>
* <tr><td>0.0</td><td>-0.3</td><td>0.0</td></tr>
* <tr><td>-0.3</td><td>2.2</td><td>-0.3</td></tr>
* <tr><td>0.0</td><td>-0.3</td><td>0.0</td></tr>
* </table>
* <p>
* This is the same result returned as
* {@code sharpen(pOriginal, 0.3f)}.
* </p>
*
* @param pOriginal the BufferedImage to sharpen
*
@@ -1087,13 +1100,14 @@ public final class ImageUtil {
/**
* Sharpens an image using a convolution matrix.
* The sharpen kernel used, is defined by the following 3 by 3 matrix:
* <TABLE border="1" cellspacing="0">
* <TR><TD>0.0</TD><TD>-{@code pAmount}</TD><TD>0.0</TD></TR>
* <TR><TD>-{@code pAmount}</TD>
* <TD>4.0 * {@code pAmount} + 1.0</TD>
* <TD>-{@code pAmount}</TD></TR>
* <TR><TD>0.0</TD><TD>-{@code pAmount}</TD><TD>0.0</TD></TR>
* </TABLE>
* <table border="1" cellspacing="0">
* <caption>Sharpen Kernel Matrix</caption>
* <tr><td>0.0</td><td>-{@code pAmount}</td><td>0.0</td></tr>
* <tr><td>-{@code pAmount}</td>
* <td>4.0 * {@code pAmount} + 1.0</td>
* <td>-{@code pAmount}</td></tr>
* <tr><td>0.0</td><td>-{@code pAmount}</td><td>0.0</td></tr>
* </table>
*
* @param pOriginal the BufferedImage to sharpen
* @param pAmount the amount of sharpening
@@ -101,32 +101,35 @@ import java.util.List;
* This class implements an adaptive palette generator to reduce images
* to a variable number of colors.
* It can also render images into fixed color pallettes.
* <p/>
* <p>
* Support for the default JVM (ordered/pattern) dither, Floyd-Steinberg like
* error-diffusion and no dither, controlled by the hints
* {@link #DITHER_DIFFUSION},
* {@link #DITHER_NONE} and
* {@link #DITHER_DEFAULT}.
* <p/>
* </p>
* <p>
* Color selection speed/accuracy can be controlled using the hints
* {@link #COLOR_SELECTION_FAST},
* {@link #COLOR_SELECTION_QUALITY} and
* {@link #COLOR_SELECTION_DEFAULT}.
* <p/>
* </p>
* <p>
* Transparency support can be controlled using the hints
* {@link #TRANSPARENCY_OPAQUE},
* {@link #TRANSPARENCY_BITMASK} and
* {@link #TRANSPARENCY_TRANSLUCENT}.
* <p/>
* <HR/>
* <p/>
* <PRE>
* </p>
* <hr>
* <p>
* <pre>
* This product includes software developed by the Apache Software Foundation.
* <p/>
*
* This software consists of voluntary contributions made by many individuals
* on behalf of the Apache Software Foundation. For more information on the
* Apache Software Foundation, please see <A href="http://www.apache.org/">http://www.apache.org/</A>
* </PRE>
* </pre>
* </p>
*
* @author <A href="mailto:deweese@apache.org">Thomas DeWeese</A>
* @author <A href="mailto:jun@oop-reserch.com">Jun Inamori</A>
@@ -825,8 +828,9 @@ class IndexImage {
* {@code TYPE_INT_ARGB}) to an indexed image. Generating an adaptive
* palette (8 bit) from the color data in the image, and uses default
* dither.
* <p/>
* <p>
* The image returned is a new image, the input image is not modified.
* </p>
*
* @param pImage the BufferedImage to index and get color information from.
* @return the indexed BufferedImage. The image will be of type
@@ -870,8 +874,9 @@ class IndexImage {
* adaptive palette (8 bit) from the given palette image.
* Dithering, transparency and color selection is controlled with the
* {@code pHints}parameter.
* <p/>
* <p>
* The image returned is a new image, the input image is not modified.
* </p>
*
* @param pImage the BufferedImage to index
* @param pPalette the Image to read color information from
@@ -904,9 +909,10 @@ class IndexImage {
* {@code TYPE_INT_ARGB}) to an indexed image. Generating an adaptive
* palette with the given number of colors.
* Dithering, transparency and color selection is controlled with the
* {@code pHints}parameter.
* <p/>
* {@code pHints} parameter.
* <p>
* The image returned is a new image, the input image is not modified.
* </p>
*
* @param pImage the BufferedImage to index
* @param pNumberOfColors the number of colors for the image
@@ -952,8 +958,9 @@ class IndexImage {
* {@code IndexColorModel}'s palette.
* Dithering, transparency and color selection is controlled with the
* {@code pHints} parameter.
* <p/>
* <p>
* The image returned is a new image, the input image is not modified.
* </p>
*
* @param pImage the BufferedImage to index
* @param pColors an {@code IndexColorModel} containing the color information
@@ -1069,8 +1076,9 @@ class IndexImage {
* palette with the given number of colors.
* Dithering, transparency and color selection is controlled with the
* {@code pHints}parameter.
* <p/>
* <p>
* The image returned is a new image, the input image is not modified.
* </p>
*
* @param pImage the BufferedImage to index
* @param pNumberOfColors the number of colors for the image
@@ -1099,8 +1107,9 @@ class IndexImage {
* {@code IndexColorModel}'s palette.
* Dithering, transparency and color selection is controlled with the
* {@code pHints}parameter.
* <p/>
* <p>
* The image returned is a new image, the input image is not modified.
* </p>
*
* @param pImage the BufferedImage to index
* @param pColors an {@code IndexColorModel} containing the color information
@@ -1130,8 +1139,9 @@ class IndexImage {
* adaptive palette (8 bit) from the given palette image.
* Dithering, transparency and color selection is controlled with the
* {@code pHints}parameter.
* <p/>
* <p>
* The image returned is a new image, the input image is not modified.
* </p>
*
* @param pImage the BufferedImage to index
* @param pPalette the Image to read color information from
@@ -33,9 +33,10 @@ package com.twelvemonkeys.image;
/**
* Inverse Colormap to provide efficient lookup of any given input color
* to the closest match to the given color map.
* <p/>
* <p>
* Based on "Efficient Inverse Color Map Computation" by Spencer W. Thomas
* in "Graphics Gems Volume II"
* in "Graphics Gems Volume II".
* </p>
*
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
* @author Robin Luiten (Java port)
@@ -41,11 +41,11 @@ import java.awt.image.BufferedImageOp;
* This class accelerates certain graphics operations, using
* JMagick and ImageMagick, if available.
* If those libraries are not installed, this class silently does nothing.
* <p/>
* <p>
* Set the system property {@code "com.twelvemonkeys.image.accel"} to
* {@code false}, to disable, even if JMagick is installed.
* Set the system property {@code "com.twelvemonkeys.image.magick.debug"} to
* <p/>
* </p>
*
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-core/src/main/java/com/twelvemonkeys/image/MagickAccelerator.java#3 $
@@ -44,10 +44,11 @@ import java.awt.image.*;
/**
* Utility for converting JMagick {@code MagickImage}s to standard Java
* {@code BufferedImage}s and back.
* <p/>
* <p>
* <em>NOTE: This class is considered an implementation detail and not part of
* the public API. This class is subject to change without further notice.
* You have been warned. :-)</em>
* </p>
*
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-core/src/main/java/com/twelvemonkeys/image/MagickUtil.java#4 $
@@ -100,8 +101,9 @@ public final class MagickUtil {
/**
* Converts a {@code MagickImage} to a {@code BufferedImage}.
* <p/>
* <p>
* The conversion depends on {@code pImage}'s {@code ImageType}:
* </p>
* <dl>
* <dt>{@code ImageType.BilevelType}</dt>
* <dd>{@code BufferedImage} of type {@code TYPE_BYTE_BINARY}</dd>
@@ -113,15 +115,16 @@ public final class MagickUtil {
*
* <dt>{@code ImageType.PaletteType}</dt>
* <dd>{@code BufferedImage} of type {@code TYPE_BYTE_BINARY} (for images
* with a palette of <= 16 colors) or {@code TYPE_BYTE_INDEXED}</dd>
* with a palette of &lt;= 16 colors) or {@code TYPE_BYTE_INDEXED}</dd>
* <dt>{@code ImageType.PaletteMatteType}</dt>
* <dd>{@code BufferedImage} of type {@code TYPE_BYTE_BINARY} (for images
* with a palette of <= 16 colors) or {@code TYPE_BYTE_INDEXED}</dd>
* with a palette of &lt;= 16 colors) or {@code TYPE_BYTE_INDEXED}</dd>
*
* <dt>{@code ImageType.TrueColorType}</dt>
* <dd>{@code BufferedImage} of type {@code TYPE_3BYTE_BGR}</dd>
* <dt>{@code ImageType.TrueColorPaletteType}</dt>
* <dd>{@code BufferedImage} of type {@code TYPE_4BYTE_ABGR}</dd>
* </dl>
*
* @param pImage the original {@code MagickImage}
* @return a new {@code BufferedImage}
@@ -191,24 +194,26 @@ public final class MagickUtil {
/**
* Converts a {@code BufferedImage} to a {@code MagickImage}.
* <p/>
* <p>
* The conversion depends on {@code pImage}'s {@code ColorModel}:
* </p>
* <dl>
* <dt>{@code IndexColorModel} with 1 bit b/w</dt>
* <dd>{@code MagickImage} of type {@code ImageType.BilevelType}</dd>
* <dt>{@code IndexColorModel} &gt; 1 bit,</dt>
* <dd>{@code MagickImage} of type {@code ImageType.PaletteType}
* or {@code MagickImage} of type {@code ImageType.PaletteMatteType}
* depending on <tt>ColorModel.getAlpha()</dd>
* depending on <tt>ColorModel.getAlpha()</tt></dd>
*
* <dt>{@code ColorModel.getColorSpace().getType() == ColorSpace.TYPE_GRAY}</dt>
* <dd>{@code MagickImage} of type {@code ImageType.GrayscaleType}
* or {@code MagickImage} of type {@code ImageType.GrayscaleMatteType}
* depending on <tt>ColorModel.getAlpha()</dd>
* depending on <tt>ColorModel.getAlpha()</tt></dd>
*
* <dt>{@code ColorModel.getColorSpace().getType() == ColorSpace.TYPE_RGB}</dt>
* <dd>{@code MagickImage} of type {@code ImageType.TrueColorType}
* or {@code MagickImage} of type {@code ImageType.TrueColorPaletteType}</dd>
* </dl>
*
* @param pImage the original {@code BufferedImage}
* @return a new {@code MagickImage}
@@ -432,7 +437,7 @@ public final class MagickUtil {
/**
* Converts a palette-based {@code MagickImage} to a
* {@code BufferedImage}, of type {@code TYPE_BYTE_BINARY} (for images
* with a palette of <= 16 colors) or {@code TYPE_BYTE_INDEXED}.
* with a palette of &lt;= 16 colors) or {@code TYPE_BYTE_INDEXED}.
*
* @param pImage the original {@code MagickImage}
* @param pAlpha keep alpha channel
@@ -67,39 +67,42 @@ import java.awt.image.*;
* constructor, either using the
* <a href="#field_summary">filter type constants</a>, or one of the
* {@code RendereingHints}.
* <p/>
* <p>
* For fastest results, use {@link #FILTER_POINT} or {@link #FILTER_BOX}.
* In most cases, {@link #FILTER_TRIANGLE} will produce acceptable results, while
* being relatively fast.
* For higher quality output, use more sophisticated interpolation algorithms,
* like {@link #FILTER_MITCHELL} or {@link #FILTER_LANCZOS}.
* <p/>
* </p>
* <p>
* Example:
* </p>
* <blockquote><pre>
* BufferedImage image;
* <p/>
*
* //...
* <p/>
*
* ResampleOp resampler = new ResampleOp(100, 100, ResampleOp.FILTER_TRIANGLE);
* BufferedImage thumbnail = resampler.filter(image, null);
* </pre></blockquote>
* <p/>
* If your imput image is very large, it's possible to first resample using the
* <p>
* If your input image is very large, it's possible to first resample using the
* very fast {@code FILTER_POINT} algorithm, then resample to the wanted size,
* using a higher quality algorithm:
* </p>
* <blockquote><pre>
* BufferedImage verylLarge;
* <p/>
*
* //...
* <p/>
*
* int w = 300;
* int h = 200;
* <p/>
*
* BufferedImage temp = new ResampleOp(w * 2, h * 2, FILTER_POINT).filter(verylLarge, null);
* <p/>
*
* BufferedImage scaled = new ResampleOp(w, h).filter(temp, null);
* </pre></blockquote>
* <p/>
* <p>
* For maximum performance, this class will use native code, through
* <a href="http://www.yeo.id.au/jmagick/">JMagick</a>, when available.
* Otherwise, the class will silently fall back to pure Java mode.
@@ -107,7 +110,8 @@ import java.awt.image.*;
* {@code com.twelvemonkeys.image.accel} to {@code false}.
* To allow debug of the native code, set the system property
* {@code com.twelvemonkeys.image.magick.debug} to {@code true}.
* <p/>
* </p>
* <p>
* This {@code BufferedImageOp} is based on C example code found in
* <a href="http://www.acm.org/tog/GraphicsGems/">Graphics Gems III</a>,
* Filtered Image Rescaling, by Dale Schumacher (with additional improvments by
@@ -116,10 +120,12 @@ import java.awt.image.*;
* <a href="http://www.imagemagick.org/">ImageMagick</a> and
* Marco Schmidt's <a href="http://schmidt.devlib.org/jiu/">Java Imaging Utilities</a>
* (which are also adaptions of the same original code from Graphics Gems III).
* <p/>
* </p>
* <p>
* For a description of the various interpolation algorithms, see
* <em>General Filtered Image Rescaling</em> in <em>Graphics Gems III</em>,
* Academic Press, 1994.
* </p>
*
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
* @author last modified by $Author: haku $
@@ -361,13 +367,14 @@ public class ResampleOp implements BufferedImageOp/* TODO: RasterOp */ {
* Creates a {@code ResampleOp} that will resample input images to the
* given width and height, using the interpolation filter specified by
* the given hints.
* <p>
* If using {@code RenderingHints}, the hints are mapped as follows:
* </p>
* <ul>
* <li>{@code KEY_RESAMPLE_INTERPOLATION} takes precedence over any
* standard {@code java.awt} hints, and dictates interpolation
* directly, see
* <a href="#field_summary">{@code RenderingHints} constants</a>.</li>
* <p/>
* <li>{@code KEY_INTERPOLATION} takes precedence over other hints.
* <ul>
* <li>{@link RenderingHints#VALUE_INTERPOLATION_NEAREST_NEIGHBOR} specifies
@@ -378,7 +385,6 @@ public class ResampleOp implements BufferedImageOp/* TODO: RasterOp */ {
* {@code FILTER_QUADRATIC}</li>
* </ul>
* </li>
* <p/>
* <li>{@code KEY_RENDERING} or {@code KEY_COLOR_RENDERING}
* <ul>
* <li>{@link RenderingHints#VALUE_RENDER_SPEED} specifies
@@ -388,7 +394,9 @@ public class ResampleOp implements BufferedImageOp/* TODO: RasterOp */ {
* </ul>
* </li>
* </ul>
* <p>
* Other hints have no effect on this filter.
* </p>
*
* @param width width of the re-sampled image
* @param height height of the re-sampled image
@@ -34,9 +34,10 @@ import java.awt.image.ReplicateScaleFilter;
/**
* An {@code ImageFilter} class for subsampling images.
* <p/>
* <p>
* It is meant to be used in conjunction with a {@code FilteredImageSource}
* object to produce subsampled versions of existing images.
* </p>
*
* @see java.awt.image.FilteredImageSource
*
@@ -30,8 +30,9 @@
/**
* Classes for image manipulation.
* <p/>
* <p>
* See the class {@link com.twelvemonkeys.image.ImageUtil}.
* </p>
*
* @version 1.0
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
+1 -1
View File
@@ -4,7 +4,7 @@
<parent>
<groupId>com.twelvemonkeys.common</groupId>
<artifactId>common</artifactId>
<version>3.4</version>
<version>3.4.4-SNAPSHOT</version>
</parent>
<artifactId>common-io</artifactId>
<packaging>jar</packaging>
@@ -186,7 +186,7 @@ abstract class AbstractCachedSeekableStream extends SeekableInputStream {
}
protected void closeImpl() throws IOException {
cache.flush(position);
cache.close();
cache = null;
stream.close();
}
@@ -198,12 +198,12 @@ abstract class AbstractCachedSeekableStream extends SeekableInputStream {
* @author last modified by $Author: haku $
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-core/src/main/java/com/twelvemonkeys/io/AbstractCachedSeekableStream.java#2 $
*/
public static abstract class StreamCache {
static abstract class StreamCache {
/**
* Creates a {@code StreamCache}.
*/
protected StreamCache() {
StreamCache() {
}
/**
@@ -218,9 +218,10 @@ abstract class AbstractCachedSeekableStream extends SeekableInputStream {
/**
* Writes a series of bytes at the current read/write position. The read/write position will be increased by
* {@code pLength}.
* <p/>
* <p>
* This implementation invokes {@link #write(int)} {@code pLength} times.
* Subclasses may override this method for performance.
* </p>
*
* @param pBuffer the bytes to write.
* @param pOffset the starting offset into the buffer.
@@ -246,9 +247,10 @@ abstract class AbstractCachedSeekableStream extends SeekableInputStream {
/**
* Writes a series of bytes at the current read/write position. The read/write position will be increased by
* {@code pLength}.
* <p/>
* <p>
* This implementation invokes {@link #read()} {@code pLength} times.
* Subclasses may override this method for performance.
* </p>
*
* @param pBuffer the bytes to write
* @param pOffset the starting offset into the buffer.
@@ -283,12 +285,14 @@ abstract class AbstractCachedSeekableStream extends SeekableInputStream {
/**
* Optionally flushes any data prior to the given position.
* <p/>
* <p>
* Attempting to perform a seek operation, and/or a read or write operation to a position equal to or before
* the flushed position may result in exceptions or undefined behaviour.
* <p/>
* </p>
* <p>
* Subclasses should override this method for performance reasons, to avoid holding on to unnecessary resources.
* This implementation does nothing.
* </p>
*
* @param pPosition the last position to flush.
*/
@@ -303,5 +307,7 @@ abstract class AbstractCachedSeekableStream extends SeekableInputStream {
* @throws IOException if the position can't be determined because of a problem in the cache backing mechanism.
*/
abstract long getPosition() throws IOException;
abstract void close() throws IOException;
}
}
@@ -40,7 +40,6 @@ import java.util.List;
/**
* A Reader implementation that can read from multiple sources.
* <p/>
*
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
* @author last modified by $Author: haku $
@@ -34,7 +34,6 @@ import java.io.StringReader;
/**
* EmptyReader
* <p/>
*
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
* @author last modified by $Author: haku $
@@ -38,7 +38,6 @@ import java.io.OutputStream;
/**
* An unsynchronized {@code ByteArrayOutputStream} implementation. This version
* also has a constructor that lets you create a stream with initial content.
* <p/>
*
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
* @version $Id: FastByteArrayOutputStream.java#2 $
@@ -60,8 +59,9 @@ public final class FastByteArrayOutputStream extends ByteArrayOutputStream {
/**
* Creates a {@code ByteArrayOutputStream} with the given initial content.
* <p/>
* <p>
* Note that the buffer is not cloned, for maximum performance.
* </p>
*
* @param pBuffer initial buffer
*/
@@ -123,10 +123,11 @@ public final class FastByteArrayOutputStream extends ByteArrayOutputStream {
* Creates a {@code ByteArrayInputStream} that reads directly from this
* {@code FastByteArrayOutputStream}'s byte buffer.
* The buffer is not cloned, for maximum performance.
* <p/>
* <p>
* Note that care needs to be taken to avoid writes to
* this output stream after the input stream is created.
* Failing to do so, may result in unpredictable behaviour.
* </p>
*
* @return a new {@code ByteArrayInputStream}, reading from this stream's buffer.
*/
@@ -36,8 +36,9 @@ import java.io.*;
/**
* A {@code SeekableInputStream} implementation that caches data in a temporary {@code File}.
* <p/>
* <p>
* Temporary files are created as specified in {@link File#createTempFile(String, String, java.io.File)}.
* </p>
*
* @see MemoryCacheSeekableStream
* @see FileSeekableStream
@@ -124,7 +125,9 @@ public final class FileCacheSeekableStream extends AbstractCachedSeekableStream
@Override
protected void closeImpl() throws IOException {
// TODO: Close cache file
super.closeImpl();
buffer = null;
}
@@ -194,39 +197,45 @@ public final class FileCacheSeekableStream extends AbstractCachedSeekableStream
return length;
}
// TODO: We need to close the cache file!!! Otherwise we are leaking file descriptors
final static class FileCache extends StreamCache {
private RandomAccessFile mCacheFile;
private RandomAccessFile cacheFile;
public FileCache(final File pFile) throws FileNotFoundException {
Validate.notNull(pFile, "file");
mCacheFile = new RandomAccessFile(pFile, "rw");
cacheFile = new RandomAccessFile(pFile, "rw");
}
public void write(final int pByte) throws IOException {
mCacheFile.write(pByte);
cacheFile.write(pByte);
}
@Override
public void write(final byte[] pBuffer, final int pOffset, final int pLength) throws IOException {
mCacheFile.write(pBuffer, pOffset, pLength);
cacheFile.write(pBuffer, pOffset, pLength);
}
public int read() throws IOException {
return mCacheFile.read();
return cacheFile.read();
}
@Override
public int read(final byte[] pBuffer, final int pOffset, final int pLength) throws IOException {
return mCacheFile.read(pBuffer, pOffset, pLength);
return cacheFile.read(pBuffer, pOffset, pLength);
}
public void seek(final long pPosition) throws IOException {
mCacheFile.seek(pPosition);
cacheFile.seek(pPosition);
}
public long getPosition() throws IOException {
return mCacheFile.getFilePointer();
return cacheFile.getFilePointer();
}
@Override
void close() throws IOException {
cacheFile.close();
}
}
}
@@ -37,7 +37,7 @@ import java.io.RandomAccessFile;
/**
* A {@code SeekableInputStream} implementation that uses random access directly to a {@code File}.
* <p/>
* @see FileCacheSeekableStream
* @see MemoryCacheSeekableStream
* @see RandomAccessFile
@@ -37,7 +37,6 @@ import java.io.InputStreamReader;
/**
* FileSystem
* <p/>
*
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
* @version $Id: FileSystem.java#1 $
@@ -171,7 +171,6 @@ public final class FileUtil {
* {@code false}. In all other cases, an
* {@code IOExceptio}n is thrown, and the method does not return.
* @throws IOException if an i/o error occurs during copy
* @todo Test copyDir functionality!
*/
public static boolean copy(File pFromFile, File pToFile, boolean pOverWrite) throws IOException {
// Copy all directory structure
@@ -41,18 +41,23 @@ import java.io.FilenameFilter;
* The mask is given as a well-known DOS filename format, with '*' and '?' as
* wildcards.
* All other characters counts as ordinary characters.
* <p/>
* <p>
* The file name masks are used as a filter input and is given to the class via
* the string array property:<br>
* <dd>{@code filenameMasksForInclusion} - Filename mask for exclusion of
* files (default if both properties are defined)
* <dd>{@code filenameMasksForExclusion} - Filename mask for exclusion of
* files.
* <p/>
* the string array property:
* </p>
* <dl>
* <dt>{@code filenameMasksForInclusion}</dt>
* <dd>Filename mask for exclusion of
* files (default if both properties are defined).</dd>
* <dt>{@code filenameMasksForExclusion}</dt>
* <dd>Filename mask for exclusion of files.</dd>
* </dl>
* <p>
* A recommended way of doing this is by referencing to the component which uses
* this class for file listing. In this way all properties are set in the same
* component and this utility component is kept in the background with only
* initial configuration necessary.
* </p>
*
* @author <a href="mailto:eirik.torske@iconmedialab.no">Eirik Torske</a>
* @see File#list(java.io.FilenameFilter) java.io.File.list
@@ -48,18 +48,19 @@ import java.io.*;
* A little endian input stream reads two's complement,
* little endian integers, floating point numbers, and characters
* and returns them as Java primitive types.
* <p/>
* <p>
* The standard {@code java.io.DataInputStream} class
* which this class imitates reads big endian quantities.
* <p/>
* </p>
* <p>
* <em>Warning:
* <!-- Beware of little indians! -->
* The {@code DataInput} and {@code DataOutput} interfaces
* specifies big endian byte order in their documentation.
* This means that this class is, strictly speaking, not a proper
* implementation. However, I don't see a reason for the these interfaces to
* specify the byte order of their underlying representations.
* </em>
* </p>
*
* @see com.twelvemonkeys.io.LittleEndianRandomAccessFile
* @see java.io.DataInputStream
@@ -381,12 +382,10 @@ public class LittleEndianDataInputStream extends FilterInputStream implements Da
}
/**
* See the general contract of the {@code readFully}
* method of {@code DataInput}.
* <p/>
* Bytes
* for this operation are read from the contained
* input stream.
* See the general contract of the {@code readFully} method of {@code DataInput}.
* <p>
* Bytes for this operation are read from the contained input stream.
* </p>
*
* @param pBytes the buffer into which the data is read.
* @throws EOFException if this input stream reaches the end before
@@ -399,12 +398,10 @@ public class LittleEndianDataInputStream extends FilterInputStream implements Da
}
/**
* See the general contract of the {@code readFully}
* method of {@code DataInput}.
* <p/>
* Bytes
* for this operation are read from the contained
* input stream.
* See the general contract of the {@code readFully} method of {@code DataInput}.
* <p>
* Bytes for this operation are read from the contained input stream.
* </p>
*
* @param pBytes the buffer into which the data is read.
* @param pOffset the start offset of the data.
@@ -444,7 +441,6 @@ public class LittleEndianDataInputStream extends FilterInputStream implements Da
* @exception IOException if an I/O error occurs.
* @see java.io.BufferedReader#readLine()
* @see java.io.DataInputStream#readLine()
* @noinspection deprecation
*/
public String readLine() throws IOException {
DataInputStream ds = new DataInputStream(in);
@@ -47,18 +47,19 @@ import java.io.*;
/**
* A little endian output stream writes primitive Java numbers
* and characters to an output stream in a little endian format.
* <p/>
* <p>
* The standard {@code java.io.DataOutputStream} class which this class
* imitates uses big endian integers.
* <p/>
* </p>
* <p>
* <em>Warning:
* <!-- Beware of little indians! -->
* The {@code DataInput} and {@code DataOutput} interfaces
* specifies big endian byte order in their documentation.
* This means that this class is, strictly speaking, not a proper
* implementation. However, I don't see a reason for the these interfaces to
* specify the byte order of their underlying representations.
* </em>
* <p>
*
* @see com.twelvemonkeys.io.LittleEndianRandomAccessFile
* @see java.io.DataOutputStream
@@ -36,15 +36,15 @@ import java.nio.channels.FileChannel;
/**
* A replacement for {@link java.io.RandomAccessFile} that is capable of reading
* and writing data in little endian byte order.
* <p/>
* <p>
* <em>Warning:
* <!-- Beware of little indians! -->
* The {@code DataInput} and {@code DataOutput} interfaces
* specifies big endian byte order in their documentation.
* This means that this class is, strictly speaking, not a proper
* implementation. However, I don't see a reason for the these interfaces to
* specify the byte order of their underlying representations.
* </em>
* </p>
*
* @see com.twelvemonkeys.io.LittleEndianDataInputStream
* @see com.twelvemonkeys.io.LittleEndianDataOutputStream
@@ -37,7 +37,6 @@ import java.util.List;
/**
* A {@code SeekableInputStream} implementation that caches data in memory.
* <p/>
*
* @see FileCacheSeekableStream
*
@@ -67,7 +66,7 @@ public final class MemoryCacheSeekableStream extends AbstractCachedSeekableStrea
final static class MemoryCache extends StreamCache {
final static int BLOCK_SIZE = 1 << 13;
private final List<byte[]> cache = new ArrayList<byte[]>();
private final List<byte[]> cache = new ArrayList<>();
private long length;
private long position;
private long start;
@@ -186,6 +185,11 @@ public final class MemoryCacheSeekableStream extends AbstractCachedSeekableStrea
start = pPosition;
}
@Override
void close() throws IOException {
cache.clear();
}
public long getPosition() {
return position;
}
@@ -35,7 +35,6 @@ import java.io.InputStream;
/**
* An {@code InputStream} that contains no bytes.
* <p/>
*
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-core/src/main/java/com/twelvemonkeys/io/NullInputStream.java#2 $
@@ -35,7 +35,6 @@ import java.io.OutputStream;
/**
* An {@code OutputStream} implementation that works as a sink.
* <p/>
*
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-core/src/main/java/com/twelvemonkeys/io/NullOutputStream.java#2 $
@@ -38,7 +38,6 @@ import java.io.IOException;
/**
* A data stream that is both readable and writable, much like a
* {@code RandomAccessFile}, except it may be backed by something other than a file.
* <p/>
*
* @see java.io.RandomAccessFile
*
@@ -114,8 +113,9 @@ public abstract class RandomAccessStream implements Seekable, DataInput, DataOut
/**
* Returns an input view of this {@code RandomAccessStream}.
* Invoking this method several times, will return the same object.
* <p/>
* <p>
* <em>Note that read access is NOT synchronized.</em>
* </p>
*
* @return a {@code SeekableInputStream} reading from this stream
*/
@@ -129,8 +129,9 @@ public abstract class RandomAccessStream implements Seekable, DataInput, DataOut
/**
* Returns an output view of this {@code RandomAccessStream}.
* Invoking this method several times, will return the same object.
* <p/>
* <p>
* <em>Note that write access is NOT synchronized.</em>
* </p>
*
* @return a {@code SeekableOutputStream} writing to this stream
*/
@@ -34,7 +34,7 @@ import java.io.IOException;
/**
* Interface for seekable streams.
* <p/>
*
* @see SeekableInputStream
* @see SeekableOutputStream
*
@@ -55,12 +55,14 @@ public interface Seekable {
/**
* Sets the current stream position to the desired location.
* The next read will occur at this location.
* <p/>
* <p>
* An {@code IndexOutOfBoundsException} will be thrown if pPosition is smaller
* than the flushed position (as returned by {@link #getFlushedPosition()}).
* <p/>
* </p>
* <p>
* It is legal to seek past the end of the file; an {@code EOFException}
* will be thrown only if a read is performed.
* </p>
*
* @param pPosition a long containing the desired file pointer position.
*
@@ -76,25 +78,29 @@ public interface Seekable {
* Unlike a standard {@code InputStream}, all {@code Seekable}
* streams upport marking. Additionally, calls to {@code mark} and
* {@code reset} may be nested arbitrarily.
* <p/>
* <p>
* Unlike the {@code mark} methods declared by the {@code Reader} or
* {@code InputStream}
* interfaces, no {@code readLimit} parameter is used. An arbitrary amount
* of data may be read following the call to {@code mark}.
* </p>
*/
void mark();
/**
* Returns the file pointer to its previous position,
* at the time of the most recent unmatched call to mark.
* <p/>
* <p>
* Calls to reset without a corresponding call to mark will either:
* </p>
* <ul>
* <li>throw an {@code IOException}</li>
* <li>or, reset to the beginning of the stream.</li>
* </ul>
* <p>
* An {@code IOException} will be thrown if the previous marked position
* lies in the discarded portion of the stream.
* </p>
*
* @throws IOException if an I/O error occurs.
* @see java.io.InputStream#reset()
@@ -105,10 +111,11 @@ public interface Seekable {
* Discards the initial portion of the stream prior to the indicated
* postion. Attempting to seek to an offset within the flushed portion of
* the stream will result in an {@code IndexOutOfBoundsException}.
* <p/>
* <p>
* Calling {@code flushBefore} may allow classes implementing this
* interface to free up resources such as memory or disk space that are
* being used to store data from the stream.
* </p>
*
* @param pPosition a long containing the length of the file prefix that
* may be flushed.
@@ -36,7 +36,7 @@ import java.util.Stack;
/**
* Abstract base class for {@code InputStream}s implementing the {@code Seekable} interface.
* <p/>
*
* @see SeekableOutputStream
*
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
@@ -37,7 +37,7 @@ import java.util.Stack;
/**
* Abstract base class for {@code OutputStream}s implementing the
* {@code Seekable} interface.
* <p/>
*
* @see SeekableInputStream
*
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
@@ -38,7 +38,6 @@ import java.io.StringReader;
/**
* StringArrayReader
* <p/>
*
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
* @author last modified by $Author: haku $
@@ -39,7 +39,6 @@ import java.io.InputStream;
/**
* An {@code InputStream} reading up to a specified number of bytes from an
* underlying stream.
* <p/>
*
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-core/src/main/java/com/twelvemonkeys/io/SubStream.java#2 $
@@ -38,7 +38,6 @@ import java.io.IOException;
/**
* UnixFileSystem
* <p/>
*
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-core/src/main/java/com/twelvemonkeys/io/UnixFileSystem.java#1 $
@@ -37,7 +37,6 @@ import java.io.IOException;
/**
* Win32File
* <p/>
*
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-core/src/main/java/com/twelvemonkeys/io/Win32File.java#2 $
@@ -36,7 +36,6 @@ import java.io.IOException;
/**
* WindowsFileSystem
* <p/>
*
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-core/src/main/java/com/twelvemonkeys/io/Win32FileSystem.java#2 $
@@ -35,10 +35,11 @@ import java.util.Arrays;
/**
* A {@code File} implementation that resolves the Windows {@code .lnk} files as symbolic links.
* <p/>
* <p>
* This class is based on example code from
* <a href="http://www.oreilly.com/catalog/swinghks/index.html">Swing Hacks</a>,
* By Joshua Marinacci, Chris Adamson (O'Reilly, ISBN: 0-596-00907-0), Hack 30.
* </p>
*
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-core/src/main/java/com/twelvemonkeys/io/Win32Lnk.java#2 $
@@ -324,9 +325,10 @@ final class Win32Lnk extends File {
/**
* Converts two bytes into a short.
* <p/>
* <p>
* NOTE: this is little endian because it's for an
* Intel only OS
* </p>
*
* @ param bytes
* @ param off
@@ -39,15 +39,16 @@ import java.nio.charset.Charset;
/**
* Wraps a {@code Writer} in an {@code OutputStream}.
* <p/>
* <p>
* <em>Instances of this class are not thread-safe.</em>
* <p/>
* </p>
* <p>
* <em>NOTE: This class is probably not the right way of solving your problem,
* however it might prove useful in JSPs etc.
* If possible, it's always better to use the {@code Writer}'s underlying
* {@code OutputStream}, or wrap it's native backing.
* </em>
* <p/>
* </p>
*
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-core/src/main/java/com/twelvemonkeys/io/WriterOutputStream.java#2 $
@@ -36,9 +36,9 @@ import java.nio.ByteBuffer;
/**
* {@code Decoder} implementation for standard base64 encoding.
* <p/>
*
* @see <a href="http://tools.ietf.org/html/rfc1421">RFC 1421</a>
* @see <a href="http://tools.ietf.org/html/rfc2045"RFC 2045</a>
* @see <a href="http://tools.ietf.org/html/rfc2045">RFC 2045</a>
*
* @see Base64Encoder
*
@@ -36,9 +36,9 @@ import java.nio.ByteBuffer;
/**
* {@code Encoder} implementation for standard base64 encoding.
* <p/>
*
* @see <a href="http://tools.ietf.org/html/rfc1421">RFC 1421</a>
* @see <a href="http://tools.ietf.org/html/rfc2045"RFC 2045</a>
* @see <a href="http://tools.ietf.org/html/rfc2045">RFC 2045</a>
*
* @see Base64Decoder
*
@@ -34,7 +34,6 @@ import java.io.IOException;
/**
* Thrown by {@code Decoder}s when encoded data can not be decoded.
* <p/>
*
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-core/src/main/java/com/twelvemonkeys/io/enc/DecodeException.java#2 $
@@ -38,9 +38,10 @@ import java.nio.ByteBuffer;
* Interface for decoders.
* A {@code Decoder} may be used with a {@code DecoderStream}, to perform
* on-the-fly decoding from an {@code InputStream}.
* <p/>
* <p>
* Important note: Decoder implementations are typically not synchronized.
* <p/>
* </p>
*
* @see Encoder
* @see DecoderStream
*
@@ -36,9 +36,8 @@ import java.io.InputStream;
import java.nio.ByteBuffer;
/**
* An {@code InputStream} that provides on-the-fly decoding from an underlying
* stream.
* <p/>
* An {@code InputStream} that provides on-the-fly decoding from an underlying stream.
*
* @see EncoderStream
* @see Decoder
*
@@ -38,8 +38,9 @@ import java.nio.ByteBuffer;
* Interface for encoders.
* An {@code Encoder} may be used with an {@code EncoderStream}, to perform
* on-the-fly encoding to an {@code OutputStream}.
* <p/>
* <p>
* Important note: Encoder implementations are typically not synchronized.
* </p>
*
* @see Decoder
* @see EncoderStream
@@ -36,9 +36,8 @@ import java.io.OutputStream;
import java.nio.ByteBuffer;
/**
* An {@code OutputStream} that provides on-the-fly encoding to an underlying
* stream.
* <p/>
* An {@code OutputStream} that provides on-the-fly encoding to an underlying stream.
*
* @see DecoderStream
* @see Encoder
*
@@ -37,30 +37,36 @@ import java.nio.ByteBuffer;
/**
* Decoder implementation for Apple PackBits run-length encoding.
* <p/>
* <small>From Wikipedia, the free encyclopedia</small><br/>
* <p>
* <small>From Wikipedia, the free encyclopedia</small>
* <br>
* PackBits is a fast, simple compression scheme for run-length encoding of
* data.
* <p/>
* </p>
* <p>
* Apple introduced the PackBits format with the release of MacPaint on the
* Macintosh computer. This compression scheme is one of the types of
* compression that can be used in TIFF-files.
* <p/>
* </p>
* <p>
* A PackBits data stream consists of packets of one byte of header followed by
* data. The header is a signed byte; the data can be signed, unsigned, or
* packed (such as MacPaint pixels).
* <p/>
* <table><tr><th>Header byte</th><th>Data</th></tr>
* <tr><td>0 to 127</td> <td>1 + <i>n</i> literal bytes of data</td></tr>
* <tr><td>0 to -127</td> <td>One byte of data, repeated 1 - <i>n</i> times in
* the decompressed output</td></tr>
* <tr><td>-128</td> <td>No operation</td></tr></table>
* <p/>
* </p>
* <table>
* <caption>PackBits</caption>
* <tr><th>Header byte</th><th>Data</th></tr>
* <tr><td>0 to 127</td> <td>1 + <i>n</i> literal bytes of data</td></tr>
* <tr><td>0 to -127</td> <td>One byte of data, repeated 1 - <i>n</i> times in the decompressed output</td></tr>
* <tr><td>-128</td> <td>No operation</td></tr>
* </table>
* <p>
* Note that interpreting 0 as positive or negative makes no difference in the
* output. Runs of two bytes adjacent to non-runs are typically written as
* literal data.
* <p/>
* See <a href="http://developer.apple.com/technotes/tn/tn1023.html">Understanding PackBits</a>
* </p>
*
* @see <a href="http://developer.apple.com/technotes/tn/tn1023.html">Understanding PackBits</a>
*
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-core/src/main/java/com/twelvemonkeys/io/enc/PackBitsDecoder.java#1 $
@@ -71,8 +77,6 @@ public final class PackBitsDecoder implements Decoder {
private final boolean disableNoOp;
private final byte[] sample;
private int leftOfRun;
private boolean splitRun;
private boolean reachedEOF;
/** Creates a {@code PackBitsDecoder}. */
@@ -82,10 +86,11 @@ public final class PackBitsDecoder implements Decoder {
/**
* Creates a {@code PackBitsDecoder}, with optional compatibility mode.
* <p/>
* <p>
* As some implementations of PackBits-like encoders treat {@code -128} as length of
* a compressed run, instead of a no-op, it's possible to disable no-ops for compatibility.
* Should be used with caution, even though, most known encoders never write no-ops in the compressed streams.
* </p>
*
* @param disableNoOp {@code true} if {@code -128} should be treated as a compressed run, and not a no-op
*/
@@ -95,10 +100,11 @@ public final class PackBitsDecoder implements Decoder {
/**
* Creates a {@code PackBitsDecoder}, with optional compatibility mode.
* <p/>
* <p>
* As some implementations of PackBits-like encoders treat {@code -128} as length of
* a compressed run, instead of a no-op, it's possible to disable no-ops for compatibility.
* Should be used with caution, even though, most known encoders never write no-ops in the compressed streams.
* </p>
*
* @param disableNoOp {@code true} if {@code -128} should be treated as a compressed run, and not a no-op
*/
@@ -114,65 +120,43 @@ public final class PackBitsDecoder implements Decoder {
* @param buffer a byte array, minimum 128 (or 129 if no-op is disabled) bytes long
* @return The number of bytes decoded
*
* @throws java.io.IOException
* @throws java.io.IOException if a problem occurs during decoding.
*/
public int decode(final InputStream stream, final ByteBuffer buffer) throws IOException {
if (reachedEOF) {
return -1;
}
// TODO: Don't decode more than single runs, because some writers add pad bytes inside the stream...
while (buffer.hasRemaining()) {
int n;
// NOTE: We don't decode more than single runs, because some writers add pad bytes inside the stream...
// Start new run
int b = stream.read();
if (b < 0) {
reachedEOF = true;
return 0;
}
if (splitRun) {
// Continue run
n = leftOfRun;
splitRun = false;
int n = (byte) b;
try {
if (n >= 0) {
// Copy next n + 1 bytes literally
readFully(stream, buffer, sample.length * (n + 1));
}
else {
// Start new run
int b = stream.read();
if (b < 0) {
reachedEOF = true;
break;
// Allow -128 for compatibility, see above
else if (disableNoOp || n != -128) {
// Replicate the next byte -n + 1 times
for (int s = 0; s < sample.length; s++) {
sample[s] = readByte(stream);
}
n = (byte) b;
}
// Split run at or before max
if (n >= 0 && n + 1 > buffer.remaining()) {
leftOfRun = n;
splitRun = true;
break;
}
else if (n < 0 && -n + 1 > buffer.remaining()) {
leftOfRun = n;
splitRun = true;
break;
}
try {
if (n >= 0) {
// Copy next n + 1 bytes literally
readFully(stream, buffer, sample.length * (n + 1));
for (int i = -n + 1; i > 0; i--) {
buffer.put(sample);
}
// Allow -128 for compatibility, see above
else if (disableNoOp || n != -128) {
// Replicate the next byte -n + 1 times
for (int s = 0; s < sample.length; s++) {
sample[s] = readByte(stream);
}
for (int i = -n + 1; i > 0; i--) {
buffer.put(sample);
}
}
// else NOOP (-128)
}
catch (IndexOutOfBoundsException e) {
throw new DecodeException("Error in PackBits decompression, data seems corrupt", e);
}
// else NOOP (-128)
}
catch (IndexOutOfBoundsException e) {
throw new DecodeException("Error in PackBits decompression, data seems corrupt", e);
}
return buffer.position();
@@ -36,30 +36,36 @@ import java.nio.ByteBuffer;
/**
* Encoder implementation for Apple PackBits run-length encoding.
* <p/>
* From Wikipedia, the free encyclopedia<br/>
* <p>
* From Wikipedia, the free encyclopedia
* <br>
* PackBits is a fast, simple compression scheme for run-length encoding of
* data.
* <p/>
* </p>
* <p>
* Apple introduced the PackBits format with the release of MacPaint on the
* Macintosh computer. This compression scheme is one of the types of
* compression that can be used in TIFF-files.
* <p/>
* </p>
* <p>
* A PackBits data stream consists of packets of one byte of header followed by
* data. The header is a signed byte; the data can be signed, unsigned, or
* packed (such as MacPaint pixels).
* <p/>
* <table><tr><th>Header byte</th><th>Data</th></tr>
* <tr><td>0 to 127</td> <td>1 + <i>n</i> literal bytes of data</td></tr>
* <tr><td>0 to -127</td> <td>One byte of data, repeated 1 - <i>n</i> times in
* the decompressed output</td></tr>
* <tr><td>-128</td> <td>No operation</td></tr></table>
* <p/>
* </p>
* <table>
* <caption>PackBits</caption>
* <tr><th>Header byte</th><th>Data</th></tr>
* <tr><td>0 to 127</td> <td>1 + <i>n</i> literal bytes of data</td></tr>
* <tr><td>0 to -127</td> <td>One byte of data, repeated 1 - <i>n</i> times in the decompressed output</td></tr>
* <tr><td>-128</td> <td>No operation</td></tr>
* </table>
* <p>
* Note that interpreting 0 as positive or negative makes no difference in the
* output. Runs of two bytes adjacent to non-runs are typically written as
* literal data.
* <p/>
* See <a href="http://developer.apple.com/technotes/tn/tn1023.html">Understanding PackBits</a>
* </p>
*
* @see <a href="http://developer.apple.com/technotes/tn/tn1023.html">Understanding PackBits</a>
*
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-core/src/main/java/com/twelvemonkeys/io/enc/PackBitsEncoder.java#1 $
@@ -35,24 +35,28 @@ import com.twelvemonkeys.lang.StringUtil;
import javax.imageio.stream.ImageInputStream;
import java.io.*;
import java.nio.ByteOrder;
import java.util.Arrays;
import java.util.SortedSet;
import java.util.TreeSet;
import java.util.UUID;
import static com.twelvemonkeys.lang.Validate.notNull;
/**
* Represents a read-only OLE2 compound document.
* <p/>
* <p>
* <!-- TODO: Consider really detaching the entries, as this is hard for users to enforce... -->
* <em>NOTE: This class is not synchronized. Accessing the document or its
* entries from different threads, will need synchronization on the document
* instance.</em>
* </p>
*
* @author <a href="mailto:harald.kuhr@gmail.no">Harald Kuhr</a>
* @author last modified by $Author: haku $
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-core/src/main/java/com/twelvemonkeys/io/ole2/CompoundDocument.java#4 $
*/
public final class CompoundDocument {
public final class CompoundDocument implements AutoCloseable {
// TODO: Write support...
// TODO: Properties: http://support.microsoft.com/kb/186898
@@ -96,13 +100,19 @@ public final class CompoundDocument {
/**
* Creates a (for now) read only {@code CompoundDocument}.
* <p>
* <em>Warning! You must invoke {@link #close()} on the compound document
* created from this constructor when done, to avoid leaking file
* descriptors.</em>
* </p>
*
* @param pFile the file to read from
* @param file the file to read from
*
* @throws IOException if an I/O exception occurs while reading the header
*/
public CompoundDocument(final File pFile) throws IOException {
input = new LittleEndianRandomAccessFile(FileUtil.resolve(pFile), "r");
public CompoundDocument(final File file) throws IOException {
// TODO: We need to close this (or it's underlying RAF)! Otherwise we're leaking file descriptors!
input = new LittleEndianRandomAccessFile(FileUtil.resolve(file), "r");
// TODO: Might be better to read header on first read operation?!
// OTOH: It's also good to be fail-fast, so at least we should make
@@ -113,17 +123,17 @@ public final class CompoundDocument {
/**
* Creates a read only {@code CompoundDocument}.
*
* @param pInput the input to read from
* @param pInput the input to read from.
*
* @throws IOException if an I/O exception occurs while reading the header
*/
public CompoundDocument(final InputStream pInput) throws IOException {
this(new FileCacheSeekableStream(pInput));
this(new MemoryCacheSeekableStream(pInput));
}
// For testing only, consider exposing later
CompoundDocument(final SeekableInputStream pInput) throws IOException {
input = new SeekableLittleEndianDataInputStream(pInput);
CompoundDocument(final SeekableInputStream stream) throws IOException {
input = new SeekableLittleEndianDataInputStream(stream);
// TODO: Might be better to read header on first read operation?!
// OTOH: It's also good to be fail-fast, so at least we should make
@@ -134,12 +144,15 @@ public final class CompoundDocument {
/**
* Creates a read only {@code CompoundDocument}.
*
* @param pInput the input to read from
* @param input the input to read from
*
* @throws IOException if an I/O exception occurs while reading the header
*/
public CompoundDocument(final ImageInputStream pInput) throws IOException {
input = pInput;
public CompoundDocument(final ImageInputStream input) throws IOException {
this.input = notNull(input, "input");
// This implementation only supports little endian (Intel) CompoundDocuments
input.setByteOrder(ByteOrder.LITTLE_ENDIAN);
// TODO: Might be better to read header on first read operation?!
// OTOH: It's also good to be fail-fast, so at least we should make
@@ -147,6 +160,27 @@ public final class CompoundDocument {
readHeader();
}
/**
* This method will close the underlying {@link RandomAccessFile} if any,
* but will leave any stream created outside the document open.
*
* @see #CompoundDocument(File)
* @see RandomAccessFile#close()
*
* @throws IOException if an I/O error occurs.
*/
@Override
public void close() throws IOException {
if (input instanceof RandomAccessFile) {
((RandomAccessFile) input).close();
}
else if (input instanceof LittleEndianRandomAccessFile) {
((LittleEndianRandomAccessFile) input).close();
}
// Other streams are left open
}
public static boolean canRead(final DataInput pInput) {
return canRead(pInput, true);
}
@@ -609,9 +643,10 @@ public final class CompoundDocument {
* milliseconds since January 1, 1970.
* The time stamp parameter is assumed to be in units of
* 100 nano seconds since January 1, 1601.
* <p/>
* <p>
* If the timestamp is {@code 0L} (meaning not specified), no conversion
* is done, to behave like {@code java.io.File}.
* </p>
*
* @param pMSTime an unsigned long value representing the time stamp (in
* units of 100 nano seconds since January 1, 1601).
@@ -214,8 +214,9 @@ public final class Entry implements Comparable<Entry> {
* The time is converted from its internal representation to standard Java
* representation, milliseconds since the epoch
* (00:00:00 GMT, January 1, 1970).
* <p/>
* <p>
* Note that most applications leaves this value empty ({@code 0L}).
* </p>
*
* @return A {@code long} value representing the time this entry was
* created, measured in milliseconds since the epoch
@@ -231,8 +232,9 @@ public final class Entry implements Comparable<Entry> {
* The time is converted from its internal representation to standard Java
* representation, milliseconds since the epoch
* (00:00:00 GMT, January 1, 1970).
* <p/>
* <p>
* Note that many applications leaves this value empty ({@code 0L}).
* </p>
*
* @return A {@code long} value representing the time this entry was
* last modified, measured in milliseconds since the epoch
@@ -38,7 +38,6 @@ import java.util.*;
/**
* Contains mappings from file extension to mime-types and from mime-type to file-types.
* <p/>
*
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-core/src/main/java/com/twelvemonkeys/net/MIMEUtil.java#5 $
@@ -102,8 +102,9 @@ public final class DOMSerializer {
/**
* Specifies wether the serializer should use indentation and optimize for
* readability.
* <p/>
* Note: This is a hint, and may be ignored by DOM implemenations.
* <p>
* Note: This is a hint, and may be ignored by DOM implementations.
* </p>
*
* @param pPrettyPrint {@code true} to enable pretty printing
*/
+8 -6
View File
@@ -389,9 +389,10 @@ public class XMLSerializer {
private void writeDocument(final PrintWriter pOut, final Node pNode, final SerializationContext pContext) {
// Document fragments might not have child nodes...
if (pNode.hasChildNodes()) {
NodeList nodes = pNode.getChildNodes();
for (int i = 0; i < nodes.getLength(); i++) {
writeNodeRecursive(pOut, nodes.item(i), pContext);
Node child = pNode.getFirstChild();
while (child != null) {
writeNodeRecursive(pOut, child, pContext);
child = child.getNextSibling();
}
}
}
@@ -448,9 +449,10 @@ public class XMLSerializer {
pOut.println();
}
NodeList children = pNode.getChildNodes();
for (int i = 0; i < children.getLength(); i++) {
writeNodeRecursive(pOut, children.item(i), pContext.push());
Node child = pNode.getFirstChild();
while (child != null) {
writeNodeRecursive(pOut, child, pContext.push());
child = child.getNextSibling();
}
if (!pContext.preserveSpace) {
@@ -72,64 +72,64 @@ public class CompoundDocumentTest {
@Test
public void testRoot() throws IOException {
CompoundDocument document = createTestDocument();
try (CompoundDocument document = createTestDocument()) {
Entry root = document.getRootEntry();
Entry root = document.getRootEntry();
assertNotNull(root);
assertEquals("Root Entry", root.getName());
assertTrue(root.isRoot());
assertFalse(root.isFile());
assertFalse(root.isDirectory());
assertEquals(0, root.length());
assertNull(root.getInputStream());
assertNotNull(root);
assertEquals("Root Entry", root.getName());
assertTrue(root.isRoot());
assertFalse(root.isFile());
assertFalse(root.isDirectory());
assertEquals(0, root.length());
assertNull(root.getInputStream());
}
}
@Test
public void testContents() throws IOException {
CompoundDocument document = createTestDocument();
try (CompoundDocument document = createTestDocument()) {
Entry root = document.getRootEntry();
Entry root = document.getRootEntry();
assertNotNull(root);
assertNotNull(root);
SortedSet<Entry> children = new TreeSet<Entry>(root.getChildEntries());
assertEquals(25, children.size());
SortedSet<Entry> children = new TreeSet<Entry>(root.getChildEntries());
assertEquals(25, children.size());
// Weirdness in the file format, name is *written backwards* 1-24 + Catalog
for (String name : "1,2,3,4,5,6,7,8,9,01,02,11,12,21,22,31,32,41,42,51,61,71,81,91,Catalog".split(",")) {
assertEquals(name, children.first().getName());
children.remove(children.first());
// Weirdness in the file format, name is *written backwards* 1-24 + Catalog
for (String name : "1,2,3,4,5,6,7,8,9,01,02,11,12,21,22,31,32,41,42,51,61,71,81,91,Catalog".split(",")) {
assertEquals(name, children.first().getName());
children.remove(children.first());
}
}
}
@Test(expected = UnsupportedOperationException.class)
public void testChildEntriesUnmodifiable() throws IOException {
CompoundDocument document = createTestDocument();
try (CompoundDocument document = createTestDocument()) {
Entry root = document.getRootEntry();
Entry root = document.getRootEntry();
assertNotNull(root);
assertNotNull(root);
SortedSet<Entry> children = root.getChildEntries();
SortedSet<Entry> children = root.getChildEntries();
// Should not be allowed, as it modifies the internal structure
children.remove(children.first());
// Should not be allowed, as it modifies the internal structure
children.remove(children.first());
}
}
@Test
public void testReadThumbsCatalogFile() throws IOException {
CompoundDocument document = createTestDocument();
try (CompoundDocument document = createTestDocument()) {
Entry root = document.getRootEntry();
Entry root = document.getRootEntry();
assertNotNull(root);
assertEquals(25, root.getChildEntries().size());
assertNotNull(root);
assertEquals(25, root.getChildEntries().size());
Entry catalog = root.getChildEntry("Catalog");
Entry catalog = root.getChildEntry("Catalog");
assertNotNull(catalog);
assertNotNull("Input stream may not be null", catalog.getInputStream());
assertNotNull(catalog);
assertNotNull("Input stream may not be null", catalog.getInputStream());
}
}
@Test
@@ -51,35 +51,7 @@ import static org.junit.Assert.*;
* @author last modified by $Author: haraldk$
* @version $Id: CompoundDocument_StreamTestCase.java,v 1.0 13.10.11 12:01 haraldk Exp$
*/
//@Ignore("Need proper in-memory creation of CompoundDocuments")
public class CompoundDocument_StreamTest extends InputStreamAbstractTest {
private static final String SAMPLE_DATA = "/Thumbs-camera.db";
protected final CompoundDocument createTestDocument() throws IOException {
URL input = getClass().getResource(SAMPLE_DATA);
assertNotNull("Missing test resource!", input);
assertEquals("Test resource not a file:// resource", "file", input.getProtocol());
try {
return new CompoundDocument(new File(input.toURI()));
}
catch (URISyntaxException e) {
throw new AssertionError(e);
}
}
private SeekableInputStream createRealInputStream() {
try {
Entry first = createTestDocument().getRootEntry().getChildEntries().first();
assertNotNull(first);
return first.getInputStream();
}
catch (IOException e) {
throw new AssertionError(e);
}
}
@Override
protected InputStream makeInputStream(byte[] data) {
try {
@@ -182,15 +154,13 @@ public class CompoundDocument_StreamTest extends InputStreamAbstractTest {
return pad;
}
// @Ignore
@Test
public void testDev() throws IOException {
public void testStreamRead() throws IOException {
InputStream stream = makeInputStream(makeOrderedArray(32));
int read;
int count = 0;
while ((read = stream.read()) >= 0) {
// System.out.printf("read %02d: 0x%02x%n", count, read & 0xFF);
assertEquals(count, read);
count++;
}
+1 -1
View File
@@ -4,7 +4,7 @@
<parent>
<groupId>com.twelvemonkeys.common</groupId>
<artifactId>common</artifactId>
<version>3.4</version>
<version>3.4.4-SNAPSHOT</version>
</parent>
<artifactId>common-lang</artifactId>
<packaging>jar</packaging>
@@ -42,8 +42,9 @@ import java.util.Map;
/**
* A utility class with some useful bean-related functions.
* <p/>
* <p>
* <em>NOTE: This class is not considered part of the public API and may be changed without notice</em>
* </p>
*
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
* @author last modified by $Author: haku $
@@ -66,13 +67,11 @@ public final class BeanUtil {
*
* @return A string containing the value of the given property, or {@code null}
* if it can not be found.
* @todo Remove System.err's... Create new Exception? Hmm..
*/
public static Object getPropertyValue(Object pObject, String pProperty) {
//
// TODO: Remove System.err's... Create new Exception? Hmm..
// TODO: Support get(Object) method of Collections!
// Handle lists and arrays with [] (index) operator
//
if (pObject == null || pProperty == null || pProperty.length() < 1) {
return null;
@@ -535,9 +534,10 @@ public final class BeanUtil {
* a method named
* {@code set + capitalize(entry.getKey())} is called on the bean,
* with {@code entry.getValue()} as its argument.
* <p/>
* <p>
* Properties that has no matching set-method in the bean, are simply
* discarded.
* </p>
*
* @param pBean The bean to configure
* @param pMapping The mapping for the bean
@@ -560,12 +560,14 @@ public final class BeanUtil {
* a method named
* {@code set + capitalize(entry.getKey())} is called on the bean,
* with {@code entry.getValue()} as its argument.
* <p/>
* <p>
* Optionally, lisp-style names are allowed, and automatically converted
* to Java-style camel-case names.
* <p/>
* </p>
* <p>
* Properties that has no matching set-method in the bean, are simply
* discarded.
* </p>
*
* @see StringUtil#lispToCamel(String)
*
@@ -35,7 +35,6 @@ import java.util.TimeZone;
/**
* A utility class with useful date manipulation methods and constants.
* <p/>
*
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-core/src/main/java/com/twelvemonkeys/lang/DateUtil.java#1 $
@@ -199,9 +199,10 @@ public final class Platform {
/**
* Enumeration of common System {@code Architecture}s.
* <p/>
* <p>
* For {@link #Unknown unknown architectures}, {@code toString()} will return
* the the same value as {@code System.getProperty("os.arch")}.
* </p>
*
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-core/src/main/java/com/twelvemonkeys/lang/Platform.java#1 $
@@ -228,9 +229,10 @@ public final class Platform {
/**
* Enumeration of common {@code OperatingSystem}s.
* <p/>
* <p>
* For {@link #Unknown unknown operating systems}, {@code getName()} will return
* the the same value as {@code System.getProperty("os.name")}.
* </p>
*
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-core/src/main/java/com/twelvemonkeys/lang/Platform.java#1 $
@@ -32,9 +32,10 @@ package com.twelvemonkeys.lang;
/**
* Util class for various reflection-based operations.
* <p/>
* <p>
* <em>NOTE: This class is not considered part of the public API and may be
* changed without notice</em>
* </p>
*
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-core/src/main/java/com/twelvemonkeys/lang/ReflectUtil.java#1 $
@@ -56,9 +56,9 @@ import java.util.regex.PatternSyntaxException;
* @author <A href="mailto:eirik.torske@twelvemonkeys.com">Eirik Torske</A>
* @author last modified by $Author: haku $
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-core/src/main/java/com/twelvemonkeys/lang/StringUtil.java#2 $
* @todo Consistency check: Method names, parameter sequence, Exceptions,
* return values, null-value handling and parameter names (cosmetics).
*/
// TODO: Consistency check: Method names, parameter sequence, Exceptions,
public final class StringUtil {
/**
@@ -798,10 +798,10 @@ public final class StringUtil {
* @param pPrepend The location of fill-ins, prepend (true),
* or append (false)
* @return a concatenated string.
* @todo What if source is allready longer than required length?
* @todo Consistency with cut
* @see #cut(String,int,String)
*/
// TODO: What if source is allready longer than required length?
// TODO: Consistency with cut
public static String pad(String pSource, int pRequiredLength, String pPadString, boolean pPrepend) {
if (pPadString == null || pPadString.length() == 0) {
throw new IllegalArgumentException("Pad string: \"" + pPadString + "\"");
@@ -873,10 +873,11 @@ public final class StringUtil {
* @param pString the string to convert
* @param pFormat the date format
* @return the date
* @todo cache formats?
*
* @see java.text.SimpleDateFormat
* @see java.text.SimpleDateFormat#SimpleDateFormat(String)
*/
// TODO: cache formats?
public static Date toDate(String pString, String pFormat) {
// Get the format from cache, or create new and insert
// Return new date
@@ -1203,14 +1204,15 @@ public final class StringUtil {
* hexadecimal for red, green and blue values respectively.</LI>
* <LI>{@code #AARRGGBB}, as above, with AA as alpha component.</LI>
* </UL>
* <p/>
* <p>
* Examlples: {@code toColorString(Color.red) == "#ff0000"},
* {@code toColorString(new Color(0xcc, 0xcc, 0xcc)) == "#cccccc"}.
* </p>
*
* @param pColor the color
* @return A String representation of the color on HTML/CSS form
* @todo Consider moving to ImageUtil?
*/
// TODO: Consider moving to ImageUtil?
public static String toColorString(Color pColor) {
// Not a color...
if (pColor == null) {
@@ -1237,9 +1239,10 @@ public final class StringUtil {
* Tests a string, to see if it is an number (element of <b>Z</b>).
* Valid integers are positive natural numbers (1, 2, 3, ...),
* their negatives (?1, ?2, ?3, ...) and the number zero.
* <p/>
* <p>
* Note that there is no guarantees made, that this number can be
* represented as either an int or a long.
* </p>
*
* @param pString The string to check.
* @return true if the String is a natural number.
@@ -1356,9 +1359,10 @@ public final class StringUtil {
/**
* Ensures that a string includes a given substring at a given position.
* <p/>
* <p>
* Extends the string with a given string if it is not already there.
* E.g an URL "www.vg.no", to "http://www.vg.no".
* </p>
*
* @param pSource The source string.
* @param pSubstring The substring to include.
@@ -1384,9 +1388,10 @@ public final class StringUtil {
/**
* Ensures that a string does not include a given substring at a given
* position.
* <p/>
* <p>
* Removes a given substring from a string if it is there.
* E.g an URL "http://www.vg.no", to "www.vg.no".
* </p>
*
* @param pSource The source string.
* @param pSubstring The substring to check and possibly remove.
@@ -1411,7 +1416,6 @@ public final class StringUtil {
/**
* Gets the first substring between the given string boundaries.
* <p/>
*
* @param pSource The source string.
* @param pBeginBoundaryString The string that marks the beginning.
@@ -1446,7 +1450,6 @@ public final class StringUtil {
/**
* Removes the first substring demarcated by the given string boundaries.
* <p/>
*
* @param pSource The source string.
* @param pBeginBoundaryChar The character that marks the beginning of the
@@ -1486,7 +1489,6 @@ public final class StringUtil {
/**
* Removes all substrings demarcated by the given string boundaries.
* <p/>
*
* @param pSource The source string.
* @param pBeginBoundaryChar The character that marks the beginning of the unwanted substring.
@@ -1520,13 +1522,12 @@ public final class StringUtil {
/**
* Gets the first element of a {@code String} containing string elements delimited by a given delimiter.
* <i>NB - Straightforward implementation!</i>
* <p/>
*
* @param pSource The source string.
* @param pDelimiter The delimiter used in the source string.
* @return The last string element.
* @todo This method should be re-implemented for more efficient execution.
*/
// TODO: This method should be re-implemented for more efficient execution.
public static String getFirstElement(final String pSource, final String pDelimiter) {
if (pDelimiter == null) {
throw new IllegalArgumentException("delimiter == null");
@@ -1547,7 +1548,6 @@ public final class StringUtil {
* Gets the last element of a {@code String} containing string elements
* delimited by a given delimiter.
* <i>NB - Straightforward implementation!</i>
* <p/>
*
* @param pSource The source string.
* @param pDelimiter The delimiter used in the source string.
@@ -1620,9 +1620,9 @@ public final class StringUtil {
* @param pForceDeep {@code true} to force deep {@code toString}, even
* if object overrides toString
* @return a deep string representation of the given object
* @todo Array handling (print full type and length)
* @todo Register handlers for specific toDebugString handling? :-)
*/
// TODO: Array handling (print full type and length)
// TODO: Register handlers for specific toDebugString handling? :-)
public static String deepToString(Object pObject, boolean pForceDeep, int pDepth) {
// Null is null
if (pObject == null) {
@@ -1761,11 +1761,11 @@ public final class StringUtil {
/**
* Tells whether or not the given string string matches the given regular
* expression.
* <p/>
* <p>
* An invocation of this method of the form
* <tt>matches(<i>str</i>, <i>regex</i>)</tt> yields exactly the
* same result as the expression
* <p/>
* </p>
* <blockquote><tt> {@link Pattern}.
* {@link Pattern#matches(String, CharSequence) matches}
* (<i>regex</i>, <i>str</i>)</tt></blockquote>
@@ -1785,15 +1785,18 @@ public final class StringUtil {
/**
* Replaces the first substring of the given string that matches the given
* regular expression with the given pReplacement.
* <p/>
* <p>
* An invocation of this method of the form
* <tt>replaceFirst(<i>str</i>, </tt><i>regex</i>, <i>repl</i>)</tt>
* yields exactly the same result as the expression
* <p/>
* <tt>
* replaceFirst(<i>str</i>, <i>regex</i>, <i>repl</i>)
* </tt>
* yields exactly the same result as the expression:
* </p>
* <blockquote><tt>
* {@link Pattern}.{@link Pattern#compile compile}(<i>regex</i>).
* {@link Pattern}.{@link Pattern#compile(String) compile}(<i>regex</i>).
* {@link Pattern#matcher matcher}(<i>str</i>).
* {@link java.util.regex.Matcher#replaceFirst replaceFirst}(<i>repl</i>)</tt></blockquote>
* {@link java.util.regex.Matcher#replaceFirst replaceFirst}(<i>repl</i>)
* </tt></blockquote>
*
* @param pString the string
* @param pRegex the regular expression to which this string is to be matched
@@ -1810,15 +1813,16 @@ public final class StringUtil {
/**
* Replaces each substring of this string that matches the given
* regular expression with the given pReplacement.
* <p/>
* <p>
* An invocation of this method of the form
* <tt>replaceAll(<i>str</i>, <i>pRegex</i>, <i>repl</i><)</tt>
* <tt>replaceAll(<i>str</i>, <i>pRegex</i>, <i>repl</i>)</tt>
* yields exactly the same result as the expression
* <p/>
* </p>
* <blockquote><tt>
* {@link Pattern}.{@link Pattern#compile compile}(<i>pRegex</i>).
* {@link Pattern#matcher matcher}(</tt><i>str</i>{@code ).
* {@link java.util.regex.Matcher#replaceAll replaceAll}(}<i>repl</i>{@code )}</blockquote>
* {@link Pattern}.{@link Pattern#compile(String) compile}(<i>pRegex</i>).
* {@link Pattern#matcher matcher}(<i>str</i>{@code ).
* {@link java.util.regex.Matcher#replaceAll replaceAll}(}<i>repl</i>{@code )}
* </tt></blockquote>
*
* @param pString the string
* @param pRegex the regular expression to which this string is to be matched
@@ -1834,14 +1838,15 @@ public final class StringUtil {
/**
* Splits this string around matches of the given regular expression.
* <p/>
* <p>
* The array returned by this method contains each substring of this
* string that is terminated by another substring that matches the given
* expression or is terminated by the end of the string. The substrings in
* the array are in the order in which they occur in this string. If the
* expression does not match any part of the input then the resulting array
* has just one element, namely this string.
* <p/>
* </p>
* <p>
* The {@code pLimit} parameter controls the number of times the
* pattern is applied and therefore affects the length of the resulting
* array. If the pLimit <i>n</i> is greater than zero then the pattern
@@ -1852,13 +1857,14 @@ public final class StringUtil {
* possible and the array can have any length. If <i>n</i> is zero then
* the pattern will be applied as many times as possible, the array can
* have any length, and trailing empty strings will be discarded.
* <p/>
* </p>
* <p>
* An invocation of this method of the form
* <tt>split(<i>str</i>, <i>regex</i>, <i>n</i>)</tt>
* yields the same result as the expression
* <p/>
* yields the same result as the expression:
* </p>
* <blockquote>{@link Pattern}.
* {@link Pattern#compile compile}<tt>(<i>regex</i>).
* {@link Pattern#compile(String) compile}<tt>(<i>regex</i>).
* {@link Pattern#split(CharSequence,int) split}(<i>str</i>, <i>n</i>)</tt>
* </blockquote>
*
@@ -1878,11 +1884,12 @@ public final class StringUtil {
/**
* Splits this string around matches of the given regular expression.
* <p/>
* <p>
* This method works as if by invoking the two-argument
* {@link #split(String,String,int) split} method with the given
* expression and a limit argument of zero.
* Trailing empty strings are therefore not included in the resulting array.
* </p>
*
* @param pString the string
* @param pRegex the delimiting regular expression
@@ -1901,7 +1908,7 @@ public final class StringUtil {
* from camel-style (Java in-fix) naming convention
* to Lisp-style naming convention (hyphen delimitted, all lower case).
* Other characters in the string are left untouched.
* <p/>
* <p>
* Eg.
* {@code "foo" => "foo"},
* {@code "fooBar" => "foo-bar"},
@@ -1910,6 +1917,7 @@ public final class StringUtil {
* {@code "HttpURLConnection" => "http-url-connection"}
* {@code "my45Caliber" => "my-45-caliber"}
* {@code "allready-lisp" => "allready-lisp"}
* </p>
*
* @param pString the camel-style input string
* @return the string converted to lisp-style naming convention
@@ -2040,14 +2048,14 @@ public final class StringUtil {
* from Lisp-style naming convention (hyphen delimitted, all lower case)
* to camel-style (Java in-fix) naming convention.
* Other characters in the string are left untouched.
* <p/>
* <p>
* Eg.
* {@code "foo" => "foo"},
* {@code "foo-bar" => "fooBar"},
* {@code "http-request-wrapper" => "httpRequestWrapper"}
* {@code "my-45-caliber" => "my45Caliber"}
* {@code "allreadyCamel" => "allreadyCamel"}
* <p/>
* </p>
*
* @param pString the lisp-style input string
* @return the string converted to camel-style
@@ -2064,7 +2072,7 @@ public final class StringUtil {
* from Lisp-style naming convention (hyphen delimitted, all lower case)
* to camel-style (Java in-fix) naming convention.
* Other characters in the string are left untouched.
* <p/>
* <p>
* To create a string starting with a lower case letter
* (like Java variable names, etc),
* specify the {@code pFirstUpperCase} paramter to be {@code false}.
@@ -2072,14 +2080,15 @@ public final class StringUtil {
* {@code "foo" => "foo"},
* {@code "foo-bar" => "fooBar"},
* {@code "allreadyCamel" => "allreadyCamel"}
* <p/>
* </p>
* <p>
* To create a string starting with an upper case letter
* (like Java class name, etc),
* specify the {@code pFirstUpperCase} paramter to be {@code true}.
* Eg.
* {@code "http-request-wrapper" => "HttpRequestWrapper"}
* {@code "my-45-caliber" => "My45Caliber"}
* <p/>
* {@code "my-12-monkeys" => "My12Monkeys"}
* </p>
*
* @param pString the lisp-style input string
* @param pFirstUpperCase {@code true} if the first char should be
@@ -43,9 +43,10 @@ import java.util.Properties;
/**
* A utility class with some useful system-related functions.
* <p/>
* <p>
* <em>NOTE: This class is not considered part of the public API and may be
* changed without notice</em>
* </p>
*
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
* @author last modified by $Author: haku $
@@ -200,12 +201,10 @@ public final class SystemUtil {
* @see #loadProperties(Class)
* @see java.lang.ClassLoader#getResourceAsStream
* @see java.lang.ClassLoader#getSystemResourceAsStream
*
* @todo Reconsider ever using the System ClassLoader: http://www.javaworld.com/javaworld/javaqa/2003-06/01-qa-0606-load.html
* @todo Consider using Context Classloader instead?
*/
public static Properties loadProperties(Class pClass, String pName) throws IOException
{
// TODO: Reconsider ever using the System ClassLoader: http://www.javaworld.com/javaworld/javaqa/2003-06/01-qa-0606-load.html
// TODO: Consider using Context Classloader instead?
public static Properties loadProperties(Class pClass, String pName) throws IOException {
// Convert to name the classloader understands
String name = !StringUtil.isEmpty(pName) ? pName : pClass.getName().replace('.', '/');
@@ -36,10 +36,11 @@ import java.util.Map;
/**
* Kind of like {@code org.apache.commons.lang.Validate}. Just smarter. ;-)
* <p/>
* <p>
* Uses type parameterized return values, thus making it possible to check
* constructor arguments before
* they are passed on to {@code super} or {@code this} type constructors.
* </p>
*
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
* @author last modified by $Author: haku $
@@ -35,7 +35,6 @@ import java.util.*;
/**
* AbstractDecoratedMap
* <p/>
*
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-core/src/main/java/com/twelvemonkeys/util/AbstractDecoratedMap.java#2 $
@@ -59,9 +58,10 @@ abstract class AbstractDecoratedMap<K, V> extends AbstractMap<K, V> implements M
/**
* Creates a {@code Map} backed by a {@code HashMap}, containing all
* key/value mappings from the given {@code Map}.
* <p/>
* <p>
* <small>This is constructor is here to comply with the reccomendations for
* "standard" constructors in the {@code Map} interface.</small>
* </p>
*
* @see #AbstractDecoratedMap(java.util.Map, java.util.Map)
*
@@ -75,9 +75,10 @@ abstract class AbstractDecoratedMap<K, V> extends AbstractMap<K, V> implements M
/**
* Creates a {@code Map} backed by the given backing-{@code Map},
* containing all key/value mappings from the given contents-{@code Map}.
* <p/>
* <p>
* NOTE: The backing map is structuraly cahnged, and it should NOT be
* accessed directly, after the wrapped map is created.
* </p>
*
* @param pBacking the backing map of this map. Must be either empty, or
* the same map as {@code pContents}.
@@ -149,9 +150,10 @@ abstract class AbstractDecoratedMap<K, V> extends AbstractMap<K, V> implements M
* specified pValue. More formally, returns {@code true} if and only if
* this map contains at least one mapping to a pValue {@code v} such that
* {@code (pValue==null ? v==null : pValue.equals(v))}.
* <p/>
* <p>
* This implementation requires time linear in the map size for this
* operation.
* </p>
*
* @param pValue pValue whose presence in this map is to be tested.
* @return {@code true} if this map maps one or more keys to the
@@ -32,7 +32,6 @@ package com.twelvemonkeys.util;
/**
* Abstract base class for {@code TokenIterator}s to extend.
* <p/>
*
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-core/src/main/java/com/twelvemonkeys/util/AbstractTokenIterator.java#1 $
@@ -41,9 +41,10 @@ import java.util.*;
/**
* A {@code Map} adapter for a Java Bean.
* <p/>
* <p>
* Ruthlessly stolen from
* <a href="http://binkley.blogspot.com/2006/08/mapping-java-bean.html>Binkley's Blog</a>
* <a href="http://binkley.blogspot.com/2006/08/mapping-java-bean.html">Binkley's Blog</a>
* </p>
*/
public final class BeanMap extends AbstractMap<String, Object> implements Serializable, Cloneable {
private final Object bean;
@@ -268,7 +268,7 @@ public final class CollectionUtil {
*
* @throws IllegalArgumentException if {@code pArray} is {@code null} or
* if {@code pArray} is not an array.
* @throws ArrayIndexOutOfBoundsException if {@code pStart} < 0
* @throws ArrayIndexOutOfBoundsException if {@code pStart} &lt; 0
*/
public static Object subArray(Object pArray, int pStart) {
return subArray(pArray, pStart, -1);
@@ -279,13 +279,14 @@ public final class CollectionUtil {
* If the sub array is same length as the original
* ({@code pStart == 0}), the original array will be returned.
*
* @param <T> the type of array
* @param pArray the original array
* @param pStart the start index of the original array
* @return a subset of the original array, or the original array itself,
* if {@code pStart} is 0.
*
* @throws IllegalArgumentException if {@code pArray} is {@code null}
* @throws ArrayIndexOutOfBoundsException if {@code pStart} < 0
* @throws ArrayIndexOutOfBoundsException if {@code pStart} &lt; 0
*/
public static <T> T[] subArray(T[] pArray, int pStart) {
return subArray(pArray, pStart, -1);
@@ -309,7 +310,7 @@ public final class CollectionUtil {
*
* @throws IllegalArgumentException if {@code pArray} is {@code null} or
* if {@code pArray} is not an array.
* @throws ArrayIndexOutOfBoundsException if {@code pStart} < 0
* @throws ArrayIndexOutOfBoundsException if {@code pStart} &lt; 0
*/
@SuppressWarnings({"SuspiciousSystemArraycopy"})
public static Object subArray(Object pArray, int pStart, int pLength) {
@@ -363,6 +364,7 @@ public final class CollectionUtil {
* If the sub array is same length as the original, the original array will
* be returned.
*
* @param <T> the type of array
* @param pArray the original array
* @param pStart the start index of the original array
* @param pLength the length of the new array
@@ -371,7 +373,7 @@ public final class CollectionUtil {
* negative, or greater or equal to {@code pArray.length}.
*
* @throws IllegalArgumentException if {@code pArray} is {@code null}
* @throws ArrayIndexOutOfBoundsException if {@code pStart} < 0
* @throws ArrayIndexOutOfBoundsException if {@code pStart} &lt; 0
*/
@SuppressWarnings("unchecked")
public static <T> T[] subArray(T[] pArray, int pStart, int pLength) {
@@ -424,8 +426,8 @@ public final class CollectionUtil {
* @param pArray the array to iterate
* @return a new {@link ListIterator}
* @throws IllegalArgumentException if {@code pArray} is {@code null},
* {@code pStart < 0}, or
* {@code pLength > pArray.length - pStart}
* {@code pStart &lt; 0}, or
* {@code pLength &gt; pArray.length - pStart}
*/
public static <E> ListIterator<E> iterator(final E[] pArray) {
return iterator(pArray, 0, notNull(pArray).length);
@@ -439,8 +441,8 @@ public final class CollectionUtil {
* @param pLength the number of elements to include in the iterator
* @return a new {@link ListIterator}
* @throws IllegalArgumentException if {@code pArray} is {@code null},
* {@code pStart < 0}, or
* {@code pLength > pArray.length - pStart}
* {@code pStart &lt; 0}, or
* {@code pLength &gt; pArray.length - pStart}
*/
public static <E> ListIterator<E> iterator(final E[] pArray, final int pStart, final int pLength) {
return new ArrayIterator<E>(pArray, pStart, pLength);
@@ -32,7 +32,6 @@ package com.twelvemonkeys.util;
/**
* DuplicateHandler
* <p/>
*
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-core/src/main/java/com/twelvemonkeys/util/DuplicateHandler.java#2 $
@@ -38,10 +38,11 @@ import java.util.NoSuchElementException;
* element filtering. Each
* element is filtered against the given {@code Filter}, and only elements
* that are {@code accept}ed are returned by the {@code next} method.
* <p/>
* <p>
* The optional {@code remove} operation is implemented, but may throw
* {@code UnsupportedOperationException} if the underlying iterator does not
* support the remove operation.
* </p>
*
* @see FilterIterator.Filter
*
@@ -41,7 +41,6 @@ import java.util.Map;
* if the keys used are {@code Strings}. If the keys
* used are not {@code String}s, it wil work as a normal
* {@code java.util.Map}.
* <p/>
*
* @see java.util.Map
*
@@ -61,11 +60,12 @@ public class IgnoreCaseMap<V> extends AbstractDecoratedMap<String, V> implements
* Constructs a new {@code Map} with the same key-value mappings as the
* given {@code Map}.
* The backing map will be a {@link java.util.HashMap}
* <p/>
* <p>
* NOTE: As the keys in the given map parameter will be converted to
* uppercase (if they are strings), any duplicate key/value pair where
* {@code key instanceof String && key.equalsIgnoreCase(otherKey)}
* is true, will be lost.
* </p>
*
* @param pMap the map whose mappings are to be placed in this map.
*/
@@ -76,14 +76,16 @@ public class IgnoreCaseMap<V> extends AbstractDecoratedMap<String, V> implements
/**
* Constructs a new {@code Map} with the same key-value mappings as the
* given {@code Map}.
* <p/>
* <p>
* NOTE: The backing map is structuraly cahnged, and it should NOT be
* accessed directly, after the wrapped map is created.
* <p/>
* </p>
* <p>
* NOTE: As the keys in the given map parameter will be converted to
* uppercase (if they are strings), any duplicate key/value pair where
* {@code key instanceof String && key.equalsIgnoreCase(otherKey)}
* is true, will be lost.
* </p>
*
* @param pBacking the backing map of this map. Must be either empty, or
* the same map as {@code pContents}.
@@ -345,8 +345,6 @@ public class LinkedMap<K, V> extends AbstractDecoratedMap<K, V> implements Seria
}
/**
* @todo
*
* @return a copy of this map, with the same order and same key/value pairs.
*/
public Object clone() throws CloneNotSupportedException {
@@ -375,7 +373,7 @@ public class LinkedMap<K, V> extends AbstractDecoratedMap<K, V> implements Seria
* private static final int MAX_ENTRIES = 100;
*
* protected boolean removeEldestEntry(Map.Entry eldest) {
* return size() > MAX_ENTRIES;
* return size() &gt; MAX_ENTRIES;
* }
* </pre>
*
@@ -39,7 +39,8 @@ import java.util.*;
* <p>
* Resembles {@code LinkedHashSet} from JDK 1.4+, but is backed by a generic
* {@code LinkedMap}, rather than implementing a particular algoritm.
* <p/>
* </p>
*
* @see LinkedMap
*
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
@@ -40,10 +40,11 @@ import java.util.Set;
* An (immutable) empty {@link Map}, that supports all {@code Map} operations
* without throwing exceptions (in contrast to {@link Collections#EMPTY_MAP}
* that will throw exceptions on {@code put}/{@code remove}).
* <p/>
* <p>
* NOTE: This is not a general purpose {@code Map} implementation,
* as the {@code put} and {@code putAll} methods will not modify the map.
* Instances of this class will always be an empty map.
* </p>
*
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
* @version $Id: com/twelvemonkeys/util/NullMap.java#2 $
@@ -35,8 +35,8 @@ package com.twelvemonkeys.util;
* as an int, counting seconds.
*
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
* @todo Milliseconds!
*/
// TODO: Milliseconds!
public class Time {
private int time = -1;
@@ -140,13 +140,13 @@ public class Time {
* <DD>m (or any multiple of m's)
* <DT>the minutes part (padded with 0's, if number has less digits than
* the number of m's)
* m -> 0,1,...,59,60,61,...
* mm -> 00,01,...,59,60,61,...
* m -&gt; 0,1,...,59,60,61,...
* mm -&gt; 00,01,...,59,60,61,...
* <DD>s or ss
* <DT>the seconds part (padded with 0's, if number has less digits than
* the number of s's)
* s -> 0,1,...,59
* ss -> 00,01,...,59
* s -&gt; 0,1,...,59
* ss -&gt; 00,01,...,59
* <DD>S
* <DT>all seconds (including the ones above 59)
* </DL>
@@ -46,13 +46,13 @@ import java.util.Vector;
* <DD>m (or any multiple of m's)
* <DT>the minutes part (padded with 0's, if number has less digits than
* the number of m's)
* m -> 0,1,...,59,60,61,...
* mm -> 00,01,...,59,60,61,...
* m -&gt; 0,1,...,59,60,61,...
* mm -&gt; 00,01,...,59,60,61,...
* <DD>s or ss
* <DT>the seconds part (padded with 0's, if number has less digits than
* the number of s's)
* s -> 0,1,...,59
* ss -> 00,01,...,59
* s -&gt; 0,1,...,59
* ss -&gt; 00,01,...,59
* <DD>S
* <DT>all seconds (including the ones above 59)
* </DL>
@@ -60,10 +60,6 @@ import java.util.Vector;
* May not handle all cases, and formats... ;-)
* Safest is: Always delimiters between the minutes (m) and seconds (s) part.
* <P>
* TODO:
* Move to com.twelvemonkeys.text?
* Milliseconds!
* Fix bugs.
* Known bugs:
* <P>
* The last character in the formatString is not escaped, while it should be.
@@ -76,6 +72,10 @@ import java.util.Vector;
*
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
*/
// TODO:
// Move to com.twelvemonkeys.text?
// Milliseconds!
// Fix bugs.
public class TimeFormat extends Format {
final static String MINUTE = "m";
final static String SECOND = "s";
@@ -37,8 +37,9 @@ import java.util.*;
* A {@code Map} implementation that removes (exipres) its elements after
* a given period. The map is by default backed by a {@link java.util.HashMap},
* or can be instantiated with any given {@code Map} as backing.
* <P/>
* <p>
* Notes to consider when using this map:
* </p>
* <ul>
* <li>Elements may not expire on the exact millisecond as expected.</li>
* <li>The value returned by the {@code size()} method of the map, or any of
@@ -52,14 +53,13 @@ import java.util.*;
*
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-core/src/main/java/com/twelvemonkeys/util/TimeoutMap.java#2 $
*
* @todo Consider have this Map extend LinkedMap.. That way the removeExpired
* method only have to run from the first element, until it finds an element
* that should not expire, as elements are in insertion order.
* and next expiry time would be the time of the first element.
* @todo Consider running the removeExpiredEntries method in a separate (deamon) thread
* @todo - or document why it is not such a good idea.
*/
// TODO: Consider have this Map extend LinkedMap.. That way the removeExpired
// method only have to run from the first element, until it finds an element
// that should not expire, as elements are in insertion order.
// and next expiry time would be the time of the first element.
// TODO: Consider running the removeExpiredEntries method in a separate (deamon) thread
// TODO: - or document why it is not such a good idea.
public class TimeoutMap<K, V> extends AbstractDecoratedMap<K, V> implements ExpiringMap<K, V>, Serializable, Cloneable {
/**
* Expiry time
@@ -73,9 +73,10 @@ public class TimeoutMap<K, V> extends AbstractDecoratedMap<K, V> implements Expi
/**
* Creates a {@code TimeoutMap} with the default expiry time of 1 minute.
* This {@code TimeoutMap} will be backed by a new {@code HashMap} instance.
* <p/>
* <small>This is constructor is here to comply with the reccomendations for
* <p>
* <small>This is constructor is here to comply with the recommendations for
* "standard" constructors in the {@code Map} interface.</small>
* </p>
*
* @see #TimeoutMap(long)
*/
@@ -88,9 +89,10 @@ public class TimeoutMap<K, V> extends AbstractDecoratedMap<K, V> implements Expi
* with the default expiry time of 1 minute.
* This {@code TimeoutMap} will be backed by a new {@code HashMap} instance,
* and <em>not</em> the map passed in as a paramter.
* <p/>
* <small>This is constructor is here to comply with the reccomendations for
* <p>
* <small>This is constructor is here to comply with the recommendations for
* "standard" constructors in the {@code Map} interface.</small>
* </p>
*
* @param pContents the map whose mappings are to be placed in this map.
* May be {@code null}.
@@ -115,10 +117,11 @@ public class TimeoutMap<K, V> extends AbstractDecoratedMap<K, V> implements Expi
/**
* Creates a {@code TimeoutMap} with the given expiry time (milliseconds).
* This {@code TimeoutMap} will be backed by the given {@code Map}.
* <P/>
* <EM>Note that structurally modifying the backing map directly (not
* <p>
* <em>Note that structurally modifying the backing map directly (not
* through this map or its collection views), is not allowed, and will
* produce undeterministic exceptions.</EM>
* produce undeterministic exceptions.</em>
* </p>
*
* @param pBacking the map that will be used as backing.
* @param pContents the map whose mappings are to be placed in this map.
@@ -300,10 +303,9 @@ public class TimeoutMap<K, V> extends AbstractDecoratedMap<K, V> implements Expi
/**
* Okay, I guess this do resemble DCL...
*
* @todo Write some exhausting multi-threaded unit-tests.
*
* @param pTime now
*/
// TODO: Write some exhausting multi-threaded unit-tests.
private synchronized void removeExpiredEntriesSynced(long pTime) {
if (pTime > nextExpiryTime) {
////
@@ -35,7 +35,6 @@ import java.util.Iterator;
/**
* TokenIterator, Iterator-based replacement for StringTokenizer.
* <p/>
*
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-core/src/main/java/com/twelvemonkeys/util/TokenIterator.java#1 $
@@ -39,12 +39,13 @@ import java.util.Map;
/**
* The converter (singleton). Converts strings to objects and back.
* This is the entry point to the converter framework.
* <p/>
* <p>
* By default, converters for {@link com.twelvemonkeys.util.Time}, {@link Date}
* and {@link Object}
* (the {@link DefaultConverter}) are registered by this class' static
* initializer. You might remove them using the
* {@code unregisterConverter} method.
* </p>
*
* @see #registerConverter(Class, PropertyConverter)
* @see #unregisterConverter(Class)
@@ -105,12 +106,13 @@ public abstract class Converter implements PropertyConverter {
* Registers a converter for a given type.
* This converter will also be used for all subclasses, unless a more
* specific version is registered.
* </p>
* <p>
* By default, converters for {@link com.twelvemonkeys.util.Time}, {@link Date}
* and {@link Object}
* (the {@link DefaultConverter}) are registered by this class' static
* initializer. You might remove them using the
* {@code unregisterConverter} method.
* </p>
*
* @param pType the (super) type to register a converter for
* @param pConverter the converter
@@ -41,9 +41,10 @@ import java.util.Locale;
/**
* Converts strings to dates and back.
* <p/>
* <p>
* <small>This class has a static cache of {@code DateFormats}, to avoid
* creation and parsing of date formats every time one is used.</small>
* </p>
*
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
* @author last modified by $Author: haku $
@@ -38,12 +38,13 @@ import java.lang.reflect.InvocationTargetException;
/**
* Converts strings to objects and back.
* <p/>
* <p>
* This converter first tries to create an object, using the class' single
* string argument constructor ({@code &lt;type&gt;(String)}) if found,
* otherwise, an attempt to call
* the class' static {@code valueOf(String)} method. If both fails, a
* {@link ConversionException} is thrown.
* </p>
*
* @author <A href="haraldk@iconmedialab.no">Harald Kuhr</A>
* @author last modified by $Author: haku $
@@ -43,9 +43,10 @@ import java.util.Map;
/**
* Converts strings to numbers and back.
* <p/>
* <p>
* <small>This class has a static cache of {@code NumberFormats}, to avoid
* creation and parsing of number formats every time one is used.</small>
* </p>
*
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
* @author last modified by $Author: haku $
@@ -36,9 +36,10 @@ import com.twelvemonkeys.util.TimeFormat;
/**
* Converts strings to times and back.
* <p/>
* <p>
* <small>This class has a static cache of {@code TimeFormats}, to avoid creation and
* parsing of timeformats every time one is used.</small>
* </p>
*
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
* @author last modified by $Author: haku $
@@ -40,8 +40,8 @@ import java.util.regex.PatternSyntaxException;
/**
* {@code StringTokenizer} replacement, that uses regular expressions to split
* strings into tokens.
* <p/>
* @see java.util.regex.Pattern for pattern syntax.
*
*@see java.util.regex.Pattern for pattern syntax.
*
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-core/src/main/java/com/twelvemonkeys/util/regex/RegExTokenIterator.java#1 $
@@ -35,34 +35,32 @@ import java.io.PrintStream;
/**
* This class parses arbitrary strings against a wildcard string mask provided.
* The wildcard characters are '*' and '?'.
* <p/>
* <p>
* The string masks provided are treated as case sensitive.<br>
* Null-valued string masks as well as null valued strings to be parsed, will lead to rejection.
* <p/>
* <p/>
* <p/>
* </p>
* <p>
* <i>This class is custom designed for wildcard string parsing and is several times faster than the implementation based on the Jakarta Regexp package.</i>
* <p/>
* <p><hr style="height=1"><p>
* <p/>
* </p>
* <hr style="height=1">
* <p>
* This task is performed based on regular expression techniques.
* The possibilities of string generation with the well-known wildcard characters stated above,
* represent a subset of the possibilities of string generation with regular expressions.<br>
* The '*' corresponds to ([Union of all characters in the alphabet])*<br>
* The '?' corresponds to ([Union of all characters in the alphabet])<br>
* &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<small>These expressions are not suited for textual representation at all, I must say. Is there any math tags included in HTML?</small>
* <p/>
* <p/>
* <p/>
* </p>
* <p>
* The complete meta-language for regular expressions are much larger.
* This fact makes it fairly straightforward to build data structures for parsing because the amount of rules of building these structures are quite limited, as stated below.
* <p/>
* <p/>
* <p/>
* </p>
* <p>
* To bring this over to mathematical terms:
* The parser ia a <b>nondeterministic finite automaton</b> (latin) representing the <b>grammar</b> which is stated by the string mask.
* The <b>language</b> accepted by this automaton is the set of all strings accepted by this automaton.<br>
* The formal automaton quintuple consists of:
* </p>
* <ol>
* <li>A finite set of <b>states</b>, depending on the wildcard string mask.
* For each character in the mask a state representing that character is created.
@@ -92,11 +90,11 @@ import java.io.PrintStream;
* Parsing faults must be reported to the author.
* </small>
* </ol>
* <p/>
* <p><hr style="height=1"><p>
* <p/>
* <hr style="height=1">
* <p>
* Examples of usage:<br>
* This example will return "Accepted!".
* </p>
* <pre>
* WildcardStringParser parser = new WildcardStringParser("*_28????.jp*");
* if (parser.parseString("gupu_280915.jpg")) {
@@ -105,12 +103,10 @@ import java.io.PrintStream;
* System.out.println("Not accepted!");
* }
* </pre>
* <p/>
* <p><hr style="height=1"><p>
* <p/>
* <hr style="height=1">
* <p>
* Theories and concepts are based on the book <i>Elements of the Theory of Computation</i>, by Harry l. Lewis and Christos H. Papadimitriou, (c) 1981 by Prentice Hall.
* <p/>
* <p/>
* </p>
*
* @author <a href="mailto:eirik.torske@iconmedialab.no">Eirik Torske</a>
* @deprecated Will probably be removed in the near future
@@ -146,7 +142,6 @@ public class WildcardStringParser {
/**
* Creates a wildcard string parser.
* <p/>
*
* @param pStringMask the wildcard string mask.
*/
@@ -156,7 +151,6 @@ public class WildcardStringParser {
/**
* Creates a wildcard string parser.
* <p/>
*
* @param pStringMask the wildcard string mask.
* @param pDebugging {@code true} will cause debug messages to be emitted to {@code System.out}.
@@ -167,7 +161,6 @@ public class WildcardStringParser {
/**
* Creates a wildcard string parser.
* <p/>
*
* @param pStringMask the wildcard string mask.
* @param pDebugging {@code true} will cause debug messages to be emitted.
@@ -313,7 +306,6 @@ public class WildcardStringParser {
/**
* Gets the string mask that was used when building the parser atomaton.
* <p/>
*
* @return the string mask used for building the parser automaton.
*/
@@ -323,7 +315,6 @@ public class WildcardStringParser {
/**
* Parses a string according to the rules stated above.
* <p/>
*
* @param pStringToParse the string to parse.
* @return {@code true} if and only if the string are accepted by the automaton.
@@ -32,10 +32,11 @@ package com.twelvemonkeys.util.service;
/**
* An optional interface that may be implemented by service provider objects.
* <p/>
* <p>
* If this interface is implemented, the service provider objects will receive
* notification of registration and deregistration from the
* {@code ServiceRegistry}.
* </p>
*
* @see ServiceRegistry
*
@@ -33,7 +33,7 @@ package com.twelvemonkeys.util.service;
/**
* Error thrown by the {@code ServiceRegistry} in case of a configuration
* error.
* <p/>
*
* @see ServiceRegistry
*
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
@@ -39,26 +39,32 @@ import java.util.*;
/**
* A registry for service provider objects.
* <p/>
* <p>
* Service providers are looked up from the classpath, under the path
* {@code META-INF/services/}&lt;full-class-name&gt;.
* <p/>
* For example:<br/>
* </p>
* <p>
* For example:
* <br>
* {@code META-INF/services/com.company.package.spi.MyService}.
* <p/>
* </p>
* <p>
* The file should contain a list of fully-qualified concrete class names,
* one per line.
* <p/>
* </p>
* <p>
* The <em>full-class-name</em> represents an interface or (typically) an
* abstract class, and is the same class used as the category for this registry.
* Note that only one instance of a concrete subclass may be registered with a
* specific category at a time.
* <p/>
* </p>
* <p>
* <small>Implementation detail: This class is a clean room implementation of
* a service registry and does not use the proprietary {@code sun.misc.Service}
* class that is referred to in the <em>JAR File specification</em>.
* This class should work on any Java platform.
* </small>
* </p>
*
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
* @version $Id: com/twelvemonkeys/util/service/ServiceRegistry.java#2 $
@@ -80,9 +86,10 @@ public class ServiceRegistry {
/**
* Creates a {@code ServiceRegistry} instance with a set of categories
* taken from the {@code pCategories} argument.
* <p/>
* <p>
* The categories are constant during the lifetime of the registry, and may
* not be changed after initial creation.
* </p>
*
* @param pCategories an {@code Iterator} containing
* {@code Class} objects that defines this registry's categories.
@@ -187,15 +194,17 @@ public class ServiceRegistry {
/**
* Returns an {@code Iterator} containing all providers in the given
* category.
* <p/>
* <p>
* The iterator supports removal.
* <p/>
* </p>
* <p>
* <small>
* NOTE: Removing a provider from the iterator, deregisters the current
* provider (as returned by the last invocation of {@code next()}) from
* {@code pCategory}, it does <em>not</em> remove the provider
* from other categories in the registry.
* </small>
* </p>
*
* @param pCategory the category class
* @return an {@code Iterator} containing all providers in the given
@@ -209,8 +218,9 @@ public class ServiceRegistry {
/**
* Returns an {@code Iterator} containing all categories in this registry.
* <p/>
* <p>
* The iterator does not support removal.
* </p>
*
* @return an {@code Iterator} containing all categories in this registry.
*/
@@ -221,8 +231,9 @@ public class ServiceRegistry {
/**
* Returns an {@code Iterator} containing all categories in this registry
* the given {@code pProvider} <em>may be registered with</em>.
* <p/>
* <p>
* The iterator does not support removal.
* </p>
*
* @param pProvider the provider instance
* @return an {@code Iterator} containing all categories in this registry
@@ -240,15 +251,17 @@ public class ServiceRegistry {
/**
* Returns an {@code Iterator} containing all categories in this registry
* the given {@code pProvider} <em>is currently registered with</em>.
* <p/>
* <p>
* The iterator supports removal.
* <p/>
* </p>
* <p>
* <small>
* NOTE: Removing a category from the iterator, de-registers
* {@code pProvider} from the current category (as returned by the last
* invocation of {@code next()}), it does <em>not</em> remove the category
* itself from the registry.
* </small>
* </p>
*
* @param pProvider the provider instance
* @return an {@code Iterator} containing all categories in this registry
@@ -30,9 +30,10 @@
/**
* Provides a service provider registry.
* <p/>
* <p>
* This package contains a service provider registry, as specified in the
* <a href="http://java.sun.com/j2se/1.3/docs/guide/jar/jar.html#Service%20Provider">JAR File Specification</a>.
* </p>
*
* @see <a href="http://java.sun.com/j2se/1.3/docs/guide/jar/jar.html#Service%20Provider">JAR File Specification</a>
*/
@@ -36,13 +36,12 @@ import java.util.Map;
/**
* BeanMapTestCase
* <p/>
* @todo Extend with BeanMap specific tests
*
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
* @author last modified by $Author: haku $
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-core/src/test/java/com/twelvemonkeys/util/BeanMapTestCase.java#2 $
*/
// TODO: Extend with BeanMap specific tests
public class BeanMapTest extends MapAbstractTest {
public boolean isPutAddSupported() {
+1 -1
View File
@@ -4,7 +4,7 @@
<parent>
<groupId>com.twelvemonkeys</groupId>
<artifactId>twelvemonkeys</artifactId>
<version>3.4</version>
<version>3.4.4-SNAPSHOT</version>
</parent>
<groupId>com.twelvemonkeys.common</groupId>
<artifactId>common</artifactId>
+1 -1
View File
@@ -4,7 +4,7 @@
<parent>
<groupId>com.twelvemonkeys</groupId>
<artifactId>twelvemonkeys</artifactId>
<version>3.4</version>
<version>3.4.4-SNAPSHOT</version>
</parent>
<groupId>com.twelvemonkeys.contrib</groupId>
<artifactId>contrib</artifactId>
+1 -1
View File
@@ -4,7 +4,7 @@
<parent>
<groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio</artifactId>
<version>3.4</version>
<version>3.4.4-SNAPSHOT</version>
</parent>
<artifactId>imageio-batik</artifactId>
<name>TwelveMonkeys :: ImageIO :: Batik Plugin</name>
@@ -46,6 +46,7 @@ import org.apache.batik.gvt.renderer.ImageRendererFactory;
import org.apache.batik.transcoder.*;
import org.apache.batik.transcoder.image.ImageTranscoder;
import org.apache.batik.util.ParsedURL;
import org.apache.batik.util.SVGConstants;
import org.w3c.dom.DOMImplementation;
import org.w3c.dom.Document;
import org.w3c.dom.svg.SVGSVGElement;
@@ -68,7 +69,6 @@ import java.util.Map;
/**
* Image reader for SVG document fragments.
* <p/>
*
* @author Harald Kuhr
* @author Inpspired by code from the Batik Team
@@ -110,24 +110,25 @@ public class SVGImageReader extends ImageReaderBase {
public BufferedImage read(int pIndex, ImageReadParam pParam) throws IOException {
checkBounds(pIndex);
String baseURI = null;
if (pParam instanceof SVGReadParam) {
SVGReadParam svgParam = (SVGReadParam) pParam;
// Set IIOParams as hints
// Get the base URI
// This must be done before converting the params to hints
String baseURI = svgParam.getBaseURI();
rasterizer.transcoderInput.setURI(baseURI);
// Set ImageReadParams as hints
// Note: The cast to Map invokes a different method that preserves
// unset defaults, DO NOT REMOVE!
rasterizer.setTranscodingHints((Map) paramsToHints(svgParam));
// Get the base URI (not a hint)
baseURI = svgParam.getBaseURI();
}
Dimension size;
if (pParam != null && (size = pParam.getSourceRenderSize()) != null) {
// Use size...
Dimension size = null;
if (pParam != null) {
size = pParam.getSourceRenderSize();
}
else {
if (size == null) {
size = new Dimension(getWidth(pIndex), getHeight(pIndex));
}
@@ -137,7 +138,6 @@ public class SVGImageReader extends ImageReaderBase {
try {
processImageStarted(pIndex);
rasterizer.transcoderInput.setURI(baseURI);
BufferedImage image = rasterizer.getImage();
Graphics2D g = destination.createGraphics();
@@ -155,10 +155,16 @@ public class SVGImageReader extends ImageReaderBase {
return destination;
}
catch (TranscoderException e) {
throw new IIOException(e.getMessage(), e);
Throwable cause = unwrapException(e);
throw new IIOException(cause.getMessage(), cause);
}
}
private static Throwable unwrapException(TranscoderException ex) {
// The TranscoderException is generally useless...
return ex.getException() != null ? ex.getException() : ex;
}
private TranscodingHints paramsToHints(SVGReadParam pParam) throws IOException {
TranscodingHints hints = new TranscodingHints();
// Note: We must allow generic ImageReadParams, so converting to
@@ -174,8 +180,8 @@ public class SVGImageReader extends ImageReaderBase {
}
if (size != null) {
hints.put(ImageTranscoder.KEY_WIDTH, new Float(size.getWidth()));
hints.put(ImageTranscoder.KEY_HEIGHT, new Float(size.getHeight()));
hints.put(ImageTranscoder.KEY_WIDTH, (float) size.getWidth());
hints.put(ImageTranscoder.KEY_HEIGHT, (float) size.getHeight());
}
// Set area of interest
@@ -185,16 +191,16 @@ public class SVGImageReader extends ImageReaderBase {
// Avoid that the batik transcoder scales the AOI up to original image size
if (size == null) {
hints.put(ImageTranscoder.KEY_WIDTH, new Float(region.getWidth()));
hints.put(ImageTranscoder.KEY_HEIGHT, new Float(region.getHeight()));
hints.put(ImageTranscoder.KEY_WIDTH, (float) region.getWidth());
hints.put(ImageTranscoder.KEY_HEIGHT, (float) region.getHeight());
}
else {
// Need to resize here...
double xScale = size.getWidth() / origSize.getWidth();
double yScale = size.getHeight() / origSize.getHeight();
hints.put(ImageTranscoder.KEY_WIDTH, new Float(region.getWidth() * xScale));
hints.put(ImageTranscoder.KEY_HEIGHT, new Float(region.getHeight() * yScale));
hints.put(ImageTranscoder.KEY_WIDTH, (float) (region.getWidth() * xScale));
hints.put(ImageTranscoder.KEY_HEIGHT, (float) (region.getHeight() * yScale));
}
}
else if (size != null) {
@@ -219,7 +225,7 @@ public class SVGImageReader extends ImageReaderBase {
return null;
}
public ImageReadParam getDefaultReadParam() {
public SVGReadParam getDefaultReadParam() {
return new SVGReadParam();
}
@@ -249,13 +255,14 @@ public class SVGImageReader extends ImageReaderBase {
/**
* An image transcoder that stores the resulting image.
* <p/>
* <p>
* NOTE: This class includes a lot of copy and paste code from the Batik classes
* and needs major refactoring!
* </p>
*/
private class Rasterizer extends SVGAbstractTranscoder /*ImageTranscoder*/ {
BufferedImage image = null;
private BufferedImage image;
private TranscoderInput transcoderInput;
private float defaultWidth;
private float defaultHeight;
@@ -266,17 +273,19 @@ public class SVGImageReader extends ImageReaderBase {
private TranscoderException exception;
private BridgeContext context;
public BufferedImage createImage(final int width, final int height) {
return ImageUtil.createTransparent(width, height);//, BufferedImage.TYPE_INT_ARGB);
private BufferedImage createImage(final int width, final int height) {
return ImageUtil.createTransparent(width, height); // BufferedImage.TYPE_INT_ARGB
}
// This is cheating... We don't fully transcode after all
protected void transcode(Document document, final String uri, final TranscoderOutput output) throws TranscoderException {
// Sets up root, curTxf & curAoi
// ----
if ((document != null) && !(document.getImplementation() instanceof SVGDOMImplementation)) {
DOMImplementation impl = (DOMImplementation) hints.get(KEY_DOM_IMPLEMENTATION);
document = DOMUtilities.deepCloneDocument(document, impl);
if (document != null) {
if (!(document.getImplementation() instanceof SVGDOMImplementation)) {
DOMImplementation impl = (DOMImplementation) hints.get(KEY_DOM_IMPLEMENTATION);
document = DOMUtilities.deepCloneDocument(document, impl);
}
if (uri != null) {
try {
@@ -318,7 +327,7 @@ public class SVGImageReader extends ImageReaderBase {
// get the 'width' and 'height' attributes of the SVG document
Dimension2D docSize = ctx.getDocumentSize();
if (docSize != null) {
if (docSize != null) {
defaultWidth = (float) docSize.getWidth();
defaultHeight = (float) docSize.getHeight();
}
@@ -326,6 +335,14 @@ public class SVGImageReader extends ImageReaderBase {
defaultWidth = 200;
defaultHeight = 200;
}
SVGSVGElement rootElement = svgDoc.getRootElement();
String viewBoxStr = rootElement.getAttributeNS
(null, SVGConstants.SVG_VIEW_BOX_ATTRIBUTE);
if (viewBoxStr.length() != 0) {
float[] rect = ViewBox.parseViewBoxAttribute(rootElement, viewBoxStr, null);
defaultWidth = rect[2];
defaultHeight = rect[3];
}
// Hack to work around exception above
if (root != null) {
@@ -346,8 +363,8 @@ public class SVGImageReader extends ImageReaderBase {
processReadAborted();
return null;
}
processImageProgress(10f);
processImageProgress(10f);
// Hacky workaround below...
if (gvtRoot == null) {
@@ -369,6 +386,7 @@ public class SVGImageReader extends ImageReaderBase {
}
ctx = context;
// /Hacky
if (abortRequested()) {
processReadAborted();
return null;
@@ -489,11 +507,9 @@ public class SVGImageReader extends ImageReaderBase {
// now we are sure that the aoi is the image size
Shape raoi = new Rectangle2D.Float(0, 0, width, height);
// Warning: the renderer's AOI must be in user space
renderer.repaint(curTxf.createInverse().
createTransformedShape(raoi));
renderer.repaint(curTxf.createInverse().createTransformedShape(raoi));
// NOTE: repaint above cause nullpointer exception with fonts..???
BufferedImage rend = renderer.getOffScreen();
renderer = null; // We're done with it...
@@ -558,18 +574,40 @@ public class SVGImageReader extends ImageReaderBase {
return image;
}
protected int getDefaultWidth() throws TranscoderException {
int getDefaultWidth() throws TranscoderException {
init();
return (int) (defaultWidth + 0.5);
return (int) Math.ceil(defaultWidth);
}
protected int getDefaultHeight() throws TranscoderException {
int getDefaultHeight() throws TranscoderException {
init();
return (int) (defaultHeight + 0.5);
return (int) Math.ceil(defaultHeight);
}
public void setInput(final TranscoderInput pInput) {
void setInput(final TranscoderInput pInput) {
transcoderInput = pInput;
}
@Override
protected UserAgent createUserAgent() {
return new SVGImageReaderUserAgent();
}
private class SVGImageReaderUserAgent extends SVGAbstractTranscoderUserAgent {
@Override
public void displayError(Exception e) {
displayError(e.getMessage());
}
@Override
public void displayError(String message) {
displayMessage(message);
}
@Override
public void displayMessage(String message) {
processWarningOccurred(message.replaceAll("[\\r\\n]+", " "));
}
}
}
}

Some files were not shown because too many files have changed in this diff Show More