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