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 language: java
jdk: jdk:
- oraclejdk8 - 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) 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). [Release notes](https://github.com/haraldk/TwelveMonkeys/releases/latest).
## About ## About
@@ -56,9 +56,9 @@ Mainstream format support
* `javax_imageio_jpeg_image_1.0` format (currently as native format, may change in the future) * `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 * 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) "MarkerSequence" tag for the unsupported segments (for `javax_imageio_jpeg_image_1.0` format)
* Extended write support in progress: * Extended write support:
* CMYK JPEGs * CMYK JPEGs
* YCCK JPEGs * YCCK JPEGs in progress
#### JPEG-2000 #### JPEG-2000
@@ -206,6 +206,7 @@ Legacy formats
* Uncompressed * Uncompressed
* RLE compressed * RLE compressed
* Standard metadata support * Standard metadata support
* Write support
Icon/other formats Icon/other formats
@@ -215,6 +216,7 @@ Icon/other formats
* All known "native" icon types * All known "native" icon types
* Large PNG encoded icons * Large PNG encoded icons
* Large JPEG 2000 encoded icons (requires JPEG 2000 ImageIO plugin or fallback to `sips` command line tool) * 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 #### ICO & CUR - MS Windows Icon and Cursor Formats
@@ -223,6 +225,7 @@ Icon/other formats
* ICO RGB, 16, 24 and 32 bit * ICO RGB, 16, 24 and 32 bit
* CUR Indexed color, 1, 4 and 8 bit * CUR Indexed color, 1, 4 and 8 bit
* CUR RGB, 16, 24 and 32 bit * CUR RGB, 16, 24 and 32 bit
* Write support
* *3.1* Note: These formats are now part of the BMP plugin * *3.1* Note: These formats are now part of the BMP plugin
#### Thumbs.db - MS Windows Thumbs DB #### 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: If you need more control of read parameters and the reading process, the common idiom for reading is something like:
```java
// Create input stream // Create input stream
ImageInputStream input = ImageIO.createImageInputStream(file); 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 // Close stream in finally block to avoid resource leaks
input.close(); input.close();
} }
```
Query the reader for source image dimensions using `reader.getWidth(n)` and `reader.getHeight(n)` without reading the Query the reader for source image dimensions using `reader.getWidth(n)` and `reader.getHeight(n)` without reading the
entire image into memory first. 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: If you need more control of write parameters and the writing process, the common idiom for writing is something like:
```java
// Get the writer // Get the writer
Iterator<ImageWriter> writers = ImageIO.getImageWritersByFormatName(format); 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 // Dispose writer in finally block to avoid memory leaks
writer.dispose(); writer.dispose();
} }
```
For more advanced usage, and information on how to use the ImageIO API, I suggest you read the For more advanced usage, and information on how to use the ImageIO API, I suggest you read the
[Java Image I/O API Guide](http://docs.oracle.com/javase/7/docs/technotes/guides/imageio/spec/imageio_guideTOC.fm.html) [Java Image I/O API Guide](http://docs.oracle.com/javase/7/docs/technotes/guides/imageio/spec/imageio_guideTOC.fm.html)
@@ -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 it is *strongly recommended* to use the `IIOProviderContextListener` that implements
dynamic loading and unloading of ImageIO plugins for web applications. dynamic loading and unloading of ImageIO plugins for web applications.
```xml
<web-app ...> <web-app ...>
... ...
@@ -388,6 +396,7 @@ dynamic loading and unloading of ImageIO plugins for web applications.
... ...
</web-app> </web-app>
```
Loading plugins from `WEB-INF/lib` without the context listener installed is unsupported and will not work correctly. 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 The library comes with a resampling (image resizing) operation, that contains many different algorithms
to provide excellent results at reasonable speed. to provide excellent results at reasonable speed.
```java
import com.twelvemonkeys.image.ResampleOp; 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 BufferedImageOp resampler = new ResampleOp(width, height, ResampleOp.FILTER_LANCZOS); // A good default filter, see class documentation for more info
BufferedImage output = resampler.filter(input, null); BufferedImage output = resampler.filter(input, null);
```
#### Using the DiffusionDither #### Using the DiffusionDither
The library comes with a dithering operation, that can be used to convert `BufferedImage`s to `IndexColorModel` using The library comes with a dithering operation, that can be used to convert `BufferedImage`s to `IndexColorModel` using
Floyd-Steinberg error-diffusion dither. Floyd-Steinberg error-diffusion dither.
```java
import com.twelvemonkeys.image.DiffusionDither; import com.twelvemonkeys.image.DiffusionDither;
... ...
@@ -425,7 +436,7 @@ Floyd-Steinberg error-diffusion dither.
BufferedImageOp ditherer = new DiffusionDither(); BufferedImageOp ditherer = new DiffusionDither();
BufferedImage output = ditherer.filter(input, null); BufferedImage output = ditherer.filter(input, null);
```
## Building ## 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: 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"); Iterator<ImageReader> readers = ImageIO.getImageReadersByFormatName("JPEG");
while (readers.hasNext()) { while (readers.hasNext()) {
System.out.println("reader: " + readers.next()); System.out.println("reader: " + readers.next());
} }
```
The first line should print: The first line should print:
@@ -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: To depend on the JPEG and TIFF plugin using Maven, add the following to your POM:
```xml
... ...
<dependencies> <dependencies>
... ...
<dependency> <dependency>
<groupId>com.twelvemonkeys.imageio</groupId> <groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio-jpeg</artifactId> <artifactId>imageio-jpeg</artifactId>
<version>3.3.2</version> <!-- Alternatively, build your own version --> <version>3.4.1</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.twelvemonkeys.imageio</groupId> <groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio-tiff</artifactId> <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> </dependency>
</dependencies> </dependencies>
```
#### Manual dependency example #### Manual dependency example
To depend on the JPEG and TIFF plugin in your IDE or program, add all of the following JARs to your class path: To depend on the JPEG and TIFF plugin in your IDE or program, add all of the following JARs to your class path:
twelvemonkeys-common-lang-3.3.2.jar twelvemonkeys-common-lang-3.4.1.jar
twelvemonkeys-common-io-3.3.2.jar twelvemonkeys-common-io-3.4.1.jar
twelvemonkeys-common-image-3.3.2.jar twelvemonkeys-common-image-3.4.1.jar
twelvemonkeys-imageio-core-3.3.2.jar twelvemonkeys-imageio-core-3.4.1.jar
twelvemonkeys-imageio-metadata-3.3.2.jar twelvemonkeys-imageio-metadata-3.4.1.jar
twelvemonkeys-imageio-jpeg-3.3.2.jar twelvemonkeys-imageio-jpeg-3.4.1.jar
twelvemonkeys-imageio-tiff-3.3.2.jar twelvemonkeys-imageio-tiff-3.4.1.jar
### Links to prebuilt binaries ### Links to prebuilt binaries
##### Latest version (3.2.x) ##### Latest version (3.4.1)
Requires Java 7 or later. Requires Java 7 or later.
Common dependencies 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-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.3.2.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/common/common-io/3.3.2/common-io-3.3.2.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.3.2.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/common/common-image/3.3.2/common-image-3.3.2.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 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-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.3.2.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-metadata/3.3.2/imageio-metadata-3.3.2.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 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-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.3.2.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-jpeg/3.3.2/imageio-jpeg-3.3.2.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.3.2.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-tiff/3.3.2/imageio-tiff-3.3.2.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.3.2.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-pnm/3.3.2/imageio-pnm-3.3.2.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.3.2.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-psd/3.3.2/imageio-psd-3.3.2.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.3.2.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-hdr/3.3.2/imageio-hdr-3.3.2.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.3.2.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-iff/3.3.2/imageio-iff-3.3.2.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.3.2.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-pcx/3.3.2/imageio-pcx-3.3.2.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.3.2.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-pict/3.3.2/imageio-pict-3.3.2.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.3.2.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-sgi/3.3.2/imageio-sgi-3.3.2.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.3.2.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-tga/3.3.2/imageio-tga-3.3.2.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.3.2.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-icns/3.3.2/imageio-icns-3.3.2.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.3.2.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-thumbsdb/3.3.2/imageio-thumbsdb-3.3.2.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 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 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 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) ##### 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): 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. All rights reserved.
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met: modification, are permitted provided that the following conditions are met:
o Redistributions of source code must retain the above copyright o Redistributions of source code must retain the above copyright notice, this
notice, this list of conditions and the following disclaimer. list of conditions and the following disclaimer.
o Redistributions in binary form must reproduce the above copyright o Redistributions in binary form must reproduce the above copyright notice,
notice, this list of conditions and the following disclaimer in the this list of conditions and the following disclaimer in the documentation
documentation and/or other materials provided with the distribution. and/or other materials provided with the distribution.
o Neither the name "TwelveMonkeys" nor the o Neither the name of the copyright holder nor the names of its
names of its contributors may be used to endorse or promote products contributors may be used to endorse or promote products derived from
derived from this software without specific prior written permission. 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.
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 ## 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. 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 a: While great libraries with a wide range of formats support, the ImageMagick-based libraries has some disadvantages
compared to ImageIO. compared to ImageIO.
+1 -1
View File
@@ -5,7 +5,7 @@
<parent> <parent>
<groupId>com.twelvemonkeys</groupId> <groupId>com.twelvemonkeys</groupId>
<artifactId>twelvemonkeys</artifactId> <artifactId>twelvemonkeys</artifactId>
<version>3.4</version> <version>3.4.4-SNAPSHOT</version>
</parent> </parent>
<groupId>com.twelvemonkeys.bom</groupId> <groupId>com.twelvemonkeys.bom</groupId>
+1 -1
View File
@@ -4,7 +4,7 @@
<parent> <parent>
<groupId>com.twelvemonkeys.common</groupId> <groupId>com.twelvemonkeys.common</groupId>
<artifactId>common</artifactId> <artifactId>common</artifactId>
<version>3.4</version> <version>3.4.4-SNAPSHOT</version>
</parent> </parent>
<artifactId>common-image</artifactId> <artifactId>common-image</artifactId>
<packaging>jar</packaging> <packaging>jar</packaging>
@@ -37,7 +37,6 @@ import java.util.List;
/** /**
* AbstractImageSource * AbstractImageSource
* <p/>
* *
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</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/image/AbstractImageSource.java#1 $ * @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. * Adjusts the contrast and brightness of an image.
* <p/> * <p>
* For brightness, the valid range is {@code -2.0,..,0.0,..,2.0}. * For brightness, the valid range is {@code -2.0,..,0.0,..,2.0}.
* A value of {@code 0.0} means no change. * A value of {@code 0.0} means no change.
* Negative values will make the pixels darker. * Negative values will make the pixels darker.
* Maximum negative value ({@code -2}) will make all filtered pixels black. * Maximum negative value ({@code -2}) will make all filtered pixels black.
* Positive values will make the pixels brighter. * Positive values will make the pixels brighter.
* Maximum positive value ({@code 2}) will make all filtered pixels white. * 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}. * For contrast, the valid range is {@code -1.0,..,0.0,..,1.0}.
* A value of {@code 0.0} means no change. * A value of {@code 0.0} means no change.
* Negative values will reduce contrast. * Negative values will reduce contrast.
@@ -51,15 +52,14 @@ import java.awt.image.RGBImageFilter;
* Positive values will increase contrast. * Positive values will increase contrast.
* Maximum positive value ({@code 1}) will make all filtered pixels primary * Maximum positive value ({@code 1}) will make all filtered pixels primary
* colors (either black, white, cyan, magenta, yellow, red, blue or green). * colors (either black, white, cyan, magenta, yellow, red, blue or green).
* </p>
* *
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a> * @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
* @author last modified by $Author: haku $ * @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 $ * @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 { public class BrightnessContrastFilter extends RGBImageFilter {
// TODO: Replace with RescaleOp? // TODO: Replace with RescaleOp?
@@ -76,8 +76,9 @@ public class BrightnessContrastFilter extends RGBImageFilter {
/** /**
* Creates a BrightnessContrastFilter with default values * Creates a BrightnessContrastFilter with default values
* ({@code brightness=0.3, contrast=0.3}). * ({@code brightness=0.3, contrast=0.3}).
* <p/> * <p>
* This will slightly increase both brightness and contrast. * This will slightly increase both brightness and contrast.
* </p>
*/ */
public BrightnessContrastFilter() { public BrightnessContrastFilter() {
this(0.3f, 0.3f); this(0.3f, 0.3f);
@@ -86,14 +87,15 @@ public class BrightnessContrastFilter extends RGBImageFilter {
/** /**
* Creates a BrightnessContrastFilter with the given values for brightness * Creates a BrightnessContrastFilter with the given values for brightness
* and contrast. * and contrast.
* <p/> * <p>
* For brightness, the valid range is {@code -2.0,..,0.0,..,2.0}. * For brightness, the valid range is {@code -2.0,..,0.0,..,2.0}.
* A value of {@code 0.0} means no change. * A value of {@code 0.0} means no change.
* Negative values will make the pixels darker. * Negative values will make the pixels darker.
* Maximum negative value ({@code -2}) will make all filtered pixels black. * Maximum negative value ({@code -2}) will make all filtered pixels black.
* Positive values will make the pixels brighter. * Positive values will make the pixels brighter.
* Maximum positive value ({@code 2}) will make all filtered pixels white. * 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}. * For contrast, the valid range is {@code -1.0,..,0.0,..,1.0}.
* A value of {@code 0.0} means no change. * A value of {@code 0.0} means no change.
* Negative values will reduce contrast. * Negative values will reduce contrast.
@@ -102,6 +104,7 @@ public class BrightnessContrastFilter extends RGBImageFilter {
* Positive values will increase contrast. * Positive values will increase contrast.
* Maximum positive value ({@code 1}) will make all filtered pixels primary * Maximum positive value ({@code 1}) will make all filtered pixels primary
* colors (either black, white, cyan, magenta, yellow, red, blue or green). * colors (either black, white, cyan, magenta, yellow, red, blue or green).
* </p>
* *
* @param pBrightness adjust the brightness of the image, in the range * @param pBrightness adjust the brightness of the image, in the range
* {@code -2.0,..,0.0,..,2.0}. * {@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 * A faster, lighter and easier way to convert an {@code Image} to a
* {@code BufferedImage} than using a {@code PixelGrabber}. * {@code BufferedImage} than using a {@code PixelGrabber}.
* Clients may provide progress listeners to monitor conversion progress. * Clients may provide progress listeners to monitor conversion progress.
* <p/> * <p>
* Supports source image subsampling and source region extraction. * Supports source image subsampling and source region extraction.
* Supports source images with 16 bit {@link ColorModel} and * Supports source images with 16 bit {@link ColorModel} and
* {@link DataBuffer#TYPE_USHORT} transfer type, without converting to * {@link DataBuffer#TYPE_USHORT} transfer type, without converting to
* 32 bit/TYPE_INT. * 32 bit/TYPE_INT.
* <p/> * </p>
* <p>
* NOTE: Does not support images with more than one {@code ColorModel} or * NOTE: Does not support images with more than one {@code ColorModel} or
* different types of pixel data. This is not very common. * different types of pixel data. This is not very common.
* </p>
* *
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</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/image/BufferedImageFactory.java#1 $ * @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}. * An {@code Icon} implementation backed by a {@code BufferedImage}.
* <p/>
* *
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</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/image/BufferedImageIcon.java#2 $ * @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 * This {@code BufferedImageOp/RasterOp} implements basic
* Floyd-Steinberg error-diffusion algorithm for dithering. * 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: * The weights used are 7/16, 3/16, 5/16 and 1/16, distributed like this:
* <!-- - - * <!-- - -
* | |x|7| * | |x|7|
* - - - - * - - - -
* |3|5|1| * |3|5|1|
* - - --> * - - -->
* <P/> * </p>
* <TABLE border="1" cellpadding="4" cellspacing="0"> * <table border="1" cellpadding="4" cellspacing="0">
* <TR><TD bgcolor="#000000">&nbsp;</TD><TD class="TableHeadingColor" * <caption>Floyd-Steinberg error-diffusion weights</caption>
* align="center">X</TD><TD>7/16</TD></TR> * <tr><td bgcolor="#000000">&nbsp;</td><td class="TableHeadingColor"
* <TR><TD>3/16</TD><TD>5/16</TD><TD>1/16</TD></TR> * align="center">x</td><td>7/16</td></tr>
* </TABLE> * <tr><td>3/16</td><td>5/16</td><td>1/16</td></tr>
* <P/> * </table>
* <p>
* See <A href="http://www.awprofessional.com/bookstore/product.asp?isbn=0201848406&rl=1">Computer Graphics (Foley et al.)</a> * See <A href="http://www.awprofessional.com/bookstore/product.asp?isbn=0201848406&rl=1">Computer Graphics (Foley et al.)</a>
* for more information. * for more information.
* </p>
* *
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a> * @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
* @author last modified by $Author: haku $ * @author last modified by $Author: haku $
@@ -43,10 +43,11 @@ public final class GraphicsUtil {
/** /**
* Enables anti-aliasing in the {@code Graphics} object. * Enables anti-aliasing in the {@code Graphics} object.
* <p/> * <p>
* Anti-aliasing is enabled by casting to {@code Graphics2D} and setting * Anti-aliasing is enabled by casting to {@code Graphics2D} and setting
* the rendering hint {@code RenderingHints.KEY_ANTIALIASING} to * the rendering hint {@code RenderingHints.KEY_ANTIALIASING} to
* {@code RenderingHints.VALUE_ANTIALIAS_ON}. * {@code RenderingHints.VALUE_ANTIALIAS_ON}.
* </p>
* *
* @param pGraphics the graphics object * @param pGraphics the graphics object
* @throws ClassCastException if {@code pGraphics} is not an instance of * @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. * Sets the alpha in the {@code Graphics} object.
* <p/> * <p>
* Alpha is set by casting to {@code Graphics2D} and setting the composite * Alpha is set by casting to {@code Graphics2D} and setting the composite
* to the rule {@code AlphaComposite.SRC_OVER} multiplied by the given * to the rule {@code AlphaComposite.SRC_OVER} multiplied by the given
* alpha. * alpha.
* </p>
* *
* @param pGraphics the graphics object * @param pGraphics the graphics object
* @param pAlpha the alpha level, {@code alpha} must be a floating point * @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. * This class can convert a color image to grayscale.
* <P/> * <p>
* Uses ITU standard conversion: (222 * Red + 707 * Green + 71 * Blue) / 1000. * Uses ITU standard conversion: (222 * Red + 707 * Green + 71 * Blue) / 1000.
* </p>
* *
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a> * @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
* @author last modified by $Author: haku $ * @author last modified by $Author: haku $
@@ -64,7 +65,7 @@ public class GrayFilter extends RGBImageFilter {
* pLow and pHigh. * pLow and pHigh.
* *
* @param pLow float in the range 0..1 * @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) { public GrayFilter(float pLow, float pHigh) {
if (pLow > pHigh) { if (pLow > pHigh) {
@@ -94,7 +95,7 @@ public class GrayFilter extends RGBImageFilter {
* range between pLow and pHigh. * range between pLow and pHigh.
* *
* @param pLow integer in the range 0..255 * @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) { public GrayFilter(int pLow, int pHigh) {
this(pLow / 255f, pHigh / 255f); this(pLow / 255f, pHigh / 255f);
@@ -162,11 +162,12 @@ public final class ImageUtil {
/** /**
* The sharpen kernel. Uses the following 3 by 3 matrix: * The sharpen kernel. Uses the following 3 by 3 matrix:
* <TABLE border="1" cellspacing="0"> * <table border="1" cellspacing="0">
* <TR><TD>0.0</TD><TD>-0.3</TD><TD>0.0</TD></TR> * <caption>Sharpen Kernel Matrix</caption>
* <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>
* <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>
* </TABLE> * <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); 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}. * Converts the {@code RenderedImage} to a {@code BufferedImage}.
* The new image will have the <em>same</em> {@code ColorModel}, * The new image will have the <em>same</em> {@code ColorModel},
* {@code Raster} and properties as the original image, if possible. * {@code Raster} and properties as the original image, if possible.
* <p/> * <p>
* If the image is already a {@code BufferedImage}, it is simply returned * If the image is already a {@code BufferedImage}, it is simply returned
* and no conversion takes place. * and no conversion takes place.
* </p>
* *
* @param pOriginal the image to convert. * @param pOriginal the image to convert.
* *
@@ -262,9 +264,10 @@ public final class ImageUtil {
/** /**
* Converts the {@code RenderedImage} to a {@code BufferedImage} of the * Converts the {@code RenderedImage} to a {@code BufferedImage} of the
* given type. * given type.
* <p/> * <p>
* If the image is already a {@code BufferedImage} of the given type, it * If the image is already a {@code BufferedImage} of the given type, it
* is simply returned and no conversion takes place. * is simply returned and no conversion takes place.
* </p>
* *
* @param pOriginal the image to convert. * @param pOriginal the image to convert.
* @param pType the type of buffered image * @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 * Converts the {@code BufferedImage} to a {@code BufferedImage} of the
* given type. The new image will have the same {@code ColorModel}, * given type. The new image will have the same {@code ColorModel},
* {@code Raster} and properties as the original image, if possible. * {@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 * If the image is already a {@code BufferedImage} of the given type, it
* is simply returned and no conversion takes place. * is simply returned and no conversion takes place.
* <p/> * </p>
* <p>
* This method simply invokes * This method simply invokes
* {@link #toBuffered(RenderedImage,int) toBuffered((RenderedImage) pOriginal, pType)}. * {@link #toBuffered(RenderedImage,int) toBuffered((RenderedImage) pOriginal, pType)}.
* </p>
* *
* @param pOriginal the image to convert. * @param pOriginal the image to convert.
* @param pType the type of buffered image * @param pType the type of buffered image
@@ -333,9 +338,10 @@ public final class ImageUtil {
* Converts the {@code Image} to a {@code BufferedImage}. * Converts the {@code Image} to a {@code BufferedImage}.
* The new image will have the same {@code ColorModel}, {@code Raster} and * The new image will have the same {@code ColorModel}, {@code Raster} and
* properties as the original image, if possible. * properties as the original image, if possible.
* <p/> * <p>
* If the image is already a {@code BufferedImage}, it is simply returned * If the image is already a {@code BufferedImage}, it is simply returned
* and no conversion takes place. * and no conversion takes place.
* </p>
* *
* @param pOriginal the image to convert. * @param pOriginal the image to convert.
* *
@@ -389,19 +395,22 @@ public final class ImageUtil {
/** /**
* Creates a {@code WritableRaster} for the given {@code ColorModel} and * Creates a {@code WritableRaster} for the given {@code ColorModel} and
* pixel data. * pixel data.
* <p/> * <p>
* This method is optimized for the most common cases of {@code ColorModel} * This method is optimized for the most common cases of {@code ColorModel}
* and pixel data combinations. The raster's backing {@code DataBuffer} is * and pixel data combinations. The raster's backing {@code DataBuffer} is
* created directly from the pixel data, as this is faster and more * created directly from the pixel data, as this is faster and more
* resource-friendly than using * resource-friendly than using
* {@code ColorModel.createCompatibleWritableRaster(w, h)}. * {@code ColorModel.createCompatibleWritableRaster(w, h)}.
* <p/> * </p>
* <p>
* For uncommon combinations, the method will fallback to using * For uncommon combinations, the method will fallback to using
* {@code ColorModel.createCompatibleWritableRaster(w, h)} and * {@code ColorModel.createCompatibleWritableRaster(w, h)} and
* {@code WritableRaster.setDataElements(w, h, pixels)} * {@code WritableRaster.setDataElements(w, h, pixels)}
* <p/> * </p>
* <p>
* Note that the {@code ColorModel} and pixel data are <em>not</em> cloned * Note that the {@code ColorModel} and pixel data are <em>not</em> cloned
* (in most cases). * (in most cases).
* </p>
* *
* @param pWidth the requested raster width * @param pWidth the requested raster width
* @param pHeight the requested raster height * @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. * Converts the {@code Image} to a {@code BufferedImage} of the given type.
* The new image will have the same {@code ColorModel}, {@code Raster} and * The new image will have the same {@code ColorModel}, {@code Raster} and
* properties as the original image, if possible. * properties as the original image, if possible.
* <p/> * <p>
* If the image is already a {@code BufferedImage} of the given type, it * If the image is already a {@code BufferedImage} of the given type, it
* is simply returned and no conversion takes place. * is simply returned and no conversion takes place.
* </p>
* *
* @param pOriginal the image to convert. * @param pOriginal the image to convert.
* @param pType the type of buffered image * @param pType the type of buffered image
@@ -656,9 +666,10 @@ public final class ImageUtil {
* Rotates the image 90 degrees, clockwise (aka "rotate right"), * Rotates the image 90 degrees, clockwise (aka "rotate right"),
* counter-clockwise (aka "rotate left") or 180 degrees, depending on the * counter-clockwise (aka "rotate left") or 180 degrees, depending on the
* {@code pDirection} argument. * {@code pDirection} argument.
* <p/> * <p>
* The new image will be completely covered with pixels from the source * The new image will be completely covered with pixels from the source
* image. * image.
* </p>
* *
* @param pImage the source image. * @param pImage the source image.
* @param pDirection the direction, must be either {@link #ROTATE_90_CW}, * @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. * Sharpens an image using a convolution matrix.
* The sharpen kernel used, is defined by the following 3 by 3 matrix: * The sharpen kernel used, is defined by the following 3 by 3 matrix:
* <TABLE border="1" cellspacing="0"> * <table border="1" cellspacing="0">
* <TR><TD>0.0</TD><TD>-0.3</TD><TD>0.0</TD></TR> * <caption>Sharpen Kernel Matrix</caption>
* <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>
* <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>
* </TABLE> * <tr><td>0.0</td><td>-0.3</td><td>0.0</td></tr>
* <P/> * </table>
* <p>
* This is the same result returned as * This is the same result returned as
* {@code sharpen(pOriginal, 0.3f)}. * {@code sharpen(pOriginal, 0.3f)}.
* </p>
* *
* @param pOriginal the BufferedImage to sharpen * @param pOriginal the BufferedImage to sharpen
* *
@@ -1087,13 +1100,14 @@ public final class ImageUtil {
/** /**
* Sharpens an image using a convolution matrix. * Sharpens an image using a convolution matrix.
* The sharpen kernel used, is defined by the following 3 by 3 matrix: * The sharpen kernel used, is defined by the following 3 by 3 matrix:
* <TABLE border="1" cellspacing="0"> * <table border="1" cellspacing="0">
* <TR><TD>0.0</TD><TD>-{@code pAmount}</TD><TD>0.0</TD></TR> * <caption>Sharpen Kernel Matrix</caption>
* <TR><TD>-{@code pAmount}</TD> * <tr><td>0.0</td><td>-{@code pAmount}</td><td>0.0</td></tr>
* <TD>4.0 * {@code pAmount} + 1.0</TD> * <tr><td>-{@code pAmount}</td>
* <TD>-{@code pAmount}</TD></TR> * <td>4.0 * {@code pAmount} + 1.0</td>
* <TR><TD>0.0</TD><TD>-{@code pAmount}</TD><TD>0.0</TD></TR> * <td>-{@code pAmount}</td></tr>
* </TABLE> * <tr><td>0.0</td><td>-{@code pAmount}</td><td>0.0</td></tr>
* </table>
* *
* @param pOriginal the BufferedImage to sharpen * @param pOriginal the BufferedImage to sharpen
* @param pAmount the amount of sharpening * @param pAmount the amount of sharpening
@@ -101,32 +101,35 @@ import java.util.List;
* This class implements an adaptive palette generator to reduce images * This class implements an adaptive palette generator to reduce images
* to a variable number of colors. * to a variable number of colors.
* It can also render images into fixed color pallettes. * It can also render images into fixed color pallettes.
* <p/> * <p>
* Support for the default JVM (ordered/pattern) dither, Floyd-Steinberg like * Support for the default JVM (ordered/pattern) dither, Floyd-Steinberg like
* error-diffusion and no dither, controlled by the hints * error-diffusion and no dither, controlled by the hints
* {@link #DITHER_DIFFUSION}, * {@link #DITHER_DIFFUSION},
* {@link #DITHER_NONE} and * {@link #DITHER_NONE} and
* {@link #DITHER_DEFAULT}. * {@link #DITHER_DEFAULT}.
* <p/> * </p>
* <p>
* Color selection speed/accuracy can be controlled using the hints * Color selection speed/accuracy can be controlled using the hints
* {@link #COLOR_SELECTION_FAST}, * {@link #COLOR_SELECTION_FAST},
* {@link #COLOR_SELECTION_QUALITY} and * {@link #COLOR_SELECTION_QUALITY} and
* {@link #COLOR_SELECTION_DEFAULT}. * {@link #COLOR_SELECTION_DEFAULT}.
* <p/> * </p>
* <p>
* Transparency support can be controlled using the hints * Transparency support can be controlled using the hints
* {@link #TRANSPARENCY_OPAQUE}, * {@link #TRANSPARENCY_OPAQUE},
* {@link #TRANSPARENCY_BITMASK} and * {@link #TRANSPARENCY_BITMASK} and
* {@link #TRANSPARENCY_TRANSLUCENT}. * {@link #TRANSPARENCY_TRANSLUCENT}.
* <p/> * </p>
* <HR/> * <hr>
* <p/> * <p>
* <PRE> * <pre>
* This product includes software developed by the Apache Software Foundation. * This product includes software developed by the Apache Software Foundation.
* <p/> *
* This software consists of voluntary contributions made by many individuals * This software consists of voluntary contributions made by many individuals
* on behalf of the Apache Software Foundation. For more information on the * 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> * 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:deweese@apache.org">Thomas DeWeese</A>
* @author <A href="mailto:jun@oop-reserch.com">Jun Inamori</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 * {@code TYPE_INT_ARGB}) to an indexed image. Generating an adaptive
* palette (8 bit) from the color data in the image, and uses default * palette (8 bit) from the color data in the image, and uses default
* dither. * dither.
* <p/> * <p>
* The image returned is a new image, the input image is not modified. * 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. * @param pImage the BufferedImage to index and get color information from.
* @return the indexed BufferedImage. The image will be of type * @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. * adaptive palette (8 bit) from the given palette image.
* Dithering, transparency and color selection is controlled with the * Dithering, transparency and color selection is controlled with the
* {@code pHints}parameter. * {@code pHints}parameter.
* <p/> * <p>
* The image returned is a new image, the input image is not modified. * The image returned is a new image, the input image is not modified.
* </p>
* *
* @param pImage the BufferedImage to index * @param pImage the BufferedImage to index
* @param pPalette the Image to read color information from * @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 * {@code TYPE_INT_ARGB}) to an indexed image. Generating an adaptive
* palette with the given number of colors. * palette with the given number of colors.
* Dithering, transparency and color selection is controlled with the * Dithering, transparency and color selection is controlled with the
* {@code pHints}parameter. * {@code pHints} parameter.
* <p/> * <p>
* The image returned is a new image, the input image is not modified. * The image returned is a new image, the input image is not modified.
* </p>
* *
* @param pImage the BufferedImage to index * @param pImage the BufferedImage to index
* @param pNumberOfColors the number of colors for the image * @param pNumberOfColors the number of colors for the image
@@ -952,8 +958,9 @@ class IndexImage {
* {@code IndexColorModel}'s palette. * {@code IndexColorModel}'s palette.
* Dithering, transparency and color selection is controlled with the * Dithering, transparency and color selection is controlled with the
* {@code pHints} parameter. * {@code pHints} parameter.
* <p/> * <p>
* The image returned is a new image, the input image is not modified. * The image returned is a new image, the input image is not modified.
* </p>
* *
* @param pImage the BufferedImage to index * @param pImage the BufferedImage to index
* @param pColors an {@code IndexColorModel} containing the color information * @param pColors an {@code IndexColorModel} containing the color information
@@ -1069,8 +1076,9 @@ class IndexImage {
* palette with the given number of colors. * palette with the given number of colors.
* Dithering, transparency and color selection is controlled with the * Dithering, transparency and color selection is controlled with the
* {@code pHints}parameter. * {@code pHints}parameter.
* <p/> * <p>
* The image returned is a new image, the input image is not modified. * The image returned is a new image, the input image is not modified.
* </p>
* *
* @param pImage the BufferedImage to index * @param pImage the BufferedImage to index
* @param pNumberOfColors the number of colors for the image * @param pNumberOfColors the number of colors for the image
@@ -1099,8 +1107,9 @@ class IndexImage {
* {@code IndexColorModel}'s palette. * {@code IndexColorModel}'s palette.
* Dithering, transparency and color selection is controlled with the * Dithering, transparency and color selection is controlled with the
* {@code pHints}parameter. * {@code pHints}parameter.
* <p/> * <p>
* The image returned is a new image, the input image is not modified. * The image returned is a new image, the input image is not modified.
* </p>
* *
* @param pImage the BufferedImage to index * @param pImage the BufferedImage to index
* @param pColors an {@code IndexColorModel} containing the color information * @param pColors an {@code IndexColorModel} containing the color information
@@ -1130,8 +1139,9 @@ class IndexImage {
* adaptive palette (8 bit) from the given palette image. * adaptive palette (8 bit) from the given palette image.
* Dithering, transparency and color selection is controlled with the * Dithering, transparency and color selection is controlled with the
* {@code pHints}parameter. * {@code pHints}parameter.
* <p/> * <p>
* The image returned is a new image, the input image is not modified. * The image returned is a new image, the input image is not modified.
* </p>
* *
* @param pImage the BufferedImage to index * @param pImage the BufferedImage to index
* @param pPalette the Image to read color information from * @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 * Inverse Colormap to provide efficient lookup of any given input color
* to the closest match to the given color map. * to the closest match to the given color map.
* <p/> * <p>
* Based on "Efficient Inverse Color Map Computation" by Spencer W. Thomas * 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 <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
* @author Robin Luiten (Java port) * @author Robin Luiten (Java port)
@@ -41,11 +41,11 @@ import java.awt.image.BufferedImageOp;
* This class accelerates certain graphics operations, using * This class accelerates certain graphics operations, using
* JMagick and ImageMagick, if available. * JMagick and ImageMagick, if available.
* If those libraries are not installed, this class silently does nothing. * If those libraries are not installed, this class silently does nothing.
* <p/> * <p>
* Set the system property {@code "com.twelvemonkeys.image.accel"} to * Set the system property {@code "com.twelvemonkeys.image.accel"} to
* {@code false}, to disable, even if JMagick is installed. * {@code false}, to disable, even if JMagick is installed.
* Set the system property {@code "com.twelvemonkeys.image.magick.debug"} to * Set the system property {@code "com.twelvemonkeys.image.magick.debug"} to
* <p/> * </p>
* *
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</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/image/MagickAccelerator.java#3 $ * @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 * Utility for converting JMagick {@code MagickImage}s to standard Java
* {@code BufferedImage}s and back. * {@code BufferedImage}s and back.
* <p/> * <p>
* <em>NOTE: This class is considered an implementation detail and not part of * <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. * the public API. This class is subject to change without further notice.
* You have been warned. :-)</em> * You have been warned. :-)</em>
* </p>
* *
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</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/image/MagickUtil.java#4 $ * @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}. * Converts a {@code MagickImage} to a {@code BufferedImage}.
* <p/> * <p>
* The conversion depends on {@code pImage}'s {@code ImageType}: * The conversion depends on {@code pImage}'s {@code ImageType}:
* </p>
* <dl> * <dl>
* <dt>{@code ImageType.BilevelType}</dt> * <dt>{@code ImageType.BilevelType}</dt>
* <dd>{@code BufferedImage} of type {@code TYPE_BYTE_BINARY}</dd> * <dd>{@code BufferedImage} of type {@code TYPE_BYTE_BINARY}</dd>
@@ -113,15 +115,16 @@ public final class MagickUtil {
* *
* <dt>{@code ImageType.PaletteType}</dt> * <dt>{@code ImageType.PaletteType}</dt>
* <dd>{@code BufferedImage} of type {@code TYPE_BYTE_BINARY} (for images * <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> * <dt>{@code ImageType.PaletteMatteType}</dt>
* <dd>{@code BufferedImage} of type {@code TYPE_BYTE_BINARY} (for images * <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> * <dt>{@code ImageType.TrueColorType}</dt>
* <dd>{@code BufferedImage} of type {@code TYPE_3BYTE_BGR}</dd> * <dd>{@code BufferedImage} of type {@code TYPE_3BYTE_BGR}</dd>
* <dt>{@code ImageType.TrueColorPaletteType}</dt> * <dt>{@code ImageType.TrueColorPaletteType}</dt>
* <dd>{@code BufferedImage} of type {@code TYPE_4BYTE_ABGR}</dd> * <dd>{@code BufferedImage} of type {@code TYPE_4BYTE_ABGR}</dd>
* </dl>
* *
* @param pImage the original {@code MagickImage} * @param pImage the original {@code MagickImage}
* @return a new {@code BufferedImage} * @return a new {@code BufferedImage}
@@ -191,24 +194,26 @@ public final class MagickUtil {
/** /**
* Converts a {@code BufferedImage} to a {@code MagickImage}. * Converts a {@code BufferedImage} to a {@code MagickImage}.
* <p/> * <p>
* The conversion depends on {@code pImage}'s {@code ColorModel}: * The conversion depends on {@code pImage}'s {@code ColorModel}:
* </p>
* <dl> * <dl>
* <dt>{@code IndexColorModel} with 1 bit b/w</dt> * <dt>{@code IndexColorModel} with 1 bit b/w</dt>
* <dd>{@code MagickImage} of type {@code ImageType.BilevelType}</dd> * <dd>{@code MagickImage} of type {@code ImageType.BilevelType}</dd>
* <dt>{@code IndexColorModel} &gt; 1 bit,</dt> * <dt>{@code IndexColorModel} &gt; 1 bit,</dt>
* <dd>{@code MagickImage} of type {@code ImageType.PaletteType} * <dd>{@code MagickImage} of type {@code ImageType.PaletteType}
* or {@code MagickImage} of type {@code ImageType.PaletteMatteType} * 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> * <dt>{@code ColorModel.getColorSpace().getType() == ColorSpace.TYPE_GRAY}</dt>
* <dd>{@code MagickImage} of type {@code ImageType.GrayscaleType} * <dd>{@code MagickImage} of type {@code ImageType.GrayscaleType}
* or {@code MagickImage} of type {@code ImageType.GrayscaleMatteType} * 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> * <dt>{@code ColorModel.getColorSpace().getType() == ColorSpace.TYPE_RGB}</dt>
* <dd>{@code MagickImage} of type {@code ImageType.TrueColorType} * <dd>{@code MagickImage} of type {@code ImageType.TrueColorType}
* or {@code MagickImage} of type {@code ImageType.TrueColorPaletteType}</dd> * or {@code MagickImage} of type {@code ImageType.TrueColorPaletteType}</dd>
* </dl>
* *
* @param pImage the original {@code BufferedImage} * @param pImage the original {@code BufferedImage}
* @return a new {@code MagickImage} * @return a new {@code MagickImage}
@@ -432,7 +437,7 @@ public final class MagickUtil {
/** /**
* Converts a palette-based {@code MagickImage} to a * Converts a palette-based {@code MagickImage} to a
* {@code BufferedImage}, of type {@code TYPE_BYTE_BINARY} (for images * {@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 pImage the original {@code MagickImage}
* @param pAlpha keep alpha channel * @param pAlpha keep alpha channel
@@ -67,39 +67,42 @@ import java.awt.image.*;
* constructor, either using the * constructor, either using the
* <a href="#field_summary">filter type constants</a>, or one of the * <a href="#field_summary">filter type constants</a>, or one of the
* {@code RendereingHints}. * {@code RendereingHints}.
* <p/> * <p>
* For fastest results, use {@link #FILTER_POINT} or {@link #FILTER_BOX}. * For fastest results, use {@link #FILTER_POINT} or {@link #FILTER_BOX}.
* In most cases, {@link #FILTER_TRIANGLE} will produce acceptable results, while * In most cases, {@link #FILTER_TRIANGLE} will produce acceptable results, while
* being relatively fast. * being relatively fast.
* For higher quality output, use more sophisticated interpolation algorithms, * For higher quality output, use more sophisticated interpolation algorithms,
* like {@link #FILTER_MITCHELL} or {@link #FILTER_LANCZOS}. * like {@link #FILTER_MITCHELL} or {@link #FILTER_LANCZOS}.
* <p/> * </p>
* <p>
* Example: * Example:
* </p>
* <blockquote><pre> * <blockquote><pre>
* BufferedImage image; * BufferedImage image;
* <p/> *
* //... * //...
* <p/> *
* ResampleOp resampler = new ResampleOp(100, 100, ResampleOp.FILTER_TRIANGLE); * ResampleOp resampler = new ResampleOp(100, 100, ResampleOp.FILTER_TRIANGLE);
* BufferedImage thumbnail = resampler.filter(image, null); * BufferedImage thumbnail = resampler.filter(image, null);
* </pre></blockquote> * </pre></blockquote>
* <p/> * <p>
* If your imput image is very large, it's possible to first resample using the * 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, * very fast {@code FILTER_POINT} algorithm, then resample to the wanted size,
* using a higher quality algorithm: * using a higher quality algorithm:
* </p>
* <blockquote><pre> * <blockquote><pre>
* BufferedImage verylLarge; * BufferedImage verylLarge;
* <p/> *
* //... * //...
* <p/> *
* int w = 300; * int w = 300;
* int h = 200; * int h = 200;
* <p/> *
* BufferedImage temp = new ResampleOp(w * 2, h * 2, FILTER_POINT).filter(verylLarge, null); * BufferedImage temp = new ResampleOp(w * 2, h * 2, FILTER_POINT).filter(verylLarge, null);
* <p/> *
* BufferedImage scaled = new ResampleOp(w, h).filter(temp, null); * BufferedImage scaled = new ResampleOp(w, h).filter(temp, null);
* </pre></blockquote> * </pre></blockquote>
* <p/> * <p>
* For maximum performance, this class will use native code, through * For maximum performance, this class will use native code, through
* <a href="http://www.yeo.id.au/jmagick/">JMagick</a>, when available. * <a href="http://www.yeo.id.au/jmagick/">JMagick</a>, when available.
* Otherwise, the class will silently fall back to pure Java mode. * 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}. * {@code com.twelvemonkeys.image.accel} to {@code false}.
* To allow debug of the native code, set the system property * To allow debug of the native code, set the system property
* {@code com.twelvemonkeys.image.magick.debug} to {@code true}. * {@code com.twelvemonkeys.image.magick.debug} to {@code true}.
* <p/> * </p>
* <p>
* This {@code BufferedImageOp} is based on C example code found in * This {@code BufferedImageOp} is based on C example code found in
* <a href="http://www.acm.org/tog/GraphicsGems/">Graphics Gems III</a>, * <a href="http://www.acm.org/tog/GraphicsGems/">Graphics Gems III</a>,
* Filtered Image Rescaling, by Dale Schumacher (with additional improvments by * 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 * <a href="http://www.imagemagick.org/">ImageMagick</a> and
* Marco Schmidt's <a href="http://schmidt.devlib.org/jiu/">Java Imaging Utilities</a> * 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). * (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 * For a description of the various interpolation algorithms, see
* <em>General Filtered Image Rescaling</em> in <em>Graphics Gems III</em>, * <em>General Filtered Image Rescaling</em> in <em>Graphics Gems III</em>,
* Academic Press, 1994. * Academic Press, 1994.
* </p>
* *
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a> * @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
* @author last modified by $Author: haku $ * @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 * Creates a {@code ResampleOp} that will resample input images to the
* given width and height, using the interpolation filter specified by * given width and height, using the interpolation filter specified by
* the given hints. * the given hints.
* <p>
* If using {@code RenderingHints}, the hints are mapped as follows: * If using {@code RenderingHints}, the hints are mapped as follows:
* </p>
* <ul> * <ul>
* <li>{@code KEY_RESAMPLE_INTERPOLATION} takes precedence over any * <li>{@code KEY_RESAMPLE_INTERPOLATION} takes precedence over any
* standard {@code java.awt} hints, and dictates interpolation * standard {@code java.awt} hints, and dictates interpolation
* directly, see * directly, see
* <a href="#field_summary">{@code RenderingHints} constants</a>.</li> * <a href="#field_summary">{@code RenderingHints} constants</a>.</li>
* <p/>
* <li>{@code KEY_INTERPOLATION} takes precedence over other hints. * <li>{@code KEY_INTERPOLATION} takes precedence over other hints.
* <ul> * <ul>
* <li>{@link RenderingHints#VALUE_INTERPOLATION_NEAREST_NEIGHBOR} specifies * <li>{@link RenderingHints#VALUE_INTERPOLATION_NEAREST_NEIGHBOR} specifies
@@ -378,7 +385,6 @@ public class ResampleOp implements BufferedImageOp/* TODO: RasterOp */ {
* {@code FILTER_QUADRATIC}</li> * {@code FILTER_QUADRATIC}</li>
* </ul> * </ul>
* </li> * </li>
* <p/>
* <li>{@code KEY_RENDERING} or {@code KEY_COLOR_RENDERING} * <li>{@code KEY_RENDERING} or {@code KEY_COLOR_RENDERING}
* <ul> * <ul>
* <li>{@link RenderingHints#VALUE_RENDER_SPEED} specifies * <li>{@link RenderingHints#VALUE_RENDER_SPEED} specifies
@@ -388,7 +394,9 @@ public class ResampleOp implements BufferedImageOp/* TODO: RasterOp */ {
* </ul> * </ul>
* </li> * </li>
* </ul> * </ul>
* <p>
* Other hints have no effect on this filter. * Other hints have no effect on this filter.
* </p>
* *
* @param width width of the re-sampled image * @param width width of the re-sampled image
* @param height height 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. * An {@code ImageFilter} class for subsampling images.
* <p/> * <p>
* It is meant to be used in conjunction with a {@code FilteredImageSource} * It is meant to be used in conjunction with a {@code FilteredImageSource}
* object to produce subsampled versions of existing images. * object to produce subsampled versions of existing images.
* </p>
* *
* @see java.awt.image.FilteredImageSource * @see java.awt.image.FilteredImageSource
* *
@@ -30,8 +30,9 @@
/** /**
* Classes for image manipulation. * Classes for image manipulation.
* <p/> * <p>
* See the class {@link com.twelvemonkeys.image.ImageUtil}. * See the class {@link com.twelvemonkeys.image.ImageUtil}.
* </p>
* *
* @version 1.0 * @version 1.0
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a> * @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
+1 -1
View File
@@ -4,7 +4,7 @@
<parent> <parent>
<groupId>com.twelvemonkeys.common</groupId> <groupId>com.twelvemonkeys.common</groupId>
<artifactId>common</artifactId> <artifactId>common</artifactId>
<version>3.4</version> <version>3.4.4-SNAPSHOT</version>
</parent> </parent>
<artifactId>common-io</artifactId> <artifactId>common-io</artifactId>
<packaging>jar</packaging> <packaging>jar</packaging>
@@ -186,7 +186,7 @@ abstract class AbstractCachedSeekableStream extends SeekableInputStream {
} }
protected void closeImpl() throws IOException { protected void closeImpl() throws IOException {
cache.flush(position); cache.close();
cache = null; cache = null;
stream.close(); stream.close();
} }
@@ -198,12 +198,12 @@ abstract class AbstractCachedSeekableStream extends SeekableInputStream {
* @author last modified by $Author: haku $ * @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 $ * @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}. * 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 * Writes a series of bytes at the current read/write position. The read/write position will be increased by
* {@code pLength}. * {@code pLength}.
* <p/> * <p>
* This implementation invokes {@link #write(int)} {@code pLength} times. * This implementation invokes {@link #write(int)} {@code pLength} times.
* Subclasses may override this method for performance. * Subclasses may override this method for performance.
* </p>
* *
* @param pBuffer the bytes to write. * @param pBuffer the bytes to write.
* @param pOffset the starting offset into the buffer. * @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 * Writes a series of bytes at the current read/write position. The read/write position will be increased by
* {@code pLength}. * {@code pLength}.
* <p/> * <p>
* This implementation invokes {@link #read()} {@code pLength} times. * This implementation invokes {@link #read()} {@code pLength} times.
* Subclasses may override this method for performance. * Subclasses may override this method for performance.
* </p>
* *
* @param pBuffer the bytes to write * @param pBuffer the bytes to write
* @param pOffset the starting offset into the buffer. * @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. * 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 * 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. * 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. * Subclasses should override this method for performance reasons, to avoid holding on to unnecessary resources.
* This implementation does nothing. * This implementation does nothing.
* </p>
* *
* @param pPosition the last position to flush. * @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. * @throws IOException if the position can't be determined because of a problem in the cache backing mechanism.
*/ */
abstract long getPosition() throws IOException; 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. * A Reader implementation that can read from multiple sources.
* <p/>
* *
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a> * @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
* @author last modified by $Author: haku $ * @author last modified by $Author: haku $
@@ -34,7 +34,6 @@ import java.io.StringReader;
/** /**
* EmptyReader * EmptyReader
* <p/>
* *
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a> * @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
* @author last modified by $Author: haku $ * @author last modified by $Author: haku $
@@ -38,7 +38,6 @@ import java.io.OutputStream;
/** /**
* An unsynchronized {@code ByteArrayOutputStream} implementation. This version * An unsynchronized {@code ByteArrayOutputStream} implementation. This version
* also has a constructor that lets you create a stream with initial content. * 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> * @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
* @version $Id: FastByteArrayOutputStream.java#2 $ * @version $Id: FastByteArrayOutputStream.java#2 $
@@ -60,8 +59,9 @@ public final class FastByteArrayOutputStream extends ByteArrayOutputStream {
/** /**
* Creates a {@code ByteArrayOutputStream} with the given initial content. * Creates a {@code ByteArrayOutputStream} with the given initial content.
* <p/> * <p>
* Note that the buffer is not cloned, for maximum performance. * Note that the buffer is not cloned, for maximum performance.
* </p>
* *
* @param pBuffer initial buffer * @param pBuffer initial buffer
*/ */
@@ -123,10 +123,11 @@ public final class FastByteArrayOutputStream extends ByteArrayOutputStream {
* Creates a {@code ByteArrayInputStream} that reads directly from this * Creates a {@code ByteArrayInputStream} that reads directly from this
* {@code FastByteArrayOutputStream}'s byte buffer. * {@code FastByteArrayOutputStream}'s byte buffer.
* The buffer is not cloned, for maximum performance. * The buffer is not cloned, for maximum performance.
* <p/> * <p>
* Note that care needs to be taken to avoid writes to * Note that care needs to be taken to avoid writes to
* this output stream after the input stream is created. * this output stream after the input stream is created.
* Failing to do so, may result in unpredictable behaviour. * Failing to do so, may result in unpredictable behaviour.
* </p>
* *
* @return a new {@code ByteArrayInputStream}, reading from this stream's buffer. * @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}. * 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)}. * Temporary files are created as specified in {@link File#createTempFile(String, String, java.io.File)}.
* </p>
* *
* @see MemoryCacheSeekableStream * @see MemoryCacheSeekableStream
* @see FileSeekableStream * @see FileSeekableStream
@@ -124,7 +125,9 @@ public final class FileCacheSeekableStream extends AbstractCachedSeekableStream
@Override @Override
protected void closeImpl() throws IOException { protected void closeImpl() throws IOException {
// TODO: Close cache file
super.closeImpl(); super.closeImpl();
buffer = null; buffer = null;
} }
@@ -194,39 +197,45 @@ public final class FileCacheSeekableStream extends AbstractCachedSeekableStream
return length; return length;
} }
// TODO: We need to close the cache file!!! Otherwise we are leaking file descriptors
final static class FileCache extends StreamCache { final static class FileCache extends StreamCache {
private RandomAccessFile mCacheFile; private RandomAccessFile cacheFile;
public FileCache(final File pFile) throws FileNotFoundException { public FileCache(final File pFile) throws FileNotFoundException {
Validate.notNull(pFile, "file"); Validate.notNull(pFile, "file");
mCacheFile = new RandomAccessFile(pFile, "rw"); cacheFile = new RandomAccessFile(pFile, "rw");
} }
public void write(final int pByte) throws IOException { public void write(final int pByte) throws IOException {
mCacheFile.write(pByte); cacheFile.write(pByte);
} }
@Override @Override
public void write(final byte[] pBuffer, final int pOffset, final int pLength) throws IOException { 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 { public int read() throws IOException {
return mCacheFile.read(); return cacheFile.read();
} }
@Override @Override
public int read(final byte[] pBuffer, final int pOffset, final int pLength) throws IOException { 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 { public void seek(final long pPosition) throws IOException {
mCacheFile.seek(pPosition); cacheFile.seek(pPosition);
} }
public long getPosition() throws IOException { 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}. * A {@code SeekableInputStream} implementation that uses random access directly to a {@code File}.
* <p/>
* @see FileCacheSeekableStream * @see FileCacheSeekableStream
* @see MemoryCacheSeekableStream * @see MemoryCacheSeekableStream
* @see RandomAccessFile * @see RandomAccessFile
@@ -37,7 +37,6 @@ import java.io.InputStreamReader;
/** /**
* FileSystem * FileSystem
* <p/>
* *
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a> * @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
* @version $Id: FileSystem.java#1 $ * @version $Id: FileSystem.java#1 $
@@ -171,7 +171,6 @@ public final class FileUtil {
* {@code false}. In all other cases, an * {@code false}. In all other cases, an
* {@code IOExceptio}n is thrown, and the method does not return. * {@code IOExceptio}n is thrown, and the method does not return.
* @throws IOException if an i/o error occurs during copy * @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 { public static boolean copy(File pFromFile, File pToFile, boolean pOverWrite) throws IOException {
// Copy all directory structure // 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 * The mask is given as a well-known DOS filename format, with '*' and '?' as
* wildcards. * wildcards.
* All other characters counts as ordinary characters. * 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 file name masks are used as a filter input and is given to the class via
* the string array property:<br> * the string array property:
* <dd>{@code filenameMasksForInclusion} - Filename mask for exclusion of * </p>
* files (default if both properties are defined) * <dl>
* <dd>{@code filenameMasksForExclusion} - Filename mask for exclusion of * <dt>{@code filenameMasksForInclusion}</dt>
* files. * <dd>Filename mask for exclusion of
* <p/> * 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 * 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 * 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 * component and this utility component is kept in the background with only
* initial configuration necessary. * initial configuration necessary.
* </p>
* *
* @author <a href="mailto:eirik.torske@iconmedialab.no">Eirik Torske</a> * @author <a href="mailto:eirik.torske@iconmedialab.no">Eirik Torske</a>
* @see File#list(java.io.FilenameFilter) java.io.File.list * @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, * A little endian input stream reads two's complement,
* little endian integers, floating point numbers, and characters * little endian integers, floating point numbers, and characters
* and returns them as Java primitive types. * and returns them as Java primitive types.
* <p/> * <p>
* The standard {@code java.io.DataInputStream} class * The standard {@code java.io.DataInputStream} class
* which this class imitates reads big endian quantities. * which this class imitates reads big endian quantities.
* <p/> * </p>
* <p>
* <em>Warning: * <em>Warning:
* <!-- Beware of little indians! -->
* The {@code DataInput} and {@code DataOutput} interfaces * The {@code DataInput} and {@code DataOutput} interfaces
* specifies big endian byte order in their documentation. * specifies big endian byte order in their documentation.
* This means that this class is, strictly speaking, not a proper * This means that this class is, strictly speaking, not a proper
* implementation. However, I don't see a reason for the these interfaces to * implementation. However, I don't see a reason for the these interfaces to
* specify the byte order of their underlying representations. * specify the byte order of their underlying representations.
* </em> * </em>
* </p>
* *
* @see com.twelvemonkeys.io.LittleEndianRandomAccessFile * @see com.twelvemonkeys.io.LittleEndianRandomAccessFile
* @see java.io.DataInputStream * @see java.io.DataInputStream
@@ -381,12 +382,10 @@ public class LittleEndianDataInputStream extends FilterInputStream implements Da
} }
/** /**
* See the general contract of the {@code readFully} * See the general contract of the {@code readFully} method of {@code DataInput}.
* method of {@code DataInput}. * <p>
* <p/> * Bytes for this operation are read from the contained input stream.
* Bytes * </p>
* for this operation are read from the contained
* input stream.
* *
* @param pBytes the buffer into which the data is read. * @param pBytes the buffer into which the data is read.
* @throws EOFException if this input stream reaches the end before * @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} * See the general contract of the {@code readFully} method of {@code DataInput}.
* method of {@code DataInput}. * <p>
* <p/> * Bytes for this operation are read from the contained input stream.
* Bytes * </p>
* for this operation are read from the contained
* input stream.
* *
* @param pBytes the buffer into which the data is read. * @param pBytes the buffer into which the data is read.
* @param pOffset the start offset of the data. * @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. * @exception IOException if an I/O error occurs.
* @see java.io.BufferedReader#readLine() * @see java.io.BufferedReader#readLine()
* @see java.io.DataInputStream#readLine() * @see java.io.DataInputStream#readLine()
* @noinspection deprecation
*/ */
public String readLine() throws IOException { public String readLine() throws IOException {
DataInputStream ds = new DataInputStream(in); DataInputStream ds = new DataInputStream(in);
@@ -47,18 +47,19 @@ import java.io.*;
/** /**
* A little endian output stream writes primitive Java numbers * A little endian output stream writes primitive Java numbers
* and characters to an output stream in a little endian format. * and characters to an output stream in a little endian format.
* <p/> * <p>
* The standard {@code java.io.DataOutputStream} class which this class * The standard {@code java.io.DataOutputStream} class which this class
* imitates uses big endian integers. * imitates uses big endian integers.
* <p/> * </p>
* <p>
* <em>Warning: * <em>Warning:
* <!-- Beware of little indians! -->
* The {@code DataInput} and {@code DataOutput} interfaces * The {@code DataInput} and {@code DataOutput} interfaces
* specifies big endian byte order in their documentation. * specifies big endian byte order in their documentation.
* This means that this class is, strictly speaking, not a proper * This means that this class is, strictly speaking, not a proper
* implementation. However, I don't see a reason for the these interfaces to * implementation. However, I don't see a reason for the these interfaces to
* specify the byte order of their underlying representations. * specify the byte order of their underlying representations.
* </em> * </em>
* <p>
* *
* @see com.twelvemonkeys.io.LittleEndianRandomAccessFile * @see com.twelvemonkeys.io.LittleEndianRandomAccessFile
* @see java.io.DataOutputStream * @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 * A replacement for {@link java.io.RandomAccessFile} that is capable of reading
* and writing data in little endian byte order. * and writing data in little endian byte order.
* <p/> * <p>
* <em>Warning: * <em>Warning:
* <!-- Beware of little indians! -->
* The {@code DataInput} and {@code DataOutput} interfaces * The {@code DataInput} and {@code DataOutput} interfaces
* specifies big endian byte order in their documentation. * specifies big endian byte order in their documentation.
* This means that this class is, strictly speaking, not a proper * This means that this class is, strictly speaking, not a proper
* implementation. However, I don't see a reason for the these interfaces to * implementation. However, I don't see a reason for the these interfaces to
* specify the byte order of their underlying representations. * specify the byte order of their underlying representations.
* </em> * </em>
* </p>
* *
* @see com.twelvemonkeys.io.LittleEndianDataInputStream * @see com.twelvemonkeys.io.LittleEndianDataInputStream
* @see com.twelvemonkeys.io.LittleEndianDataOutputStream * @see com.twelvemonkeys.io.LittleEndianDataOutputStream
@@ -37,7 +37,6 @@ import java.util.List;
/** /**
* A {@code SeekableInputStream} implementation that caches data in memory. * A {@code SeekableInputStream} implementation that caches data in memory.
* <p/>
* *
* @see FileCacheSeekableStream * @see FileCacheSeekableStream
* *
@@ -67,7 +66,7 @@ public final class MemoryCacheSeekableStream extends AbstractCachedSeekableStrea
final static class MemoryCache extends StreamCache { final static class MemoryCache extends StreamCache {
final static int BLOCK_SIZE = 1 << 13; 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 length;
private long position; private long position;
private long start; private long start;
@@ -186,6 +185,11 @@ public final class MemoryCacheSeekableStream extends AbstractCachedSeekableStrea
start = pPosition; start = pPosition;
} }
@Override
void close() throws IOException {
cache.clear();
}
public long getPosition() { public long getPosition() {
return position; return position;
} }
@@ -35,7 +35,6 @@ import java.io.InputStream;
/** /**
* An {@code InputStream} that contains no bytes. * An {@code InputStream} that contains no bytes.
* <p/>
* *
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</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/NullInputStream.java#2 $ * @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. * An {@code OutputStream} implementation that works as a sink.
* <p/>
* *
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</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/NullOutputStream.java#2 $ * @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 * 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. * {@code RandomAccessFile}, except it may be backed by something other than a file.
* <p/>
* *
* @see java.io.RandomAccessFile * @see java.io.RandomAccessFile
* *
@@ -114,8 +113,9 @@ public abstract class RandomAccessStream implements Seekable, DataInput, DataOut
/** /**
* Returns an input view of this {@code RandomAccessStream}. * Returns an input view of this {@code RandomAccessStream}.
* Invoking this method several times, will return the same object. * Invoking this method several times, will return the same object.
* <p/> * <p>
* <em>Note that read access is NOT synchronized.</em> * <em>Note that read access is NOT synchronized.</em>
* </p>
* *
* @return a {@code SeekableInputStream} reading from this stream * @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}. * Returns an output view of this {@code RandomAccessStream}.
* Invoking this method several times, will return the same object. * Invoking this method several times, will return the same object.
* <p/> * <p>
* <em>Note that write access is NOT synchronized.</em> * <em>Note that write access is NOT synchronized.</em>
* </p>
* *
* @return a {@code SeekableOutputStream} writing to this stream * @return a {@code SeekableOutputStream} writing to this stream
*/ */
@@ -34,7 +34,7 @@ import java.io.IOException;
/** /**
* Interface for seekable streams. * Interface for seekable streams.
* <p/> *
* @see SeekableInputStream * @see SeekableInputStream
* @see SeekableOutputStream * @see SeekableOutputStream
* *
@@ -55,12 +55,14 @@ public interface Seekable {
/** /**
* Sets the current stream position to the desired location. * Sets the current stream position to the desired location.
* The next read will occur at this location. * The next read will occur at this location.
* <p/> * <p>
* An {@code IndexOutOfBoundsException} will be thrown if pPosition is smaller * An {@code IndexOutOfBoundsException} will be thrown if pPosition is smaller
* than the flushed position (as returned by {@link #getFlushedPosition()}). * 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} * It is legal to seek past the end of the file; an {@code EOFException}
* will be thrown only if a read is performed. * will be thrown only if a read is performed.
* </p>
* *
* @param pPosition a long containing the desired file pointer position. * @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} * Unlike a standard {@code InputStream}, all {@code Seekable}
* streams upport marking. Additionally, calls to {@code mark} and * streams upport marking. Additionally, calls to {@code mark} and
* {@code reset} may be nested arbitrarily. * {@code reset} may be nested arbitrarily.
* <p/> * <p>
* Unlike the {@code mark} methods declared by the {@code Reader} or * Unlike the {@code mark} methods declared by the {@code Reader} or
* {@code InputStream} * {@code InputStream}
* interfaces, no {@code readLimit} parameter is used. An arbitrary amount * interfaces, no {@code readLimit} parameter is used. An arbitrary amount
* of data may be read following the call to {@code mark}. * of data may be read following the call to {@code mark}.
* </p>
*/ */
void mark(); void mark();
/** /**
* Returns the file pointer to its previous position, * Returns the file pointer to its previous position,
* at the time of the most recent unmatched call to mark. * at the time of the most recent unmatched call to mark.
* <p/> * <p>
* Calls to reset without a corresponding call to mark will either: * Calls to reset without a corresponding call to mark will either:
* </p>
* <ul> * <ul>
* <li>throw an {@code IOException}</li> * <li>throw an {@code IOException}</li>
* <li>or, reset to the beginning of the stream.</li> * <li>or, reset to the beginning of the stream.</li>
* </ul> * </ul>
* <p>
* An {@code IOException} will be thrown if the previous marked position * An {@code IOException} will be thrown if the previous marked position
* lies in the discarded portion of the stream. * lies in the discarded portion of the stream.
* </p>
* *
* @throws IOException if an I/O error occurs. * @throws IOException if an I/O error occurs.
* @see java.io.InputStream#reset() * @see java.io.InputStream#reset()
@@ -105,10 +111,11 @@ public interface Seekable {
* Discards the initial portion of the stream prior to the indicated * Discards the initial portion of the stream prior to the indicated
* postion. Attempting to seek to an offset within the flushed portion of * postion. Attempting to seek to an offset within the flushed portion of
* the stream will result in an {@code IndexOutOfBoundsException}. * the stream will result in an {@code IndexOutOfBoundsException}.
* <p/> * <p>
* Calling {@code flushBefore} may allow classes implementing this * Calling {@code flushBefore} may allow classes implementing this
* interface to free up resources such as memory or disk space that are * interface to free up resources such as memory or disk space that are
* being used to store data from the stream. * being used to store data from the stream.
* </p>
* *
* @param pPosition a long containing the length of the file prefix that * @param pPosition a long containing the length of the file prefix that
* may be flushed. * may be flushed.
@@ -36,7 +36,7 @@ import java.util.Stack;
/** /**
* Abstract base class for {@code InputStream}s implementing the {@code Seekable} interface. * Abstract base class for {@code InputStream}s implementing the {@code Seekable} interface.
* <p/> *
* @see SeekableOutputStream * @see SeekableOutputStream
* *
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a> * @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 * Abstract base class for {@code OutputStream}s implementing the
* {@code Seekable} interface. * {@code Seekable} interface.
* <p/> *
* @see SeekableInputStream * @see SeekableInputStream
* *
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a> * @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
@@ -38,7 +38,6 @@ import java.io.StringReader;
/** /**
* StringArrayReader * StringArrayReader
* <p/>
* *
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a> * @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
* @author last modified by $Author: haku $ * @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 * An {@code InputStream} reading up to a specified number of bytes from an
* underlying stream. * underlying stream.
* <p/>
* *
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</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/SubStream.java#2 $ * @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 * UnixFileSystem
* <p/>
* *
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</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/UnixFileSystem.java#1 $ * @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 * Win32File
* <p/>
* *
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</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/Win32File.java#2 $ * @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 * WindowsFileSystem
* <p/>
* *
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</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/Win32FileSystem.java#2 $ * @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. * A {@code File} implementation that resolves the Windows {@code .lnk} files as symbolic links.
* <p/> * <p>
* This class is based on example code from * This class is based on example code from
* <a href="http://www.oreilly.com/catalog/swinghks/index.html">Swing Hacks</a>, * <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. * 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> * @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 $ * @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. * Converts two bytes into a short.
* <p/> * <p>
* NOTE: this is little endian because it's for an * NOTE: this is little endian because it's for an
* Intel only OS * Intel only OS
* </p>
* *
* @ param bytes * @ param bytes
* @ param off * @ param off
@@ -39,15 +39,16 @@ import java.nio.charset.Charset;
/** /**
* Wraps a {@code Writer} in an {@code OutputStream}. * Wraps a {@code Writer} in an {@code OutputStream}.
* <p/> * <p>
* <em>Instances of this class are not thread-safe.</em> * <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, * <em>NOTE: This class is probably not the right way of solving your problem,
* however it might prove useful in JSPs etc. * however it might prove useful in JSPs etc.
* If possible, it's always better to use the {@code Writer}'s underlying * If possible, it's always better to use the {@code Writer}'s underlying
* {@code OutputStream}, or wrap it's native backing. * {@code OutputStream}, or wrap it's native backing.
* </em> * </em>
* <p/> * </p>
* *
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</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/WriterOutputStream.java#2 $ * @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. * {@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/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 * @see Base64Encoder
* *
@@ -36,9 +36,9 @@ import java.nio.ByteBuffer;
/** /**
* {@code Encoder} implementation for standard base64 encoding. * {@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/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 * @see Base64Decoder
* *
@@ -34,7 +34,6 @@ import java.io.IOException;
/** /**
* Thrown by {@code Decoder}s when encoded data can not be decoded. * Thrown by {@code Decoder}s when encoded data can not be decoded.
* <p/>
* *
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</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/DecodeException.java#2 $ * @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. * Interface for decoders.
* A {@code Decoder} may be used with a {@code DecoderStream}, to perform * A {@code Decoder} may be used with a {@code DecoderStream}, to perform
* on-the-fly decoding from an {@code InputStream}. * on-the-fly decoding from an {@code InputStream}.
* <p/> * <p>
* Important note: Decoder implementations are typically not synchronized. * Important note: Decoder implementations are typically not synchronized.
* <p/> * </p>
*
* @see Encoder * @see Encoder
* @see DecoderStream * @see DecoderStream
* *
@@ -36,9 +36,8 @@ import java.io.InputStream;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
/** /**
* An {@code InputStream} that provides on-the-fly decoding from an underlying * An {@code InputStream} that provides on-the-fly decoding from an underlying stream.
* stream. *
* <p/>
* @see EncoderStream * @see EncoderStream
* @see Decoder * @see Decoder
* *
@@ -38,8 +38,9 @@ import java.nio.ByteBuffer;
* Interface for encoders. * Interface for encoders.
* An {@code Encoder} may be used with an {@code EncoderStream}, to perform * An {@code Encoder} may be used with an {@code EncoderStream}, to perform
* on-the-fly encoding to an {@code OutputStream}. * on-the-fly encoding to an {@code OutputStream}.
* <p/> * <p>
* Important note: Encoder implementations are typically not synchronized. * Important note: Encoder implementations are typically not synchronized.
* </p>
* *
* @see Decoder * @see Decoder
* @see EncoderStream * @see EncoderStream
@@ -36,9 +36,8 @@ import java.io.OutputStream;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
/** /**
* An {@code OutputStream} that provides on-the-fly encoding to an underlying * An {@code OutputStream} that provides on-the-fly encoding to an underlying stream.
* stream. *
* <p/>
* @see DecoderStream * @see DecoderStream
* @see Encoder * @see Encoder
* *
@@ -37,30 +37,36 @@ import java.nio.ByteBuffer;
/** /**
* Decoder implementation for Apple PackBits run-length encoding. * Decoder implementation for Apple PackBits run-length encoding.
* <p/> * <p>
* <small>From Wikipedia, the free encyclopedia</small><br/> * <small>From Wikipedia, the free encyclopedia</small>
* <br>
* PackBits is a fast, simple compression scheme for run-length encoding of * PackBits is a fast, simple compression scheme for run-length encoding of
* data. * data.
* <p/> * </p>
* <p>
* Apple introduced the PackBits format with the release of MacPaint on the * Apple introduced the PackBits format with the release of MacPaint on the
* Macintosh computer. This compression scheme is one of the types of * Macintosh computer. This compression scheme is one of the types of
* compression that can be used in TIFF-files. * 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 * 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 * data. The header is a signed byte; the data can be signed, unsigned, or
* packed (such as MacPaint pixels). * packed (such as MacPaint pixels).
* <p/> * </p>
* <table><tr><th>Header byte</th><th>Data</th></tr> * <table>
* <tr><td>0 to 127</td> <td>1 + <i>n</i> literal bytes of data</td></tr> * <caption>PackBits</caption>
* <tr><td>0 to -127</td> <td>One byte of data, repeated 1 - <i>n</i> times in * <tr><th>Header byte</th><th>Data</th></tr>
* the decompressed output</td></tr> * <tr><td>0 to 127</td> <td>1 + <i>n</i> literal bytes of data</td></tr>
* <tr><td>-128</td> <td>No operation</td></tr></table> * <tr><td>0 to -127</td> <td>One byte of data, repeated 1 - <i>n</i> times in the decompressed output</td></tr>
* <p/> * <tr><td>-128</td> <td>No operation</td></tr>
* </table>
* <p>
* Note that interpreting 0 as positive or negative makes no difference in the * 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 * output. Runs of two bytes adjacent to non-runs are typically written as
* literal data. * literal data.
* <p/> * </p>
* See <a href="http://developer.apple.com/technotes/tn/tn1023.html">Understanding PackBits</a> *
* @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> * @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 $ * @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 boolean disableNoOp;
private final byte[] sample; private final byte[] sample;
private int leftOfRun;
private boolean splitRun;
private boolean reachedEOF; private boolean reachedEOF;
/** Creates a {@code PackBitsDecoder}. */ /** Creates a {@code PackBitsDecoder}. */
@@ -82,10 +86,11 @@ public final class PackBitsDecoder implements Decoder {
/** /**
* Creates a {@code PackBitsDecoder}, with optional compatibility mode. * Creates a {@code PackBitsDecoder}, with optional compatibility mode.
* <p/> * <p>
* As some implementations of PackBits-like encoders treat {@code -128} as length of * 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. * 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. * 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 * @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. * Creates a {@code PackBitsDecoder}, with optional compatibility mode.
* <p/> * <p>
* As some implementations of PackBits-like encoders treat {@code -128} as length of * 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. * 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. * 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 * @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 * @param buffer a byte array, minimum 128 (or 129 if no-op is disabled) bytes long
* @return The number of bytes decoded * @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 { public int decode(final InputStream stream, final ByteBuffer buffer) throws IOException {
if (reachedEOF) { if (reachedEOF) {
return -1; return -1;
} }
// TODO: Don't decode more than single runs, because some writers add pad bytes inside the stream... // NOTE: We don't decode more than single runs, because some writers add pad bytes inside the stream...
while (buffer.hasRemaining()) { // Start new run
int n; int b = stream.read();
if (b < 0) {
reachedEOF = true;
return 0;
}
if (splitRun) { int n = (byte) b;
// Continue run
n = leftOfRun; try {
splitRun = false; if (n >= 0) {
// Copy next n + 1 bytes literally
readFully(stream, buffer, sample.length * (n + 1));
} }
else { // Allow -128 for compatibility, see above
// Start new run else if (disableNoOp || n != -128) {
int b = stream.read(); // Replicate the next byte -n + 1 times
if (b < 0) { for (int s = 0; s < sample.length; s++) {
reachedEOF = true; sample[s] = readByte(stream);
break;
} }
n = (byte) b;
}
// Split run at or before max for (int i = -n + 1; i > 0; i--) {
if (n >= 0 && n + 1 > buffer.remaining()) { buffer.put(sample);
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));
} }
// 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(); return buffer.position();
@@ -36,30 +36,36 @@ import java.nio.ByteBuffer;
/** /**
* Encoder implementation for Apple PackBits run-length encoding. * Encoder implementation for Apple PackBits run-length encoding.
* <p/> * <p>
* From Wikipedia, the free encyclopedia<br/> * From Wikipedia, the free encyclopedia
* <br>
* PackBits is a fast, simple compression scheme for run-length encoding of * PackBits is a fast, simple compression scheme for run-length encoding of
* data. * data.
* <p/> * </p>
* <p>
* Apple introduced the PackBits format with the release of MacPaint on the * Apple introduced the PackBits format with the release of MacPaint on the
* Macintosh computer. This compression scheme is one of the types of * Macintosh computer. This compression scheme is one of the types of
* compression that can be used in TIFF-files. * 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 * 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 * data. The header is a signed byte; the data can be signed, unsigned, or
* packed (such as MacPaint pixels). * packed (such as MacPaint pixels).
* <p/> * </p>
* <table><tr><th>Header byte</th><th>Data</th></tr> * <table>
* <tr><td>0 to 127</td> <td>1 + <i>n</i> literal bytes of data</td></tr> * <caption>PackBits</caption>
* <tr><td>0 to -127</td> <td>One byte of data, repeated 1 - <i>n</i> times in * <tr><th>Header byte</th><th>Data</th></tr>
* the decompressed output</td></tr> * <tr><td>0 to 127</td> <td>1 + <i>n</i> literal bytes of data</td></tr>
* <tr><td>-128</td> <td>No operation</td></tr></table> * <tr><td>0 to -127</td> <td>One byte of data, repeated 1 - <i>n</i> times in the decompressed output</td></tr>
* <p/> * <tr><td>-128</td> <td>No operation</td></tr>
* </table>
* <p>
* Note that interpreting 0 as positive or negative makes no difference in the * 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 * output. Runs of two bytes adjacent to non-runs are typically written as
* literal data. * literal data.
* <p/> * </p>
* See <a href="http://developer.apple.com/technotes/tn/tn1023.html">Understanding PackBits</a> *
* @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> * @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 $ * @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 javax.imageio.stream.ImageInputStream;
import java.io.*; import java.io.*;
import java.nio.ByteOrder;
import java.util.Arrays; import java.util.Arrays;
import java.util.SortedSet; import java.util.SortedSet;
import java.util.TreeSet; import java.util.TreeSet;
import java.util.UUID; import java.util.UUID;
import static com.twelvemonkeys.lang.Validate.notNull;
/** /**
* Represents a read-only OLE2 compound document. * Represents a read-only OLE2 compound document.
* <p/> * <p>
* <!-- TODO: Consider really detaching the entries, as this is hard for users to enforce... --> * <!-- 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 * <em>NOTE: This class is not synchronized. Accessing the document or its
* entries from different threads, will need synchronization on the document * entries from different threads, will need synchronization on the document
* instance.</em> * instance.</em>
* </p>
* *
* @author <a href="mailto:harald.kuhr@gmail.no">Harald Kuhr</a> * @author <a href="mailto:harald.kuhr@gmail.no">Harald Kuhr</a>
* @author last modified by $Author: haku $ * @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 $ * @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: Write support...
// TODO: Properties: http://support.microsoft.com/kb/186898 // TODO: Properties: http://support.microsoft.com/kb/186898
@@ -96,13 +100,19 @@ public final class CompoundDocument {
/** /**
* Creates a (for now) read only {@code 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 * @throws IOException if an I/O exception occurs while reading the header
*/ */
public CompoundDocument(final File pFile) throws IOException { public CompoundDocument(final File file) throws IOException {
input = new LittleEndianRandomAccessFile(FileUtil.resolve(pFile), "r"); // 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?! // 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 // 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}. * 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 * @throws IOException if an I/O exception occurs while reading the header
*/ */
public CompoundDocument(final InputStream pInput) throws IOException { public CompoundDocument(final InputStream pInput) throws IOException {
this(new FileCacheSeekableStream(pInput)); this(new MemoryCacheSeekableStream(pInput));
} }
// For testing only, consider exposing later // For testing only, consider exposing later
CompoundDocument(final SeekableInputStream pInput) throws IOException { CompoundDocument(final SeekableInputStream stream) throws IOException {
input = new SeekableLittleEndianDataInputStream(pInput); input = new SeekableLittleEndianDataInputStream(stream);
// TODO: Might be better to read header on first read operation?! // 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 // 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}. * 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 * @throws IOException if an I/O exception occurs while reading the header
*/ */
public CompoundDocument(final ImageInputStream pInput) throws IOException { public CompoundDocument(final ImageInputStream input) throws IOException {
input = pInput; 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?! // 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 // OTOH: It's also good to be fail-fast, so at least we should make
@@ -147,6 +160,27 @@ public final class CompoundDocument {
readHeader(); 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) { public static boolean canRead(final DataInput pInput) {
return canRead(pInput, true); return canRead(pInput, true);
} }
@@ -609,9 +643,10 @@ public final class CompoundDocument {
* milliseconds since January 1, 1970. * milliseconds since January 1, 1970.
* The time stamp parameter is assumed to be in units of * The time stamp parameter is assumed to be in units of
* 100 nano seconds since January 1, 1601. * 100 nano seconds since January 1, 1601.
* <p/> * <p>
* If the timestamp is {@code 0L} (meaning not specified), no conversion * If the timestamp is {@code 0L} (meaning not specified), no conversion
* is done, to behave like {@code java.io.File}. * is done, to behave like {@code java.io.File}.
* </p>
* *
* @param pMSTime an unsigned long value representing the time stamp (in * @param pMSTime an unsigned long value representing the time stamp (in
* units of 100 nano seconds since January 1, 1601). * 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 * The time is converted from its internal representation to standard Java
* representation, milliseconds since the epoch * representation, milliseconds since the epoch
* (00:00:00 GMT, January 1, 1970). * (00:00:00 GMT, January 1, 1970).
* <p/> * <p>
* Note that most applications leaves this value empty ({@code 0L}). * Note that most applications leaves this value empty ({@code 0L}).
* </p>
* *
* @return A {@code long} value representing the time this entry was * @return A {@code long} value representing the time this entry was
* created, measured in milliseconds since the epoch * 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 * The time is converted from its internal representation to standard Java
* representation, milliseconds since the epoch * representation, milliseconds since the epoch
* (00:00:00 GMT, January 1, 1970). * (00:00:00 GMT, January 1, 1970).
* <p/> * <p>
* Note that many applications leaves this value empty ({@code 0L}). * Note that many applications leaves this value empty ({@code 0L}).
* </p>
* *
* @return A {@code long} value representing the time this entry was * @return A {@code long} value representing the time this entry was
* last modified, measured in milliseconds since the epoch * 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. * 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> * @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 $ * @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 * Specifies wether the serializer should use indentation and optimize for
* readability. * readability.
* <p/> * <p>
* Note: This is a hint, and may be ignored by DOM implemenations. * Note: This is a hint, and may be ignored by DOM implementations.
* </p>
* *
* @param pPrettyPrint {@code true} to enable pretty printing * @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) { private void writeDocument(final PrintWriter pOut, final Node pNode, final SerializationContext pContext) {
// Document fragments might not have child nodes... // Document fragments might not have child nodes...
if (pNode.hasChildNodes()) { if (pNode.hasChildNodes()) {
NodeList nodes = pNode.getChildNodes(); Node child = pNode.getFirstChild();
for (int i = 0; i < nodes.getLength(); i++) { while (child != null) {
writeNodeRecursive(pOut, nodes.item(i), pContext); writeNodeRecursive(pOut, child, pContext);
child = child.getNextSibling();
} }
} }
} }
@@ -448,9 +449,10 @@ public class XMLSerializer {
pOut.println(); pOut.println();
} }
NodeList children = pNode.getChildNodes(); Node child = pNode.getFirstChild();
for (int i = 0; i < children.getLength(); i++) { while (child != null) {
writeNodeRecursive(pOut, children.item(i), pContext.push()); writeNodeRecursive(pOut, child, pContext.push());
child = child.getNextSibling();
} }
if (!pContext.preserveSpace) { if (!pContext.preserveSpace) {
@@ -72,64 +72,64 @@ public class CompoundDocumentTest {
@Test @Test
public void testRoot() throws IOException { 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());
assertNotNull(root); assertTrue(root.isRoot());
assertEquals("Root Entry", root.getName()); assertFalse(root.isFile());
assertTrue(root.isRoot()); assertFalse(root.isDirectory());
assertFalse(root.isFile()); assertEquals(0, root.length());
assertFalse(root.isDirectory()); assertNull(root.getInputStream());
assertEquals(0, root.length()); }
assertNull(root.getInputStream());
} }
@Test @Test
public void testContents() throws IOException { 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()); // Weirdness in the file format, name is *written backwards* 1-24 + Catalog
assertEquals(25, children.size()); 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());
// Weirdness in the file format, name is *written backwards* 1-24 + Catalog children.remove(children.first());
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) @Test(expected = UnsupportedOperationException.class)
public void testChildEntriesUnmodifiable() throws IOException { 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 @Test
public void testReadThumbsCatalogFile() throws IOException { 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); Entry catalog = root.getChildEntry("Catalog");
assertEquals(25, root.getChildEntries().size());
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 @Test
@@ -51,35 +51,7 @@ import static org.junit.Assert.*;
* @author last modified by $Author: haraldk$ * @author last modified by $Author: haraldk$
* @version $Id: CompoundDocument_StreamTestCase.java,v 1.0 13.10.11 12:01 haraldk Exp$ * @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 { 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 @Override
protected InputStream makeInputStream(byte[] data) { protected InputStream makeInputStream(byte[] data) {
try { try {
@@ -182,15 +154,13 @@ public class CompoundDocument_StreamTest extends InputStreamAbstractTest {
return pad; return pad;
} }
// @Ignore
@Test @Test
public void testDev() throws IOException { public void testStreamRead() throws IOException {
InputStream stream = makeInputStream(makeOrderedArray(32)); InputStream stream = makeInputStream(makeOrderedArray(32));
int read; int read;
int count = 0; int count = 0;
while ((read = stream.read()) >= 0) { while ((read = stream.read()) >= 0) {
// System.out.printf("read %02d: 0x%02x%n", count, read & 0xFF);
assertEquals(count, read); assertEquals(count, read);
count++; count++;
} }
+1 -1
View File
@@ -4,7 +4,7 @@
<parent> <parent>
<groupId>com.twelvemonkeys.common</groupId> <groupId>com.twelvemonkeys.common</groupId>
<artifactId>common</artifactId> <artifactId>common</artifactId>
<version>3.4</version> <version>3.4.4-SNAPSHOT</version>
</parent> </parent>
<artifactId>common-lang</artifactId> <artifactId>common-lang</artifactId>
<packaging>jar</packaging> <packaging>jar</packaging>
@@ -42,8 +42,9 @@ import java.util.Map;
/** /**
* A utility class with some useful bean-related functions. * 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> * <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 <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
* @author last modified by $Author: haku $ * @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} * @return A string containing the value of the given property, or {@code null}
* if it can not be found. * if it can not be found.
* @todo Remove System.err's... Create new Exception? Hmm..
*/ */
public static Object getPropertyValue(Object pObject, String pProperty) { public static Object getPropertyValue(Object pObject, String pProperty) {
// // TODO: Remove System.err's... Create new Exception? Hmm..
// TODO: Support get(Object) method of Collections! // TODO: Support get(Object) method of Collections!
// Handle lists and arrays with [] (index) operator // Handle lists and arrays with [] (index) operator
//
if (pObject == null || pProperty == null || pProperty.length() < 1) { if (pObject == null || pProperty == null || pProperty.length() < 1) {
return null; return null;
@@ -535,9 +534,10 @@ public final class BeanUtil {
* a method named * a method named
* {@code set + capitalize(entry.getKey())} is called on the bean, * {@code set + capitalize(entry.getKey())} is called on the bean,
* with {@code entry.getValue()} as its argument. * with {@code entry.getValue()} as its argument.
* <p/> * <p>
* Properties that has no matching set-method in the bean, are simply * Properties that has no matching set-method in the bean, are simply
* discarded. * discarded.
* </p>
* *
* @param pBean The bean to configure * @param pBean The bean to configure
* @param pMapping The mapping for the bean * @param pMapping The mapping for the bean
@@ -560,12 +560,14 @@ public final class BeanUtil {
* a method named * a method named
* {@code set + capitalize(entry.getKey())} is called on the bean, * {@code set + capitalize(entry.getKey())} is called on the bean,
* with {@code entry.getValue()} as its argument. * with {@code entry.getValue()} as its argument.
* <p/> * <p>
* Optionally, lisp-style names are allowed, and automatically converted * Optionally, lisp-style names are allowed, and automatically converted
* to Java-style camel-case names. * to Java-style camel-case names.
* <p/> * </p>
* <p>
* Properties that has no matching set-method in the bean, are simply * Properties that has no matching set-method in the bean, are simply
* discarded. * discarded.
* </p>
* *
* @see StringUtil#lispToCamel(String) * @see StringUtil#lispToCamel(String)
* *
@@ -35,7 +35,6 @@ import java.util.TimeZone;
/** /**
* A utility class with useful date manipulation methods and constants. * A utility class with useful date manipulation methods and constants.
* <p/>
* *
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</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/lang/DateUtil.java#1 $ * @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. * Enumeration of common System {@code Architecture}s.
* <p/> * <p>
* For {@link #Unknown unknown architectures}, {@code toString()} will return * For {@link #Unknown unknown architectures}, {@code toString()} will return
* the the same value as {@code System.getProperty("os.arch")}. * the the same value as {@code System.getProperty("os.arch")}.
* </p>
* *
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</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/lang/Platform.java#1 $ * @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. * Enumeration of common {@code OperatingSystem}s.
* <p/> * <p>
* For {@link #Unknown unknown operating systems}, {@code getName()} will return * For {@link #Unknown unknown operating systems}, {@code getName()} will return
* the the same value as {@code System.getProperty("os.name")}. * the the same value as {@code System.getProperty("os.name")}.
* </p>
* *
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</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/lang/Platform.java#1 $ * @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. * Util class for various reflection-based operations.
* <p/> * <p>
* <em>NOTE: This class is not considered part of the public API and may be * <em>NOTE: This class is not considered part of the public API and may be
* changed without notice</em> * changed without notice</em>
* </p>
* *
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</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/lang/ReflectUtil.java#1 $ * @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 <A href="mailto:eirik.torske@twelvemonkeys.com">Eirik Torske</A>
* @author last modified by $Author: haku $ * @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 $ * @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). * return values, null-value handling and parameter names (cosmetics).
*/ */
// TODO: Consistency check: Method names, parameter sequence, Exceptions,
public final class StringUtil { public final class StringUtil {
/** /**
@@ -798,10 +798,10 @@ public final class StringUtil {
* @param pPrepend The location of fill-ins, prepend (true), * @param pPrepend The location of fill-ins, prepend (true),
* or append (false) * or append (false)
* @return a concatenated string. * @return a concatenated string.
* @todo What if source is allready longer than required length?
* @todo Consistency with cut
* @see #cut(String,int,String) * @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) { public static String pad(String pSource, int pRequiredLength, String pPadString, boolean pPrepend) {
if (pPadString == null || pPadString.length() == 0) { if (pPadString == null || pPadString.length() == 0) {
throw new IllegalArgumentException("Pad string: \"" + pPadString + "\""); throw new IllegalArgumentException("Pad string: \"" + pPadString + "\"");
@@ -873,10 +873,11 @@ public final class StringUtil {
* @param pString the string to convert * @param pString the string to convert
* @param pFormat the date format * @param pFormat the date format
* @return the date * @return the date
* @todo cache formats? *
* @see java.text.SimpleDateFormat * @see java.text.SimpleDateFormat
* @see java.text.SimpleDateFormat#SimpleDateFormat(String) * @see java.text.SimpleDateFormat#SimpleDateFormat(String)
*/ */
// TODO: cache formats?
public static Date toDate(String pString, String pFormat) { public static Date toDate(String pString, String pFormat) {
// Get the format from cache, or create new and insert // Get the format from cache, or create new and insert
// Return new date // Return new date
@@ -1203,14 +1204,15 @@ public final class StringUtil {
* hexadecimal for red, green and blue values respectively.</LI> * hexadecimal for red, green and blue values respectively.</LI>
* <LI>{@code #AARRGGBB}, as above, with AA as alpha component.</LI> * <LI>{@code #AARRGGBB}, as above, with AA as alpha component.</LI>
* </UL> * </UL>
* <p/> * <p>
* Examlples: {@code toColorString(Color.red) == "#ff0000"}, * Examlples: {@code toColorString(Color.red) == "#ff0000"},
* {@code toColorString(new Color(0xcc, 0xcc, 0xcc)) == "#cccccc"}. * {@code toColorString(new Color(0xcc, 0xcc, 0xcc)) == "#cccccc"}.
* </p>
* *
* @param pColor the color * @param pColor the color
* @return A String representation of the color on HTML/CSS form * @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) { public static String toColorString(Color pColor) {
// Not a color... // Not a color...
if (pColor == null) { 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>). * Tests a string, to see if it is an number (element of <b>Z</b>).
* Valid integers are positive natural numbers (1, 2, 3, ...), * Valid integers are positive natural numbers (1, 2, 3, ...),
* their negatives (?1, ?2, ?3, ...) and the number zero. * their negatives (?1, ?2, ?3, ...) and the number zero.
* <p/> * <p>
* Note that there is no guarantees made, that this number can be * Note that there is no guarantees made, that this number can be
* represented as either an int or a long. * represented as either an int or a long.
* </p>
* *
* @param pString The string to check. * @param pString The string to check.
* @return true if the String is a natural number. * @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. * 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. * 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". * E.g an URL "www.vg.no", to "http://www.vg.no".
* </p>
* *
* @param pSource The source string. * @param pSource The source string.
* @param pSubstring The substring to include. * @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 * Ensures that a string does not include a given substring at a given
* position. * position.
* <p/> * <p>
* Removes a given substring from a string if it is there. * Removes a given substring from a string if it is there.
* E.g an URL "http://www.vg.no", to "www.vg.no". * E.g an URL "http://www.vg.no", to "www.vg.no".
* </p>
* *
* @param pSource The source string. * @param pSource The source string.
* @param pSubstring The substring to check and possibly remove. * @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. * Gets the first substring between the given string boundaries.
* <p/>
* *
* @param pSource The source string. * @param pSource The source string.
* @param pBeginBoundaryString The string that marks the beginning. * @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. * Removes the first substring demarcated by the given string boundaries.
* <p/>
* *
* @param pSource The source string. * @param pSource The source string.
* @param pBeginBoundaryChar The character that marks the beginning of the * @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. * Removes all substrings demarcated by the given string boundaries.
* <p/>
* *
* @param pSource The source string. * @param pSource The source string.
* @param pBeginBoundaryChar The character that marks the beginning of the unwanted substring. * @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. * Gets the first element of a {@code String} containing string elements delimited by a given delimiter.
* <i>NB - Straightforward implementation!</i> * <i>NB - Straightforward implementation!</i>
* <p/>
* *
* @param pSource The source string. * @param pSource The source string.
* @param pDelimiter The delimiter used in the source string. * @param pDelimiter The delimiter used in the source string.
* @return The last string element. * @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) { public static String getFirstElement(final String pSource, final String pDelimiter) {
if (pDelimiter == null) { if (pDelimiter == null) {
throw new IllegalArgumentException("delimiter == 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 * Gets the last element of a {@code String} containing string elements
* delimited by a given delimiter. * delimited by a given delimiter.
* <i>NB - Straightforward implementation!</i> * <i>NB - Straightforward implementation!</i>
* <p/>
* *
* @param pSource The source string. * @param pSource The source string.
* @param pDelimiter The delimiter used in 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 * @param pForceDeep {@code true} to force deep {@code toString}, even
* if object overrides toString * if object overrides toString
* @return a deep string representation of the given object * @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) { public static String deepToString(Object pObject, boolean pForceDeep, int pDepth) {
// Null is null // Null is null
if (pObject == null) { if (pObject == null) {
@@ -1761,11 +1761,11 @@ public final class StringUtil {
/** /**
* Tells whether or not the given string string matches the given regular * Tells whether or not the given string string matches the given regular
* expression. * expression.
* <p/> * <p>
* An invocation of this method of the form * An invocation of this method of the form
* <tt>matches(<i>str</i>, <i>regex</i>)</tt> yields exactly the * <tt>matches(<i>str</i>, <i>regex</i>)</tt> yields exactly the
* same result as the expression * same result as the expression
* <p/> * </p>
* <blockquote><tt> {@link Pattern}. * <blockquote><tt> {@link Pattern}.
* {@link Pattern#matches(String, CharSequence) matches} * {@link Pattern#matches(String, CharSequence) matches}
* (<i>regex</i>, <i>str</i>)</tt></blockquote> * (<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 * Replaces the first substring of the given string that matches the given
* regular expression with the given pReplacement. * regular expression with the given pReplacement.
* <p/> * <p>
* An invocation of this method of the form * An invocation of this method of the form
* <tt>replaceFirst(<i>str</i>, </tt><i>regex</i>, <i>repl</i>)</tt> * <tt>
* yields exactly the same result as the expression * replaceFirst(<i>str</i>, <i>regex</i>, <i>repl</i>)
* <p/> * </tt>
* yields exactly the same result as the expression:
* </p>
* <blockquote><tt> * <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 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 pString the string
* @param pRegex the regular expression to which this string is to be matched * @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 * Replaces each substring of this string that matches the given
* regular expression with the given pReplacement. * regular expression with the given pReplacement.
* <p/> * <p>
* An invocation of this method of the form * 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 * yields exactly the same result as the expression
* <p/> * </p>
* <blockquote><tt> * <blockquote><tt>
* {@link Pattern}.{@link Pattern#compile compile}(<i>pRegex</i>). * {@link Pattern}.{@link Pattern#compile(String) compile}(<i>pRegex</i>).
* {@link Pattern#matcher matcher}(</tt><i>str</i>{@code ). * {@link Pattern#matcher matcher}(<i>str</i>{@code ).
* {@link java.util.regex.Matcher#replaceAll replaceAll}(}<i>repl</i>{@code )}</blockquote> * {@link java.util.regex.Matcher#replaceAll replaceAll}(}<i>repl</i>{@code )}
* </tt></blockquote>
* *
* @param pString the string * @param pString the string
* @param pRegex the regular expression to which this string is to be matched * @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. * Splits this string around matches of the given regular expression.
* <p/> * <p>
* The array returned by this method contains each substring of this * The array returned by this method contains each substring of this
* string that is terminated by another substring that matches the given * string that is terminated by another substring that matches the given
* expression or is terminated by the end of the string. The substrings in * 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 * 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 * expression does not match any part of the input then the resulting array
* has just one element, namely this string. * has just one element, namely this string.
* <p/> * </p>
* <p>
* The {@code pLimit} parameter controls the number of times the * The {@code pLimit} parameter controls the number of times the
* pattern is applied and therefore affects the length of the resulting * 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 * 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 * 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 * the pattern will be applied as many times as possible, the array can
* have any length, and trailing empty strings will be discarded. * have any length, and trailing empty strings will be discarded.
* <p/> * </p>
* <p>
* An invocation of this method of the form * An invocation of this method of the form
* <tt>split(<i>str</i>, <i>regex</i>, <i>n</i>)</tt> * <tt>split(<i>str</i>, <i>regex</i>, <i>n</i>)</tt>
* yields the same result as the expression * yields the same result as the expression:
* <p/> * </p>
* <blockquote>{@link Pattern}. * <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> * {@link Pattern#split(CharSequence,int) split}(<i>str</i>, <i>n</i>)</tt>
* </blockquote> * </blockquote>
* *
@@ -1878,11 +1884,12 @@ public final class StringUtil {
/** /**
* Splits this string around matches of the given regular expression. * Splits this string around matches of the given regular expression.
* <p/> * <p>
* This method works as if by invoking the two-argument * This method works as if by invoking the two-argument
* {@link #split(String,String,int) split} method with the given * {@link #split(String,String,int) split} method with the given
* expression and a limit argument of zero. * expression and a limit argument of zero.
* Trailing empty strings are therefore not included in the resulting array. * Trailing empty strings are therefore not included in the resulting array.
* </p>
* *
* @param pString the string * @param pString the string
* @param pRegex the delimiting regular expression * @param pRegex the delimiting regular expression
@@ -1901,7 +1908,7 @@ public final class StringUtil {
* from camel-style (Java in-fix) naming convention * from camel-style (Java in-fix) naming convention
* to Lisp-style naming convention (hyphen delimitted, all lower case). * to Lisp-style naming convention (hyphen delimitted, all lower case).
* Other characters in the string are left untouched. * Other characters in the string are left untouched.
* <p/> * <p>
* Eg. * Eg.
* {@code "foo" => "foo"}, * {@code "foo" => "foo"},
* {@code "fooBar" => "foo-bar"}, * {@code "fooBar" => "foo-bar"},
@@ -1910,6 +1917,7 @@ public final class StringUtil {
* {@code "HttpURLConnection" => "http-url-connection"} * {@code "HttpURLConnection" => "http-url-connection"}
* {@code "my45Caliber" => "my-45-caliber"} * {@code "my45Caliber" => "my-45-caliber"}
* {@code "allready-lisp" => "allready-lisp"} * {@code "allready-lisp" => "allready-lisp"}
* </p>
* *
* @param pString the camel-style input string * @param pString the camel-style input string
* @return the string converted to lisp-style naming convention * @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) * from Lisp-style naming convention (hyphen delimitted, all lower case)
* to camel-style (Java in-fix) naming convention. * to camel-style (Java in-fix) naming convention.
* Other characters in the string are left untouched. * Other characters in the string are left untouched.
* <p/> * <p>
* Eg. * Eg.
* {@code "foo" => "foo"}, * {@code "foo" => "foo"},
* {@code "foo-bar" => "fooBar"}, * {@code "foo-bar" => "fooBar"},
* {@code "http-request-wrapper" => "httpRequestWrapper"} * {@code "http-request-wrapper" => "httpRequestWrapper"}
* {@code "my-45-caliber" => "my45Caliber"} * {@code "my-45-caliber" => "my45Caliber"}
* {@code "allreadyCamel" => "allreadyCamel"} * {@code "allreadyCamel" => "allreadyCamel"}
* <p/> * </p>
* *
* @param pString the lisp-style input string * @param pString the lisp-style input string
* @return the string converted to camel-style * @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) * from Lisp-style naming convention (hyphen delimitted, all lower case)
* to camel-style (Java in-fix) naming convention. * to camel-style (Java in-fix) naming convention.
* Other characters in the string are left untouched. * Other characters in the string are left untouched.
* <p/> * <p>
* To create a string starting with a lower case letter * To create a string starting with a lower case letter
* (like Java variable names, etc), * (like Java variable names, etc),
* specify the {@code pFirstUpperCase} paramter to be {@code false}. * specify the {@code pFirstUpperCase} paramter to be {@code false}.
@@ -2072,14 +2080,15 @@ public final class StringUtil {
* {@code "foo" => "foo"}, * {@code "foo" => "foo"},
* {@code "foo-bar" => "fooBar"}, * {@code "foo-bar" => "fooBar"},
* {@code "allreadyCamel" => "allreadyCamel"} * {@code "allreadyCamel" => "allreadyCamel"}
* <p/> * </p>
* <p>
* To create a string starting with an upper case letter * To create a string starting with an upper case letter
* (like Java class name, etc), * (like Java class name, etc),
* specify the {@code pFirstUpperCase} paramter to be {@code true}. * specify the {@code pFirstUpperCase} paramter to be {@code true}.
* Eg. * Eg.
* {@code "http-request-wrapper" => "HttpRequestWrapper"} * {@code "http-request-wrapper" => "HttpRequestWrapper"}
* {@code "my-45-caliber" => "My45Caliber"} * {@code "my-12-monkeys" => "My12Monkeys"}
* <p/> * </p>
* *
* @param pString the lisp-style input string * @param pString the lisp-style input string
* @param pFirstUpperCase {@code true} if the first char should be * @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. * 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 * <em>NOTE: This class is not considered part of the public API and may be
* changed without notice</em> * changed without notice</em>
* </p>
* *
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a> * @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
* @author last modified by $Author: haku $ * @author last modified by $Author: haku $
@@ -200,12 +201,10 @@ public final class SystemUtil {
* @see #loadProperties(Class) * @see #loadProperties(Class)
* @see java.lang.ClassLoader#getResourceAsStream * @see java.lang.ClassLoader#getResourceAsStream
* @see java.lang.ClassLoader#getSystemResourceAsStream * @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 // Convert to name the classloader understands
String name = !StringUtil.isEmpty(pName) ? pName : pClass.getName().replace('.', '/'); 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. ;-) * Kind of like {@code org.apache.commons.lang.Validate}. Just smarter. ;-)
* <p/> * <p>
* Uses type parameterized return values, thus making it possible to check * Uses type parameterized return values, thus making it possible to check
* constructor arguments before * constructor arguments before
* they are passed on to {@code super} or {@code this} type constructors. * 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 <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
* @author last modified by $Author: haku $ * @author last modified by $Author: haku $
@@ -35,7 +35,6 @@ import java.util.*;
/** /**
* AbstractDecoratedMap * AbstractDecoratedMap
* <p/>
* *
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</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/util/AbstractDecoratedMap.java#2 $ * @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 * Creates a {@code Map} backed by a {@code HashMap}, containing all
* key/value mappings from the given {@code Map}. * key/value mappings from the given {@code Map}.
* <p/> * <p>
* <small>This is constructor is here to comply with the reccomendations for * <small>This is constructor is here to comply with the reccomendations for
* "standard" constructors in the {@code Map} interface.</small> * "standard" constructors in the {@code Map} interface.</small>
* </p>
* *
* @see #AbstractDecoratedMap(java.util.Map, java.util.Map) * @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}, * Creates a {@code Map} backed by the given backing-{@code Map},
* containing all key/value mappings from the given contents-{@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 * NOTE: The backing map is structuraly cahnged, and it should NOT be
* accessed directly, after the wrapped map is created. * accessed directly, after the wrapped map is created.
* </p>
* *
* @param pBacking the backing map of this map. Must be either empty, or * @param pBacking the backing map of this map. Must be either empty, or
* the same map as {@code pContents}. * 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 * 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 * this map contains at least one mapping to a pValue {@code v} such that
* {@code (pValue==null ? v==null : pValue.equals(v))}. * {@code (pValue==null ? v==null : pValue.equals(v))}.
* <p/> * <p>
* This implementation requires time linear in the map size for this * This implementation requires time linear in the map size for this
* operation. * operation.
* </p>
* *
* @param pValue pValue whose presence in this map is to be tested. * @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 * @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. * Abstract base class for {@code TokenIterator}s to extend.
* <p/>
* *
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</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/util/AbstractTokenIterator.java#1 $ * @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. * A {@code Map} adapter for a Java Bean.
* <p/> * <p>
* Ruthlessly stolen from * 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 { public final class BeanMap extends AbstractMap<String, Object> implements Serializable, Cloneable {
private final Object bean; private final Object bean;
@@ -268,7 +268,7 @@ public final class CollectionUtil {
* *
* @throws IllegalArgumentException if {@code pArray} is {@code null} or * @throws IllegalArgumentException if {@code pArray} is {@code null} or
* if {@code pArray} is not an array. * 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) { public static Object subArray(Object pArray, int pStart) {
return subArray(pArray, pStart, -1); return subArray(pArray, pStart, -1);
@@ -279,13 +279,14 @@ public final class CollectionUtil {
* If the sub array is same length as the original * If the sub array is same length as the original
* ({@code pStart == 0}), the original array will be returned. * ({@code pStart == 0}), the original array will be returned.
* *
* @param <T> the type of array
* @param pArray the original array * @param pArray the original array
* @param pStart the start index of the original array * @param pStart the start index of the original array
* @return a subset of the original array, or the original array itself, * @return a subset of the original array, or the original array itself,
* if {@code pStart} is 0. * if {@code pStart} is 0.
* *
* @throws IllegalArgumentException if {@code pArray} is {@code null} * @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) { public static <T> T[] subArray(T[] pArray, int pStart) {
return subArray(pArray, pStart, -1); return subArray(pArray, pStart, -1);
@@ -309,7 +310,7 @@ public final class CollectionUtil {
* *
* @throws IllegalArgumentException if {@code pArray} is {@code null} or * @throws IllegalArgumentException if {@code pArray} is {@code null} or
* if {@code pArray} is not an array. * if {@code pArray} is not an array.
* @throws ArrayIndexOutOfBoundsException if {@code pStart} < 0 * @throws ArrayIndexOutOfBoundsException if {@code pStart} &lt; 0
*/ */
@SuppressWarnings({"SuspiciousSystemArraycopy"}) @SuppressWarnings({"SuspiciousSystemArraycopy"})
public static Object subArray(Object pArray, int pStart, int pLength) { 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 * If the sub array is same length as the original, the original array will
* be returned. * be returned.
* *
* @param <T> the type of array
* @param pArray the original array * @param pArray the original array
* @param pStart the start index of the original array * @param pStart the start index of the original array
* @param pLength the length of the new 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}. * negative, or greater or equal to {@code pArray.length}.
* *
* @throws IllegalArgumentException if {@code pArray} is {@code null} * @throws IllegalArgumentException if {@code pArray} is {@code null}
* @throws ArrayIndexOutOfBoundsException if {@code pStart} < 0 * @throws ArrayIndexOutOfBoundsException if {@code pStart} &lt; 0
*/ */
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public static <T> T[] subArray(T[] pArray, int pStart, int pLength) { 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 * @param pArray the array to iterate
* @return a new {@link ListIterator} * @return a new {@link ListIterator}
* @throws IllegalArgumentException if {@code pArray} is {@code null}, * @throws IllegalArgumentException if {@code pArray} is {@code null},
* {@code pStart < 0}, or * {@code pStart &lt; 0}, or
* {@code pLength > pArray.length - pStart} * {@code pLength &gt; pArray.length - pStart}
*/ */
public static <E> ListIterator<E> iterator(final E[] pArray) { public static <E> ListIterator<E> iterator(final E[] pArray) {
return iterator(pArray, 0, notNull(pArray).length); 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 * @param pLength the number of elements to include in the iterator
* @return a new {@link ListIterator} * @return a new {@link ListIterator}
* @throws IllegalArgumentException if {@code pArray} is {@code null}, * @throws IllegalArgumentException if {@code pArray} is {@code null},
* {@code pStart < 0}, or * {@code pStart &lt; 0}, or
* {@code pLength > pArray.length - pStart} * {@code pLength &gt; pArray.length - pStart}
*/ */
public static <E> ListIterator<E> iterator(final E[] pArray, final int pStart, final int pLength) { public static <E> ListIterator<E> iterator(final E[] pArray, final int pStart, final int pLength) {
return new ArrayIterator<E>(pArray, pStart, pLength); return new ArrayIterator<E>(pArray, pStart, pLength);
@@ -32,7 +32,6 @@ package com.twelvemonkeys.util;
/** /**
* DuplicateHandler * DuplicateHandler
* <p/>
* *
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</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/util/DuplicateHandler.java#2 $ * @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 filtering. Each
* element is filtered against the given {@code Filter}, and only elements * element is filtered against the given {@code Filter}, and only elements
* that are {@code accept}ed are returned by the {@code next} method. * that are {@code accept}ed are returned by the {@code next} method.
* <p/> * <p>
* The optional {@code remove} operation is implemented, but may throw * The optional {@code remove} operation is implemented, but may throw
* {@code UnsupportedOperationException} if the underlying iterator does not * {@code UnsupportedOperationException} if the underlying iterator does not
* support the remove operation. * support the remove operation.
* </p>
* *
* @see FilterIterator.Filter * @see FilterIterator.Filter
* *
@@ -41,7 +41,6 @@ import java.util.Map;
* if the keys used are {@code Strings}. If the keys * if the keys used are {@code Strings}. If the keys
* used are not {@code String}s, it wil work as a normal * used are not {@code String}s, it wil work as a normal
* {@code java.util.Map}. * {@code java.util.Map}.
* <p/>
* *
* @see java.util.Map * @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 * Constructs a new {@code Map} with the same key-value mappings as the
* given {@code Map}. * given {@code Map}.
* The backing map will be a {@link java.util.HashMap} * 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 * NOTE: As the keys in the given map parameter will be converted to
* uppercase (if they are strings), any duplicate key/value pair where * uppercase (if they are strings), any duplicate key/value pair where
* {@code key instanceof String && key.equalsIgnoreCase(otherKey)} * {@code key instanceof String && key.equalsIgnoreCase(otherKey)}
* is true, will be lost. * is true, will be lost.
* </p>
* *
* @param pMap the map whose mappings are to be placed in this map. * @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 * Constructs a new {@code Map} with the same key-value mappings as the
* given {@code Map}. * given {@code Map}.
* <p/> * <p>
* NOTE: The backing map is structuraly cahnged, and it should NOT be * NOTE: The backing map is structuraly cahnged, and it should NOT be
* accessed directly, after the wrapped map is created. * accessed directly, after the wrapped map is created.
* <p/> * </p>
* <p>
* NOTE: As the keys in the given map parameter will be converted to * NOTE: As the keys in the given map parameter will be converted to
* uppercase (if they are strings), any duplicate key/value pair where * uppercase (if they are strings), any duplicate key/value pair where
* {@code key instanceof String && key.equalsIgnoreCase(otherKey)} * {@code key instanceof String && key.equalsIgnoreCase(otherKey)}
* is true, will be lost. * is true, will be lost.
* </p>
* *
* @param pBacking the backing map of this map. Must be either empty, or * @param pBacking the backing map of this map. Must be either empty, or
* the same map as {@code pContents}. * 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. * @return a copy of this map, with the same order and same key/value pairs.
*/ */
public Object clone() throws CloneNotSupportedException { 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; * private static final int MAX_ENTRIES = 100;
* *
* protected boolean removeEldestEntry(Map.Entry eldest) { * protected boolean removeEldestEntry(Map.Entry eldest) {
* return size() > MAX_ENTRIES; * return size() &gt; MAX_ENTRIES;
* } * }
* </pre> * </pre>
* *
@@ -39,7 +39,8 @@ import java.util.*;
* <p> * <p>
* Resembles {@code LinkedHashSet} from JDK 1.4+, but is backed by a generic * Resembles {@code LinkedHashSet} from JDK 1.4+, but is backed by a generic
* {@code LinkedMap}, rather than implementing a particular algoritm. * {@code LinkedMap}, rather than implementing a particular algoritm.
* <p/> * </p>
*
* @see LinkedMap * @see LinkedMap
* *
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a> * @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 * An (immutable) empty {@link Map}, that supports all {@code Map} operations
* without throwing exceptions (in contrast to {@link Collections#EMPTY_MAP} * without throwing exceptions (in contrast to {@link Collections#EMPTY_MAP}
* that will throw exceptions on {@code put}/{@code remove}). * that will throw exceptions on {@code put}/{@code remove}).
* <p/> * <p>
* NOTE: This is not a general purpose {@code Map} implementation, * NOTE: This is not a general purpose {@code Map} implementation,
* as the {@code put} and {@code putAll} methods will not modify the map. * as the {@code put} and {@code putAll} methods will not modify the map.
* Instances of this class will always be an empty map. * Instances of this class will always be an empty map.
* </p>
* *
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a> * @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
* @version $Id: com/twelvemonkeys/util/NullMap.java#2 $ * @version $Id: com/twelvemonkeys/util/NullMap.java#2 $
@@ -35,8 +35,8 @@ package com.twelvemonkeys.util;
* as an int, counting seconds. * as an int, counting seconds.
* *
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a> * @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
* @todo Milliseconds!
*/ */
// TODO: Milliseconds!
public class Time { public class Time {
private int time = -1; private int time = -1;
@@ -140,13 +140,13 @@ public class Time {
* <DD>m (or any multiple of m's) * <DD>m (or any multiple of m's)
* <DT>the minutes part (padded with 0's, if number has less digits than * <DT>the minutes part (padded with 0's, if number has less digits than
* the number of m's) * the number of m's)
* m -> 0,1,...,59,60,61,... * m -&gt; 0,1,...,59,60,61,...
* mm -> 00,01,...,59,60,61,... * mm -&gt; 00,01,...,59,60,61,...
* <DD>s or ss * <DD>s or ss
* <DT>the seconds part (padded with 0's, if number has less digits than * <DT>the seconds part (padded with 0's, if number has less digits than
* the number of s's) * the number of s's)
* s -> 0,1,...,59 * s -&gt; 0,1,...,59
* ss -> 00,01,...,59 * ss -&gt; 00,01,...,59
* <DD>S * <DD>S
* <DT>all seconds (including the ones above 59) * <DT>all seconds (including the ones above 59)
* </DL> * </DL>
@@ -46,13 +46,13 @@ import java.util.Vector;
* <DD>m (or any multiple of m's) * <DD>m (or any multiple of m's)
* <DT>the minutes part (padded with 0's, if number has less digits than * <DT>the minutes part (padded with 0's, if number has less digits than
* the number of m's) * the number of m's)
* m -> 0,1,...,59,60,61,... * m -&gt; 0,1,...,59,60,61,...
* mm -> 00,01,...,59,60,61,... * mm -&gt; 00,01,...,59,60,61,...
* <DD>s or ss * <DD>s or ss
* <DT>the seconds part (padded with 0's, if number has less digits than * <DT>the seconds part (padded with 0's, if number has less digits than
* the number of s's) * the number of s's)
* s -> 0,1,...,59 * s -&gt; 0,1,...,59
* ss -> 00,01,...,59 * ss -&gt; 00,01,...,59
* <DD>S * <DD>S
* <DT>all seconds (including the ones above 59) * <DT>all seconds (including the ones above 59)
* </DL> * </DL>
@@ -60,10 +60,6 @@ import java.util.Vector;
* May not handle all cases, and formats... ;-) * May not handle all cases, and formats... ;-)
* Safest is: Always delimiters between the minutes (m) and seconds (s) part. * Safest is: Always delimiters between the minutes (m) and seconds (s) part.
* <P> * <P>
* TODO:
* Move to com.twelvemonkeys.text?
* Milliseconds!
* Fix bugs.
* Known bugs: * Known bugs:
* <P> * <P>
* The last character in the formatString is not escaped, while it should be. * The last character in the formatString is not escaped, while it should be.
@@ -76,6 +72,10 @@ import java.util.Vector;
* *
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a> * @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 { public class TimeFormat extends Format {
final static String MINUTE = "m"; final static String MINUTE = "m";
final static String SECOND = "s"; final static String SECOND = "s";
@@ -37,8 +37,9 @@ import java.util.*;
* A {@code Map} implementation that removes (exipres) its elements after * 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}, * 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. * or can be instantiated with any given {@code Map} as backing.
* <P/> * <p>
* Notes to consider when using this map: * Notes to consider when using this map:
* </p>
* <ul> * <ul>
* <li>Elements may not expire on the exact millisecond as expected.</li> * <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 * <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> * @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 $ * @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 { public class TimeoutMap<K, V> extends AbstractDecoratedMap<K, V> implements ExpiringMap<K, V>, Serializable, Cloneable {
/** /**
* Expiry time * 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. * Creates a {@code TimeoutMap} with the default expiry time of 1 minute.
* This {@code TimeoutMap} will be backed by a new {@code HashMap} instance. * This {@code TimeoutMap} will be backed by a new {@code HashMap} instance.
* <p/> * <p>
* <small>This is constructor is here to comply with the reccomendations for * <small>This is constructor is here to comply with the recommendations for
* "standard" constructors in the {@code Map} interface.</small> * "standard" constructors in the {@code Map} interface.</small>
* </p>
* *
* @see #TimeoutMap(long) * @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. * with the default expiry time of 1 minute.
* This {@code TimeoutMap} will be backed by a new {@code HashMap} instance, * This {@code TimeoutMap} will be backed by a new {@code HashMap} instance,
* and <em>not</em> the map passed in as a paramter. * and <em>not</em> the map passed in as a paramter.
* <p/> * <p>
* <small>This is constructor is here to comply with the reccomendations for * <small>This is constructor is here to comply with the recommendations for
* "standard" constructors in the {@code Map} interface.</small> * "standard" constructors in the {@code Map} interface.</small>
* </p>
* *
* @param pContents the map whose mappings are to be placed in this map. * @param pContents the map whose mappings are to be placed in this map.
* May be {@code null}. * 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). * Creates a {@code TimeoutMap} with the given expiry time (milliseconds).
* This {@code TimeoutMap} will be backed by the given {@code Map}. * This {@code TimeoutMap} will be backed by the given {@code Map}.
* <P/> * <p>
* <EM>Note that structurally modifying the backing map directly (not * <em>Note that structurally modifying the backing map directly (not
* through this map or its collection views), is not allowed, and will * 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 pBacking the map that will be used as backing.
* @param pContents the map whose mappings are to be placed in this map. * @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... * Okay, I guess this do resemble DCL...
* *
* @todo Write some exhausting multi-threaded unit-tests.
*
* @param pTime now * @param pTime now
*/ */
// TODO: Write some exhausting multi-threaded unit-tests.
private synchronized void removeExpiredEntriesSynced(long pTime) { private synchronized void removeExpiredEntriesSynced(long pTime) {
if (pTime > nextExpiryTime) { if (pTime > nextExpiryTime) {
//// ////
@@ -35,7 +35,6 @@ import java.util.Iterator;
/** /**
* TokenIterator, Iterator-based replacement for StringTokenizer. * TokenIterator, Iterator-based replacement for StringTokenizer.
* <p/>
* *
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</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/util/TokenIterator.java#1 $ * @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. * The converter (singleton). Converts strings to objects and back.
* This is the entry point to the converter framework. * This is the entry point to the converter framework.
* <p/> * <p>
* By default, converters for {@link com.twelvemonkeys.util.Time}, {@link Date} * By default, converters for {@link com.twelvemonkeys.util.Time}, {@link Date}
* and {@link Object} * and {@link Object}
* (the {@link DefaultConverter}) are registered by this class' static * (the {@link DefaultConverter}) are registered by this class' static
* initializer. You might remove them using the * initializer. You might remove them using the
* {@code unregisterConverter} method. * {@code unregisterConverter} method.
* </p>
* *
* @see #registerConverter(Class, PropertyConverter) * @see #registerConverter(Class, PropertyConverter)
* @see #unregisterConverter(Class) * @see #unregisterConverter(Class)
@@ -105,12 +106,13 @@ public abstract class Converter implements PropertyConverter {
* Registers a converter for a given type. * Registers a converter for a given type.
* This converter will also be used for all subclasses, unless a more * This converter will also be used for all subclasses, unless a more
* specific version is registered. * specific version is registered.
* </p> * <p>
* By default, converters for {@link com.twelvemonkeys.util.Time}, {@link Date} * By default, converters for {@link com.twelvemonkeys.util.Time}, {@link Date}
* and {@link Object} * and {@link Object}
* (the {@link DefaultConverter}) are registered by this class' static * (the {@link DefaultConverter}) are registered by this class' static
* initializer. You might remove them using the * initializer. You might remove them using the
* {@code unregisterConverter} method. * {@code unregisterConverter} method.
* </p>
* *
* @param pType the (super) type to register a converter for * @param pType the (super) type to register a converter for
* @param pConverter the converter * @param pConverter the converter
@@ -41,9 +41,10 @@ import java.util.Locale;
/** /**
* Converts strings to dates and back. * Converts strings to dates and back.
* <p/> * <p>
* <small>This class has a static cache of {@code DateFormats}, to avoid * <small>This class has a static cache of {@code DateFormats}, to avoid
* creation and parsing of date formats every time one is used.</small> * 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 <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
* @author last modified by $Author: haku $ * @author last modified by $Author: haku $
@@ -38,12 +38,13 @@ import java.lang.reflect.InvocationTargetException;
/** /**
* Converts strings to objects and back. * Converts strings to objects and back.
* <p/> * <p>
* This converter first tries to create an object, using the class' single * This converter first tries to create an object, using the class' single
* string argument constructor ({@code &lt;type&gt;(String)}) if found, * string argument constructor ({@code &lt;type&gt;(String)}) if found,
* otherwise, an attempt to call * otherwise, an attempt to call
* the class' static {@code valueOf(String)} method. If both fails, a * the class' static {@code valueOf(String)} method. If both fails, a
* {@link ConversionException} is thrown. * {@link ConversionException} is thrown.
* </p>
* *
* @author <A href="haraldk@iconmedialab.no">Harald Kuhr</A> * @author <A href="haraldk@iconmedialab.no">Harald Kuhr</A>
* @author last modified by $Author: haku $ * @author last modified by $Author: haku $
@@ -43,9 +43,10 @@ import java.util.Map;
/** /**
* Converts strings to numbers and back. * Converts strings to numbers and back.
* <p/> * <p>
* <small>This class has a static cache of {@code NumberFormats}, to avoid * <small>This class has a static cache of {@code NumberFormats}, to avoid
* creation and parsing of number formats every time one is used.</small> * 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 <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
* @author last modified by $Author: haku $ * @author last modified by $Author: haku $
@@ -36,9 +36,10 @@ import com.twelvemonkeys.util.TimeFormat;
/** /**
* Converts strings to times and back. * Converts strings to times and back.
* <p/> * <p>
* <small>This class has a static cache of {@code TimeFormats}, to avoid creation and * <small>This class has a static cache of {@code TimeFormats}, to avoid creation and
* parsing of timeformats every time one is used.</small> * parsing of timeformats every time one is used.</small>
* </p>
* *
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a> * @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
* @author last modified by $Author: haku $ * @author last modified by $Author: haku $
@@ -40,8 +40,8 @@ import java.util.regex.PatternSyntaxException;
/** /**
* {@code StringTokenizer} replacement, that uses regular expressions to split * {@code StringTokenizer} replacement, that uses regular expressions to split
* strings into tokens. * 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> * @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 $ * @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. * This class parses arbitrary strings against a wildcard string mask provided.
* The wildcard characters are '*' and '?'. * The wildcard characters are '*' and '?'.
* <p/> * <p>
* The string masks provided are treated as case sensitive.<br> * 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. * 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> * <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>
* <p><hr style="height=1"><p> * <hr style="height=1">
* <p/> * <p>
* This task is performed based on regular expression techniques. * This task is performed based on regular expression techniques.
* The possibilities of string generation with the well-known wildcard characters stated above, * 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> * 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>
* 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> * &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. * 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. * 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: * 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 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 <b>language</b> accepted by this automaton is the set of all strings accepted by this automaton.<br>
* The formal automaton quintuple consists of: * The formal automaton quintuple consists of:
* </p>
* <ol> * <ol>
* <li>A finite set of <b>states</b>, depending on the wildcard string mask. * <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. * 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. * Parsing faults must be reported to the author.
* </small> * </small>
* </ol> * </ol>
* <p/> * <hr style="height=1">
* <p><hr style="height=1"><p> * <p>
* <p/>
* Examples of usage:<br> * Examples of usage:<br>
* This example will return "Accepted!". * This example will return "Accepted!".
* </p>
* <pre> * <pre>
* WildcardStringParser parser = new WildcardStringParser("*_28????.jp*"); * WildcardStringParser parser = new WildcardStringParser("*_28????.jp*");
* if (parser.parseString("gupu_280915.jpg")) { * if (parser.parseString("gupu_280915.jpg")) {
@@ -105,12 +103,10 @@ import java.io.PrintStream;
* System.out.println("Not accepted!"); * System.out.println("Not accepted!");
* } * }
* </pre> * </pre>
* <p/> * <hr style="height=1">
* <p><hr style="height=1"><p> * <p>
* <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. * 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> * @author <a href="mailto:eirik.torske@iconmedialab.no">Eirik Torske</a>
* @deprecated Will probably be removed in the near future * @deprecated Will probably be removed in the near future
@@ -146,7 +142,6 @@ public class WildcardStringParser {
/** /**
* Creates a wildcard string parser. * Creates a wildcard string parser.
* <p/>
* *
* @param pStringMask the wildcard string mask. * @param pStringMask the wildcard string mask.
*/ */
@@ -156,7 +151,6 @@ public class WildcardStringParser {
/** /**
* Creates a wildcard string parser. * Creates a wildcard string parser.
* <p/>
* *
* @param pStringMask the wildcard string mask. * @param pStringMask the wildcard string mask.
* @param pDebugging {@code true} will cause debug messages to be emitted to {@code System.out}. * @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. * Creates a wildcard string parser.
* <p/>
* *
* @param pStringMask the wildcard string mask. * @param pStringMask the wildcard string mask.
* @param pDebugging {@code true} will cause debug messages to be emitted. * @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. * Gets the string mask that was used when building the parser atomaton.
* <p/>
* *
* @return the string mask used for building the parser automaton. * @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. * Parses a string according to the rules stated above.
* <p/>
* *
* @param pStringToParse the string to parse. * @param pStringToParse the string to parse.
* @return {@code true} if and only if the string are accepted by the automaton. * @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. * An optional interface that may be implemented by service provider objects.
* <p/> * <p>
* If this interface is implemented, the service provider objects will receive * If this interface is implemented, the service provider objects will receive
* notification of registration and deregistration from the * notification of registration and deregistration from the
* {@code ServiceRegistry}. * {@code ServiceRegistry}.
* </p>
* *
* @see ServiceRegistry * @see ServiceRegistry
* *
@@ -33,7 +33,7 @@ package com.twelvemonkeys.util.service;
/** /**
* Error thrown by the {@code ServiceRegistry} in case of a configuration * Error thrown by the {@code ServiceRegistry} in case of a configuration
* error. * error.
* <p/> *
* @see ServiceRegistry * @see ServiceRegistry
* *
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a> * @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
@@ -39,26 +39,32 @@ import java.util.*;
/** /**
* A registry for service provider objects. * A registry for service provider objects.
* <p/> * <p>
* Service providers are looked up from the classpath, under the path * Service providers are looked up from the classpath, under the path
* {@code META-INF/services/}&lt;full-class-name&gt;. * {@code META-INF/services/}&lt;full-class-name&gt;.
* <p/> * </p>
* For example:<br/> * <p>
* For example:
* <br>
* {@code META-INF/services/com.company.package.spi.MyService}. * {@code META-INF/services/com.company.package.spi.MyService}.
* <p/> * </p>
* <p>
* The file should contain a list of fully-qualified concrete class names, * The file should contain a list of fully-qualified concrete class names,
* one per line. * one per line.
* <p/> * </p>
* <p>
* The <em>full-class-name</em> represents an interface or (typically) an * 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. * 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 * Note that only one instance of a concrete subclass may be registered with a
* specific category at a time. * specific category at a time.
* <p/> * </p>
* <p>
* <small>Implementation detail: This class is a clean room implementation of * <small>Implementation detail: This class is a clean room implementation of
* a service registry and does not use the proprietary {@code sun.misc.Service} * 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>. * class that is referred to in the <em>JAR File specification</em>.
* This class should work on any Java platform. * This class should work on any Java platform.
* </small> * </small>
* </p>
* *
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a> * @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
* @version $Id: com/twelvemonkeys/util/service/ServiceRegistry.java#2 $ * @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 * Creates a {@code ServiceRegistry} instance with a set of categories
* taken from the {@code pCategories} argument. * taken from the {@code pCategories} argument.
* <p/> * <p>
* The categories are constant during the lifetime of the registry, and may * The categories are constant during the lifetime of the registry, and may
* not be changed after initial creation. * not be changed after initial creation.
* </p>
* *
* @param pCategories an {@code Iterator} containing * @param pCategories an {@code Iterator} containing
* {@code Class} objects that defines this registry's categories. * {@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 * Returns an {@code Iterator} containing all providers in the given
* category. * category.
* <p/> * <p>
* The iterator supports removal. * The iterator supports removal.
* <p/> * </p>
* <p>
* <small> * <small>
* NOTE: Removing a provider from the iterator, deregisters the current * NOTE: Removing a provider from the iterator, deregisters the current
* provider (as returned by the last invocation of {@code next()}) from * provider (as returned by the last invocation of {@code next()}) from
* {@code pCategory}, it does <em>not</em> remove the provider * {@code pCategory}, it does <em>not</em> remove the provider
* from other categories in the registry. * from other categories in the registry.
* </small> * </small>
* </p>
* *
* @param pCategory the category class * @param pCategory the category class
* @return an {@code Iterator} containing all providers in the given * @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. * Returns an {@code Iterator} containing all categories in this registry.
* <p/> * <p>
* The iterator does not support removal. * The iterator does not support removal.
* </p>
* *
* @return an {@code Iterator} containing all categories in this registry. * @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 * Returns an {@code Iterator} containing all categories in this registry
* the given {@code pProvider} <em>may be registered with</em>. * the given {@code pProvider} <em>may be registered with</em>.
* <p/> * <p>
* The iterator does not support removal. * The iterator does not support removal.
* </p>
* *
* @param pProvider the provider instance * @param pProvider the provider instance
* @return an {@code Iterator} containing all categories in this registry * @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 * Returns an {@code Iterator} containing all categories in this registry
* the given {@code pProvider} <em>is currently registered with</em>. * the given {@code pProvider} <em>is currently registered with</em>.
* <p/> * <p>
* The iterator supports removal. * The iterator supports removal.
* <p/> * </p>
* <p>
* <small> * <small>
* NOTE: Removing a category from the iterator, de-registers * NOTE: Removing a category from the iterator, de-registers
* {@code pProvider} from the current category (as returned by the last * {@code pProvider} from the current category (as returned by the last
* invocation of {@code next()}), it does <em>not</em> remove the category * invocation of {@code next()}), it does <em>not</em> remove the category
* itself from the registry. * itself from the registry.
* </small> * </small>
* </p>
* *
* @param pProvider the provider instance * @param pProvider the provider instance
* @return an {@code Iterator} containing all categories in this registry * @return an {@code Iterator} containing all categories in this registry
@@ -30,9 +30,10 @@
/** /**
* Provides a service provider registry. * Provides a service provider registry.
* <p/> * <p>
* This package contains a service provider registry, as specified in the * 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>. * <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> * @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 * BeanMapTestCase
* <p/>
* @todo Extend with BeanMap specific tests
* *
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a> * @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
* @author last modified by $Author: haku $ * @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 $ * @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 class BeanMapTest extends MapAbstractTest {
public boolean isPutAddSupported() { public boolean isPutAddSupported() {
+1 -1
View File
@@ -4,7 +4,7 @@
<parent> <parent>
<groupId>com.twelvemonkeys</groupId> <groupId>com.twelvemonkeys</groupId>
<artifactId>twelvemonkeys</artifactId> <artifactId>twelvemonkeys</artifactId>
<version>3.4</version> <version>3.4.4-SNAPSHOT</version>
</parent> </parent>
<groupId>com.twelvemonkeys.common</groupId> <groupId>com.twelvemonkeys.common</groupId>
<artifactId>common</artifactId> <artifactId>common</artifactId>
+1 -1
View File
@@ -4,7 +4,7 @@
<parent> <parent>
<groupId>com.twelvemonkeys</groupId> <groupId>com.twelvemonkeys</groupId>
<artifactId>twelvemonkeys</artifactId> <artifactId>twelvemonkeys</artifactId>
<version>3.4</version> <version>3.4.4-SNAPSHOT</version>
</parent> </parent>
<groupId>com.twelvemonkeys.contrib</groupId> <groupId>com.twelvemonkeys.contrib</groupId>
<artifactId>contrib</artifactId> <artifactId>contrib</artifactId>
+1 -1
View File
@@ -4,7 +4,7 @@
<parent> <parent>
<groupId>com.twelvemonkeys.imageio</groupId> <groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio</artifactId> <artifactId>imageio</artifactId>
<version>3.4</version> <version>3.4.4-SNAPSHOT</version>
</parent> </parent>
<artifactId>imageio-batik</artifactId> <artifactId>imageio-batik</artifactId>
<name>TwelveMonkeys :: ImageIO :: Batik Plugin</name> <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.*;
import org.apache.batik.transcoder.image.ImageTranscoder; import org.apache.batik.transcoder.image.ImageTranscoder;
import org.apache.batik.util.ParsedURL; import org.apache.batik.util.ParsedURL;
import org.apache.batik.util.SVGConstants;
import org.w3c.dom.DOMImplementation; import org.w3c.dom.DOMImplementation;
import org.w3c.dom.Document; import org.w3c.dom.Document;
import org.w3c.dom.svg.SVGSVGElement; import org.w3c.dom.svg.SVGSVGElement;
@@ -68,7 +69,6 @@ import java.util.Map;
/** /**
* Image reader for SVG document fragments. * Image reader for SVG document fragments.
* <p/>
* *
* @author Harald Kuhr * @author Harald Kuhr
* @author Inpspired by code from the Batik Team * @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 { public BufferedImage read(int pIndex, ImageReadParam pParam) throws IOException {
checkBounds(pIndex); checkBounds(pIndex);
String baseURI = null;
if (pParam instanceof SVGReadParam) { if (pParam instanceof SVGReadParam) {
SVGReadParam svgParam = (SVGReadParam) pParam; 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 // Note: The cast to Map invokes a different method that preserves
// unset defaults, DO NOT REMOVE! // unset defaults, DO NOT REMOVE!
rasterizer.setTranscodingHints((Map) paramsToHints(svgParam)); rasterizer.setTranscodingHints((Map) paramsToHints(svgParam));
// Get the base URI (not a hint)
baseURI = svgParam.getBaseURI();
} }
Dimension size; Dimension size = null;
if (pParam != null && (size = pParam.getSourceRenderSize()) != null) { if (pParam != null) {
// Use size... size = pParam.getSourceRenderSize();
} }
else { if (size == null) {
size = new Dimension(getWidth(pIndex), getHeight(pIndex)); size = new Dimension(getWidth(pIndex), getHeight(pIndex));
} }
@@ -137,7 +138,6 @@ public class SVGImageReader extends ImageReaderBase {
try { try {
processImageStarted(pIndex); processImageStarted(pIndex);
rasterizer.transcoderInput.setURI(baseURI);
BufferedImage image = rasterizer.getImage(); BufferedImage image = rasterizer.getImage();
Graphics2D g = destination.createGraphics(); Graphics2D g = destination.createGraphics();
@@ -155,10 +155,16 @@ public class SVGImageReader extends ImageReaderBase {
return destination; return destination;
} }
catch (TranscoderException e) { 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 { private TranscodingHints paramsToHints(SVGReadParam pParam) throws IOException {
TranscodingHints hints = new TranscodingHints(); TranscodingHints hints = new TranscodingHints();
// Note: We must allow generic ImageReadParams, so converting to // Note: We must allow generic ImageReadParams, so converting to
@@ -174,8 +180,8 @@ public class SVGImageReader extends ImageReaderBase {
} }
if (size != null) { if (size != null) {
hints.put(ImageTranscoder.KEY_WIDTH, new Float(size.getWidth())); hints.put(ImageTranscoder.KEY_WIDTH, (float) size.getWidth());
hints.put(ImageTranscoder.KEY_HEIGHT, new Float(size.getHeight())); hints.put(ImageTranscoder.KEY_HEIGHT, (float) size.getHeight());
} }
// Set area of interest // 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 // Avoid that the batik transcoder scales the AOI up to original image size
if (size == null) { if (size == null) {
hints.put(ImageTranscoder.KEY_WIDTH, new Float(region.getWidth())); hints.put(ImageTranscoder.KEY_WIDTH, (float) region.getWidth());
hints.put(ImageTranscoder.KEY_HEIGHT, new Float(region.getHeight())); hints.put(ImageTranscoder.KEY_HEIGHT, (float) region.getHeight());
} }
else { else {
// Need to resize here... // Need to resize here...
double xScale = size.getWidth() / origSize.getWidth(); double xScale = size.getWidth() / origSize.getWidth();
double yScale = size.getHeight() / origSize.getHeight(); double yScale = size.getHeight() / origSize.getHeight();
hints.put(ImageTranscoder.KEY_WIDTH, new Float(region.getWidth() * xScale)); hints.put(ImageTranscoder.KEY_WIDTH, (float) (region.getWidth() * xScale));
hints.put(ImageTranscoder.KEY_HEIGHT, new Float(region.getHeight() * yScale)); hints.put(ImageTranscoder.KEY_HEIGHT, (float) (region.getHeight() * yScale));
} }
} }
else if (size != null) { else if (size != null) {
@@ -219,7 +225,7 @@ public class SVGImageReader extends ImageReaderBase {
return null; return null;
} }
public ImageReadParam getDefaultReadParam() { public SVGReadParam getDefaultReadParam() {
return new SVGReadParam(); return new SVGReadParam();
} }
@@ -249,13 +255,14 @@ public class SVGImageReader extends ImageReaderBase {
/** /**
* An image transcoder that stores the resulting image. * 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 * NOTE: This class includes a lot of copy and paste code from the Batik classes
* and needs major refactoring! * and needs major refactoring!
* </p>
*/ */
private class Rasterizer extends SVGAbstractTranscoder /*ImageTranscoder*/ { private class Rasterizer extends SVGAbstractTranscoder /*ImageTranscoder*/ {
BufferedImage image = null; private BufferedImage image;
private TranscoderInput transcoderInput; private TranscoderInput transcoderInput;
private float defaultWidth; private float defaultWidth;
private float defaultHeight; private float defaultHeight;
@@ -266,17 +273,19 @@ public class SVGImageReader extends ImageReaderBase {
private TranscoderException exception; private TranscoderException exception;
private BridgeContext context; private BridgeContext context;
public BufferedImage createImage(final int width, final int height) { private BufferedImage createImage(final int width, final int height) {
return ImageUtil.createTransparent(width, height);//, BufferedImage.TYPE_INT_ARGB); return ImageUtil.createTransparent(width, height); // BufferedImage.TYPE_INT_ARGB
} }
// This is cheating... We don't fully transcode after all // This is cheating... We don't fully transcode after all
protected void transcode(Document document, final String uri, final TranscoderOutput output) throws TranscoderException { protected void transcode(Document document, final String uri, final TranscoderOutput output) throws TranscoderException {
// Sets up root, curTxf & curAoi // Sets up root, curTxf & curAoi
// ---- // ----
if ((document != null) && !(document.getImplementation() instanceof SVGDOMImplementation)) { if (document != null) {
DOMImplementation impl = (DOMImplementation) hints.get(KEY_DOM_IMPLEMENTATION); if (!(document.getImplementation() instanceof SVGDOMImplementation)) {
document = DOMUtilities.deepCloneDocument(document, impl); DOMImplementation impl = (DOMImplementation) hints.get(KEY_DOM_IMPLEMENTATION);
document = DOMUtilities.deepCloneDocument(document, impl);
}
if (uri != null) { if (uri != null) {
try { try {
@@ -318,7 +327,7 @@ public class SVGImageReader extends ImageReaderBase {
// get the 'width' and 'height' attributes of the SVG document // get the 'width' and 'height' attributes of the SVG document
Dimension2D docSize = ctx.getDocumentSize(); Dimension2D docSize = ctx.getDocumentSize();
if (docSize != null) { if (docSize != null) {
defaultWidth = (float) docSize.getWidth(); defaultWidth = (float) docSize.getWidth();
defaultHeight = (float) docSize.getHeight(); defaultHeight = (float) docSize.getHeight();
} }
@@ -326,6 +335,14 @@ public class SVGImageReader extends ImageReaderBase {
defaultWidth = 200; defaultWidth = 200;
defaultHeight = 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 // Hack to work around exception above
if (root != null) { if (root != null) {
@@ -346,8 +363,8 @@ public class SVGImageReader extends ImageReaderBase {
processReadAborted(); processReadAborted();
return null; return null;
} }
processImageProgress(10f);
processImageProgress(10f);
// Hacky workaround below... // Hacky workaround below...
if (gvtRoot == null) { if (gvtRoot == null) {
@@ -369,6 +386,7 @@ public class SVGImageReader extends ImageReaderBase {
} }
ctx = context; ctx = context;
// /Hacky // /Hacky
if (abortRequested()) { if (abortRequested()) {
processReadAborted(); processReadAborted();
return null; return null;
@@ -489,11 +507,9 @@ public class SVGImageReader extends ImageReaderBase {
// now we are sure that the aoi is the image size // now we are sure that the aoi is the image size
Shape raoi = new Rectangle2D.Float(0, 0, width, height); Shape raoi = new Rectangle2D.Float(0, 0, width, height);
// Warning: the renderer's AOI must be in user space // Warning: the renderer's AOI must be in user space
renderer.repaint(curTxf.createInverse(). renderer.repaint(curTxf.createInverse().createTransformedShape(raoi));
createTransformedShape(raoi));
// NOTE: repaint above cause nullpointer exception with fonts..??? // NOTE: repaint above cause nullpointer exception with fonts..???
BufferedImage rend = renderer.getOffScreen(); BufferedImage rend = renderer.getOffScreen();
renderer = null; // We're done with it... renderer = null; // We're done with it...
@@ -558,18 +574,40 @@ public class SVGImageReader extends ImageReaderBase {
return image; return image;
} }
protected int getDefaultWidth() throws TranscoderException { int getDefaultWidth() throws TranscoderException {
init(); init();
return (int) (defaultWidth + 0.5); return (int) Math.ceil(defaultWidth);
} }
protected int getDefaultHeight() throws TranscoderException { int getDefaultHeight() throws TranscoderException {
init(); init();
return (int) (defaultHeight + 0.5); return (int) Math.ceil(defaultHeight);
} }
public void setInput(final TranscoderInput pInput) { void setInput(final TranscoderInput pInput) {
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