mirror of
https://github.com/haraldk/TwelveMonkeys.git
synced 2026-05-18 00:00:03 -04:00
Compare commits
99 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| b19e45a911 | |||
| a5b6cf898d | |||
| ce597c437d | |||
| fa4b3787d0 | |||
| 3c18e8a510 | |||
| 206481038e | |||
| cff4d88991 | |||
| 8ea8e061a9 | |||
| 101ad18f71 | |||
| 08b441a17e | |||
| b6c76d8566 | |||
| 3f74b2ddf3 | |||
| 46b48f32c3 | |||
| a07d0285fe | |||
| 98de4ad4ec | |||
| aa82612765 | |||
| 9213da3184 | |||
| a5e2226a5a | |||
| 773bedccca | |||
| 6bcc17a020 | |||
| 37d1da9b9d | |||
| 8cf1405dfc | |||
| 8c37d19928 | |||
| 87cd506fdd | |||
| e0c7edebbd | |||
| 5d13bd653f | |||
| 2d974874a9 | |||
| f625622b10 | |||
| dbdd7ae3f1 | |||
| 73883ebf99 | |||
| 970b238066 | |||
| 6cb8ac4b68 | |||
| 1a2a4edfe8 | |||
| a12a1f73b5 | |||
| 46bfdd93d8 | |||
| 447ef6b8eb | |||
| c19b6ede0a | |||
| 401c6355a1 | |||
| be0cf16124 | |||
| 47b0cd6e9a | |||
| b52ab149b3 | |||
| 900c26a5ac | |||
| 7233c593ac | |||
| 8159ba1245 | |||
| 92581a077b | |||
| f87b4d6748 | |||
| 0495f6e266 | |||
| bc7c8ba20c | |||
| 0c270f8343 | |||
| e1db332dca | |||
| 016977e382 | |||
| 134eecc59f | |||
| 16c78052ee | |||
| b51e8ccf6e | |||
| 76a9ff1122 | |||
| e9996f096f | |||
| 93d42e1c24 | |||
| 5824167600 | |||
| 126956ebd0 | |||
| d54ceba3ff | |||
| 11ee7e5e23 | |||
| 954dffd213 | |||
| b7b2a61c93 | |||
| 3cf6a4b836 | |||
| a93be99933 | |||
| b19bd1441f | |||
| 482af60534 | |||
| f55a6d30dd | |||
| e5f6227479 | |||
| 01d6fc8b49 | |||
| f133ea7d61 | |||
| 3d5cf0eecd | |||
| 975e23c28f | |||
| be60f307f7 | |||
| 3e783fba92 | |||
| 35ffe29e03 | |||
| 55155aa61c | |||
| 9e9decd5dd | |||
| 3c0b78549e | |||
| 46db5a2fbf | |||
| f6a9477279 | |||
| b7192ae857 | |||
| c0b2769e3b | |||
| 6c27ec6b30 | |||
| 0c90196357 | |||
| 48f82a159f | |||
| 7105738811 | |||
| 10aa4ba41e | |||
| 6fb06da4d7 | |||
| a963e1c355 | |||
| 966a9da45d | |||
| 319b2c4e18 | |||
| e9bf7d080c | |||
| fb3691e2ee | |||
| 25f9cc5c55 | |||
| 94777ddc96 | |||
| a4c12d0d64 | |||
| 08a69886b1 | |||
| ab85ff0ec8 |
@@ -1,17 +0,0 @@
|
||||
version: 2
|
||||
updates:
|
||||
# Maven/Java library updates
|
||||
- package-ecosystem: "maven"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
cooldown:
|
||||
default-days: 7
|
||||
open-pull-requests-limit: 10
|
||||
# GitHub actions updates
|
||||
- package-ecosystem: "github-actions"
|
||||
directory: "/.github/workflows"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
cooldown:
|
||||
default-days: 7
|
||||
+22
-60
@@ -1,14 +1,6 @@
|
||||
name: CI
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- '**'
|
||||
- '!dependabot/**'
|
||||
pull_request:
|
||||
branches: [ 'master' ]
|
||||
|
||||
permissions: read-all
|
||||
on: [ push, pull_request ]
|
||||
|
||||
jobs:
|
||||
test:
|
||||
@@ -17,67 +9,37 @@ jobs:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ ubuntu-latest, windows-latest, macos-latest ]
|
||||
java: [ 11, 17, 21, 25 ]
|
||||
java: [ 8, 11, 17 ]
|
||||
runs-on: ${{ matrix.os }}
|
||||
permissions:
|
||||
checks: write
|
||||
steps:
|
||||
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
|
||||
- uses: actions/setup-java@f2beeb24e141e01a676f977032f5a29d81c9e27e # v5.1.0
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-java@v2
|
||||
with:
|
||||
distribution: 'temurin'
|
||||
java-version: ${{ matrix.java }}
|
||||
java-package: jdk
|
||||
cache: 'maven'
|
||||
- name: Run Tests
|
||||
run: mvn --batch-mode --no-transfer-progress test
|
||||
run: mvn test
|
||||
- name: Publish Test Report
|
||||
uses: mikepenz/action-junit-report@e08919a3b1fb83a78393dfb775a9c37f17d8eea6 # v5
|
||||
uses: mikepenz/action-junit-report@v2
|
||||
if: ${{ !cancelled() }}
|
||||
with:
|
||||
report_paths: "**/target/surefire-reports/TEST*.xml"
|
||||
check_name: Unit Test Results for OpenJDK ${{ matrix.java }} on ${{ matrix.os }}
|
||||
|
||||
test-jdk8:
|
||||
name: Test OpenJDK 8 on ${{ matrix.os }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ ubuntu-latest, windows-latest, macos-14 ]
|
||||
runs-on: ${{ matrix.os }}
|
||||
permissions:
|
||||
checks: write
|
||||
steps:
|
||||
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
|
||||
- uses: actions/setup-java@f2beeb24e141e01a676f977032f5a29d81c9e27e # v5.1.0
|
||||
with:
|
||||
distribution: 'zulu'
|
||||
java-version: '8'
|
||||
java-package: jdk
|
||||
cache: 'maven'
|
||||
- name: Run Tests
|
||||
run: mvn --batch-mode --no-transfer-progress test
|
||||
- name: Publish Test Report
|
||||
uses: mikepenz/action-junit-report@e08919a3b1fb83a78393dfb775a9c37f17d8eea6 # v5
|
||||
if: ${{ !cancelled() }}
|
||||
with:
|
||||
report_paths: "**/target/surefire-reports/TEST*.xml"
|
||||
check_name: Unit Test Results for OpenJDK ${{ matrix.java }} on ${{ matrix.os }}
|
||||
|
||||
test-oracle:
|
||||
test_oracle:
|
||||
name: Test Oracle JDK 8 with KCMS=${{ matrix.kcms }}
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
checks: write
|
||||
strategy:
|
||||
matrix:
|
||||
kcms: [ true, false ]
|
||||
steps:
|
||||
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
|
||||
- uses: actions/checkout@v2
|
||||
- run: |
|
||||
download_url="https://javadl.oracle.com/webapps/download/AutoDL?BundleId=245038_d3c52aa6bfa54d3ca74e617f18309292"
|
||||
wget -O $RUNNER_TEMP/java_package.tar.gz $download_url
|
||||
- uses: actions/setup-java@f2beeb24e141e01a676f977032f5a29d81c9e27e # v5.1.0
|
||||
- uses: actions/setup-java@v2
|
||||
with:
|
||||
distribution: 'jdkfile'
|
||||
jdkFile: ${{ runner.temp }}/java_package.tar.gz
|
||||
@@ -90,9 +52,9 @@ jobs:
|
||||
- name: Display Java version
|
||||
run: java -version
|
||||
- name: Run Tests
|
||||
run: mvn --batch-mode --no-transfer-progress test
|
||||
run: mvn test
|
||||
- name: Publish Test Report
|
||||
uses: mikepenz/action-junit-report@e08919a3b1fb83a78393dfb775a9c37f17d8eea6 # v5
|
||||
uses: mikepenz/action-junit-report@v2
|
||||
if: ${{ !cancelled() }}
|
||||
with:
|
||||
report_paths: "**/target/surefire-reports/TEST*.xml"
|
||||
@@ -100,29 +62,29 @@ jobs:
|
||||
|
||||
release:
|
||||
name: Deploy
|
||||
needs: [ test, test-jdk8, test-oracle ]
|
||||
# Temporarily disable deploy
|
||||
needs: [ test, test_oracle ]
|
||||
if: github.ref == 'refs/heads/master' # only perform on latest master
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
|
||||
- uses: actions/checkout@v2
|
||||
- name: Set up Maven Central
|
||||
uses: actions/setup-java@f2beeb24e141e01a676f977032f5a29d81c9e27e # v5.1.0
|
||||
uses: actions/setup-java@v2
|
||||
with: # running setup-java again overwrites the settings.xml
|
||||
distribution: 'temurin'
|
||||
java-version: '8'
|
||||
java-package: jdk
|
||||
server-id: central # Value of the distributionManagement/repository/id field of the pom.xml
|
||||
server-id: ossrh # Value of the distributionManagement/repository/id field of the pom.xml
|
||||
server-username: MAVEN_CENTRAL_USERNAME # env variable for username in deploy (1)
|
||||
server-password: MAVEN_CENTRAL_PASSWORD # env variable for token in deploy (2)
|
||||
gpg-private-key: ${{ secrets.GPG_KEY }} # Value of the GPG private key to import
|
||||
gpg-passphrase: MAVEN_CENTRAL_GPG_PASSPHRASE # env variable for GPG private key passphrase (3)
|
||||
- name: Get Project Version
|
||||
run: |
|
||||
echo "PROJECT_VERSION=$(mvn --batch-mode help:evaluate -Dexpression=project.version -q -DforceStdout)" >> $GITHUB_ENV
|
||||
echo "PROJECT_VERSION=$(mvn help:evaluate -Dexpression=project.version -q -DforceStdout)" >> $GITHUB_ENV
|
||||
- name: Publish to Maven Central
|
||||
if: ${{ endsWith(env.PROJECT_VERSION, '-SNAPSHOT') }}
|
||||
run: mvn --batch-mode --no-transfer-progress deploy -P release -DskipTests -Dgpg.signer=bc
|
||||
run: mvn deploy -P release -DskipTests
|
||||
env:
|
||||
MAVEN_CENTRAL_USERNAME: ${{ secrets.CENTRAL_USERNAME }} # must be the same env variable name as (1)
|
||||
MAVEN_CENTRAL_PASSWORD: ${{ secrets.CENTRAL_PASSWORD }} # must be the same env variable name as (2)
|
||||
MAVEN_GPG_KEY: ${{ secrets.GPG_KEY }} # Value of the GPG private key to import
|
||||
MAVEN_GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }}
|
||||
MAVEN_CENTRAL_USERNAME: ${{ secrets.SONATYPE_USERNAME }} # must be the same env variable name as (1)
|
||||
MAVEN_CENTRAL_PASSWORD: ${{ secrets.SONATYPE_PASSWORD }} # must be the same env variable name as (2)
|
||||
MAVEN_CENTRAL_GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }} # must be the same env variable name as (3)
|
||||
@@ -1,69 +0,0 @@
|
||||
name: "CodeQL"
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ "master" ]
|
||||
pull_request:
|
||||
# The branches below must be a subset of the branches above
|
||||
branches: [ "master" ]
|
||||
schedule:
|
||||
- cron: '26 13 * * 6'
|
||||
|
||||
permissions: {}
|
||||
|
||||
jobs:
|
||||
analyze:
|
||||
name: Analyze
|
||||
# Runner size impacts CodeQL analysis time. To learn more, please see:
|
||||
# - https://gh.io/recommended-hardware-resources-for-running-codeql
|
||||
# - https://gh.io/supported-runners-and-hardware-resources
|
||||
# - https://gh.io/using-larger-runners
|
||||
# Consider using larger runners for possible analysis time improvements.
|
||||
runs-on: ${{ (matrix.language == 'swift' && 'macos-latest') || 'ubuntu-latest' }}
|
||||
timeout-minutes: ${{ (matrix.language == 'swift' && 120) || 360 }}
|
||||
permissions:
|
||||
actions: read
|
||||
contents: read
|
||||
security-events: write
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
language: [ 'java' ]
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@e12f0178983d466f2f6028f5cc7a6d786fd97f4b # v4.31.4
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
# If you wish to specify custom queries, you can do so here or in a config file.
|
||||
# By default, queries listed here will override any specified in a config file.
|
||||
# Prefix the list here with "+" to use these queries and those in the config file.
|
||||
|
||||
# For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
|
||||
# queries: security-extended,security-and-quality
|
||||
|
||||
|
||||
# Autobuild attempts to build any compiled languages (C/C++, C#, Go, Java, or Swift).
|
||||
# If this step fails, then you should remove it and run the build manually (see below)
|
||||
- name: Autobuild
|
||||
uses: github/codeql-action/autobuild@e12f0178983d466f2f6028f5cc7a6d786fd97f4b # v4.31.4
|
||||
|
||||
# ℹ️ Command-line programs to run using the OS shell.
|
||||
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
|
||||
|
||||
# If the Autobuild fails above, remove it and uncomment the following three lines.
|
||||
# modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance.
|
||||
|
||||
# - run: |
|
||||
# echo "Run, Build Application using script"
|
||||
# ./location_of_script_within_repo/buildscript.sh
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@e12f0178983d466f2f6028f5cc7a6d786fd97f4b # v4.31.4
|
||||
with:
|
||||
category: "/language:${{matrix.language}}"
|
||||
@@ -1,62 +0,0 @@
|
||||
# This workflow uses actions that are not certified by GitHub. They are provided
|
||||
# by a third-party and are governed by separate terms of service, privacy
|
||||
# policy, and support documentation.
|
||||
|
||||
name: Scorecard supply-chain security
|
||||
on:
|
||||
# For Branch-Protection check. Only the default branch is supported. See
|
||||
# https://github.com/ossf/scorecard/blob/main/docs/checks.md#branch-protection
|
||||
branch_protection_rule:
|
||||
# To guarantee Maintained check is occasionally updated. See
|
||||
# https://github.com/ossf/scorecard/blob/main/docs/checks.md#maintained
|
||||
schedule:
|
||||
- cron: '38 8 * * 2'
|
||||
push:
|
||||
branches: [ "master" ]
|
||||
|
||||
permissions: read-all # Declare default permissions as read only.
|
||||
|
||||
jobs:
|
||||
analysis:
|
||||
name: Scorecard analysis
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
security-events: write # to upload the results to code-scanning dashboard.
|
||||
id-token: write # to publish results and get a badge
|
||||
|
||||
steps:
|
||||
- name: "Checkout code"
|
||||
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
- name: "Run analysis"
|
||||
uses: ossf/scorecard-action@4eaacf0543bb3f2c246792bd56e8cdeffafb205a # v2.4.3
|
||||
with:
|
||||
results_file: results.sarif
|
||||
results_format: sarif
|
||||
# (Optional) "write" PAT token. Uncomment the `repo_token` line below if:
|
||||
# you want to enable the Branch-Protection check on the repository
|
||||
# To create the PAT, follow the steps in https://github.com/ossf/scorecard-action#authentication-with-fine-grained-pat-optional.
|
||||
# repo_token: ${{ secrets.SCORECARD_TOKEN }}
|
||||
|
||||
# Publish Results:
|
||||
# - Publish results to OpenSSF REST API for easy access by consumers
|
||||
# - Allows the repository to include the Scorecard badge.
|
||||
# - See https://github.com/ossf/scorecard-action#publishing-results.
|
||||
publish_results: true
|
||||
|
||||
# Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF
|
||||
# format to the repository Actions tab.
|
||||
- name: "Upload artifact"
|
||||
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
|
||||
with:
|
||||
name: SARIF file
|
||||
path: results.sarif
|
||||
retention-days: 5
|
||||
|
||||
# Upload the results to GitHub's code scanning dashboard.
|
||||
- name: "Upload to code-scanning"
|
||||
uses: github/codeql-action/upload-sarif@e12f0178983d466f2f6028f5cc7a6d786fd97f4b # v4.31.4
|
||||
with:
|
||||
sarif_file: results.sarif
|
||||
@@ -15,4 +15,3 @@ private
|
||||
profiles.xml
|
||||
Thumbs.db
|
||||
.DS_Store
|
||||
/.metadata/
|
||||
|
||||
@@ -1,20 +1,14 @@
|
||||
[](https://github.com/haraldk/TwelveMonkeys/actions/workflows/ci.yml)
|
||||
[](https://github.com/haraldk/TwelveMonkeys/actions/workflows/codeql.yml)
|
||||
[](https://securityscorecards.dev/viewer/?uri=github.com/haraldk/TwelveMonkeys)
|
||||
[](https://www.bestpractices.dev/projects/7900)
|
||||
|
||||
[](https://search.maven.org/search?q=g:com.twelvemonkeys.imageio)
|
||||
[](https://oss.sonatype.org/content/repositories/snapshots/com/twelvemonkeys/)
|
||||
[](https://stackoverflow.com/questions/tagged/twelvemonkeys)
|
||||
[](https://paypal.me/haraldk76/100)
|
||||
|
||||

|
||||
|
||||
## About
|
||||
|
||||
TwelveMonkeys ImageIO provides extended image file format support for the Java platform, through plugins for the `javax.imageio.*` package.
|
||||
|
||||
The main goal of this project is to provide support for file formats not covered by the JDK.
|
||||
The main goal of this project is to provide support for formats not covered by the JRE itself.
|
||||
Support for these formats is important, to be able to read data found
|
||||
"in the wild", as well as to maintain access to data in legacy formats.
|
||||
As there is lots of legacy data out there, we see the need for open implementations of readers for popular formats.
|
||||
@@ -29,8 +23,7 @@ As there is lots of legacy data out there, we see the need for open implementati
|
||||
| | WMF | MS Windows Metafile | âś” | - | - | Requires [Batik](https://xmlgraphics.apache.org/batik/) |
|
||||
| [BMP](https://github.com/haraldk/TwelveMonkeys/wiki/BMP-Plugin) | **BMP** | MS Windows and IBM OS/2 Device Independent Bitmap | âś” | âś” | [Native](https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/javax/imageio/metadata/doc-files/bmp_metadata.html), [Standard](https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/javax/imageio/metadata/doc-files/standard_metadata.html) |
|
||||
| | CUR | MS Windows Cursor Format | âś” | - | - |
|
||||
| | ICO | MS Windows Icon Format | âś” | âś” | - |
|
||||
| [DDS](https://github.com/haraldk/TwelveMonkeys/wiki/DDS-Plugin) | DDS | MS Direct Draw Surface Format | âś” | - | [Standard](https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/javax/imageio/metadata/doc-files/standard_metadata.html) |
|
||||
| | ICO | MS Windows Icon Format | âś” | âś” | - |
|
||||
| [HDR](https://github.com/haraldk/TwelveMonkeys/wiki/HDR-Plugin) | HDR | Radiance High Dynamic Range RGBE Format | âś” | - | [Standard](https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/javax/imageio/metadata/doc-files/standard_metadata.html) |
|
||||
| [ICNS](https://github.com/haraldk/TwelveMonkeys/wiki/ICNS-Plugin) | ICNS | Apple Icon Image | âś” | âś” | - |
|
||||
| [IFF](https://github.com/haraldk/TwelveMonkeys/wiki/IFF-Plugin) | IFF | Commodore Amiga/Electronic Arts Interchange File Format | âś” | âś” | [Standard](https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/javax/imageio/metadata/doc-files/standard_metadata.html) |
|
||||
@@ -57,7 +50,7 @@ As there is lots of legacy data out there, we see the need for open implementati
|
||||
|
||||
|
||||
**Important note on using Batik:** *Please read [The Apache™ XML Graphics Project - Security](https://xmlgraphics.apache.org/security.html),
|
||||
and make sure you use an updated and secure version.*
|
||||
and make sure you use version 1.14 or later.*
|
||||
|
||||
Note that GIF, PNG and WBMP formats are already supported through the ImageIO API, using the
|
||||
[JDK standard plugins](https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/javax/imageio/package-summary.html).
|
||||
@@ -223,43 +216,6 @@ BufferedImageOp ditherer = new DiffusionDither();
|
||||
BufferedImage output = ditherer.filter(input, null);
|
||||
```
|
||||
|
||||
#### Working with damaged images
|
||||
|
||||
When using the normal patterns for loading images, trying to load a damaged image will result in an `IOException` being thrown.
|
||||
|
||||
```java
|
||||
BufferedImage image = null;
|
||||
try {
|
||||
image = ImageIO.read(file);
|
||||
} catch (IOException exception) {
|
||||
// Handle, log a warning/error etc
|
||||
}
|
||||
```
|
||||
|
||||
In this scenario, if the image is damaged, and `ImageIO.read` throws an exception, `image` is still `null` - it's not possible for a function to both return a value and throw an exception.
|
||||
|
||||
However, in some cases it may be possible to get usable image data from a damaged image. The way to do this is use an `ImageReadParam` to set a `BufferedImage` as a destination.
|
||||
|
||||
```java
|
||||
int width = reader.getWidth(0);
|
||||
int height = reader.getHeight(0);
|
||||
ImageTypeSpecifier imageType = reader.getRawImageType(0);
|
||||
BufferedImage image = imageType.createBufferedImage(width, height);
|
||||
|
||||
ImageReadParam param = reader.getDefaultReadParam();
|
||||
param.setDestination(image);
|
||||
|
||||
try {
|
||||
reader.read(0, param);
|
||||
}
|
||||
catch (IOException e) {
|
||||
// Handle, log a warning/error etc
|
||||
}
|
||||
```
|
||||
|
||||
In theory this should work for all plugins, but the result is very much plugin/implementation specific. With some formats and some forms of damaged file, you may get an image that is mostly useful.
|
||||
However, you should be prepared for the possibility this just gives a blank or empty image.
|
||||
|
||||
## Building
|
||||
|
||||
Download the project (using [Git](https://git-scm.com/downloads)):
|
||||
@@ -316,12 +272,12 @@ To depend on the JPEG and TIFF plugin using Maven, add the following to your POM
|
||||
<dependency>
|
||||
<groupId>com.twelvemonkeys.imageio</groupId>
|
||||
<artifactId>imageio-jpeg</artifactId>
|
||||
<version>3.12.0</version>
|
||||
<version>3.8.1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.twelvemonkeys.imageio</groupId>
|
||||
<artifactId>imageio-tiff</artifactId>
|
||||
<version>3.12.0</version>
|
||||
<version>3.8.1</version>
|
||||
</dependency>
|
||||
|
||||
<!--
|
||||
@@ -331,7 +287,7 @@ To depend on the JPEG and TIFF plugin using Maven, add the following to your POM
|
||||
<dependency>
|
||||
<groupId>com.twelvemonkeys.servlet</groupId>
|
||||
<artifactId>servlet</artifactId>
|
||||
<version>3.12.0</version>
|
||||
<version>3.8.1</version>
|
||||
</dependency>
|
||||
|
||||
<!--
|
||||
@@ -340,7 +296,7 @@ To depend on the JPEG and TIFF plugin using Maven, add the following to your POM
|
||||
<dependency>
|
||||
<groupId>com.twelvemonkeys.servlet</groupId>
|
||||
<artifactId>servlet</artifactId>
|
||||
<version>3.12.0</version>
|
||||
<version>3.8.1</version>
|
||||
<classifier>jakarta</classifier>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
@@ -350,18 +306,18 @@ To depend on the JPEG and TIFF plugin using Maven, add the following to your POM
|
||||
|
||||
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.12.0.jar
|
||||
twelvemonkeys-common-io-3.12.0.jar
|
||||
twelvemonkeys-common-image-3.12.0.jar
|
||||
twelvemonkeys-imageio-core-3.12.0.jar
|
||||
twelvemonkeys-imageio-metadata-3.12.0.jar
|
||||
twelvemonkeys-imageio-jpeg-3.12.0.jar
|
||||
twelvemonkeys-imageio-tiff-3.12.0.jar
|
||||
twelvemonkeys-common-lang-3.8.1.jar
|
||||
twelvemonkeys-common-io-3.8.1.jar
|
||||
twelvemonkeys-common-image-3.8.1.jar
|
||||
twelvemonkeys-imageio-core-3.8.1.jar
|
||||
twelvemonkeys-imageio-metadata-3.8.1.jar
|
||||
twelvemonkeys-imageio-jpeg-3.8.1.jar
|
||||
twelvemonkeys-imageio-tiff-3.8.1.jar
|
||||
|
||||
#### Deploying the plugins in a web app
|
||||
|
||||
Because the `ImageIO` plugin registry (the `IIORegistry`) is "VM global", it does not work well with
|
||||
servlet contexts as-is. This is especially evident if you load plugins from the `WEB-INF/lib` or `classes` folder.
|
||||
Because the `ImageIO` plugin registry (the `IIORegistry`) is "VM global", it doesn't by default work well with
|
||||
servlet contexts. This is especially evident if you load plugins from the `WEB-INF/lib` or `classes` folder.
|
||||
Unless you add `ImageIO.scanForPlugins()` somewhere in your code, the plugins might never be available at all.
|
||||
|
||||
In addition, servlet contexts dynamically loads and unloads classes (using a new class loader per context).
|
||||
@@ -397,16 +353,6 @@ or other ImageIO plugins as well.
|
||||
|
||||
Another safe option, is to place the JAR files in the application server's shared or common lib folder.
|
||||
|
||||
##### Jakarta Servlet Support
|
||||
|
||||
For those transitioning from the old `javax.servlet` to the new `jakarta.servlet` package, there is a separate
|
||||
dependency available. It contains exactly the same servlet classes as mentioned above, but built against the new Jakarta EE
|
||||
packages. The dependency has the same group name and identifier as before, but a `jakarta` *classifier* appended, to
|
||||
distinguish it from the non-Jakarta package.
|
||||
|
||||
See the [Maven dependency example](#maven-dependency-example) for how to enable it with Maven.
|
||||
Gradle or other build tools will have similar options.
|
||||
|
||||
#### Including the plugins in a "fat" JAR
|
||||
|
||||
The recommended way to use the plugins, is just to include the JARs as-is in your project, through a Maven dependency or similar.
|
||||
@@ -432,52 +378,81 @@ Other "fat" JAR bundlers will probably have similar mechanisms to merge entries
|
||||
|
||||
### Links to prebuilt binaries
|
||||
|
||||
##### Latest version (3.12.0)
|
||||
##### Latest version (3.8.1)
|
||||
|
||||
The latest version that will run on Java 7 is 3.9.4. Later versions will require Java 8 or later.
|
||||
Requires Java 7 or later.
|
||||
|
||||
Common dependencies
|
||||
* [common-lang-3.12.0.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/common/common-lang/3.12.0/common-lang-3.12.0.jar)
|
||||
* [common-io-3.12.0.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/common/common-io/3.12.0/common-io-3.12.0.jar)
|
||||
* [common-image-3.12.0.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/common/common-image/3.12.0/common-image-3.12.0.jar)
|
||||
* [common-lang-3.8.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/common/common-lang/3.8.1/common-lang-3.8.1.jar)
|
||||
* [common-io-3.8.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/common/common-io/3.8.1/common-io-3.8.1.jar)
|
||||
* [common-image-3.8.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/common/common-image/3.8.1/common-image-3.8.1.jar)
|
||||
|
||||
ImageIO dependencies
|
||||
* [imageio-core-3.12.0.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-core/3.12.0/imageio-core-3.12.0.jar)
|
||||
* [imageio-metadata-3.12.0.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-metadata/3.12.0/imageio-metadata-3.12.0.jar)
|
||||
* [imageio-core-3.8.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-core/3.8.1/imageio-core-3.8.1.jar)
|
||||
* [imageio-metadata-3.8.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-metadata/3.8.1/imageio-metadata-3.8.1.jar)
|
||||
|
||||
ImageIO plugins
|
||||
* [imageio-bmp-3.12.0.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-bmp/3.12.0/imageio-bmp-3.12.0.jar)
|
||||
* [imageio-dds-3.12.0.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-dds/3.12.0/imageio-dds-3.12.0.jar)
|
||||
* [imageio-hdr-3.12.0.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-hdr/3.12.0/imageio-hdr-3.12.0.jar)
|
||||
* [imageio-icns-3.12.0.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-icns/3.12.0/imageio-icns-3.12.0.jar)
|
||||
* [imageio-iff-3.12.0.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-iff/3.12.0/imageio-iff-3.12.0.jar)
|
||||
* [imageio-jpeg-3.12.0.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-jpeg/3.12.0/imageio-jpeg-3.12.0.jar)
|
||||
* [imageio-pcx-3.12.0.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-pcx/3.12.0/imageio-pcx-3.12.0.jar)
|
||||
* [imageio-pict-3.12.0.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-pict/3.12.0/imageio-pict-3.12.0.jar)
|
||||
* [imageio-pnm-3.12.0.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-pnm/3.12.0/imageio-pnm-3.12.0.jar)
|
||||
* [imageio-psd-3.12.0.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-psd/3.12.0/imageio-psd-3.12.0.jar)
|
||||
* [imageio-sgi-3.12.0.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-sgi/3.12.0/imageio-sgi-3.12.0.jar)
|
||||
* [imageio-tga-3.12.0.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-tga/3.12.0/imageio-tga-3.12.0.jar)
|
||||
* [imageio-thumbsdb-3.12.0.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-thumbsdb/3.12.0/imageio-thumbsdb-3.12.0.jar)
|
||||
* [imageio-tiff-3.12.0.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-tiff/3.12.0/imageio-tiff-3.12.0.jar)
|
||||
* [imageio-webp-3.12.0.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-webp/3.12.0/imageio-webp-3.12.0.jar)
|
||||
* [imageio-xwd-3.12.0.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-xwd/3.12.0/imageio-xwd-3.12.0.jar)
|
||||
* [imageio-bmp-3.8.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-bmp/3.8.1/imageio-bmp-3.8.1.jar)
|
||||
* [imageio-hdr-3.8.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-hdr/3.8.1/imageio-hdr-3.8.1.jar)
|
||||
* [imageio-icns-3.8.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-icns/3.8.1/imageio-icns-3.8.1.jar)
|
||||
* [imageio-iff-3.8.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-iff/3.8.1/imageio-iff-3.8.1.jar)
|
||||
* [imageio-jpeg-3.8.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-jpeg/3.8.1/imageio-jpeg-3.8.1.jar)
|
||||
* [imageio-pcx-3.8.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-pcx/3.8.1/imageio-pcx-3.8.1.jar)
|
||||
* [imageio-pict-3.8.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-pict/3.8.1/imageio-pict-3.8.1.jar)
|
||||
* [imageio-pnm-3.8.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-pnm/3.8.1/imageio-pnm-3.8.1.jar)
|
||||
* [imageio-psd-3.8.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-psd/3.8.1/imageio-psd-3.8.1.jar)
|
||||
* [imageio-sgi-3.8.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-sgi/3.8.1/imageio-sgi-3.8.1.jar)
|
||||
* [imageio-tga-3.8.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-tga/3.8.1/imageio-tga-3.8.1.jar)
|
||||
* [imageio-thumbsdb-3.8.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-thumbsdb/3.8.1/imageio-thumbsdb-3.8.1.jar)
|
||||
* [imageio-tiff-3.8.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-tiff/3.8.1/imageio-tiff-3.8.1.jar)
|
||||
* [imageio-webp-3.8.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-webp/3.8.1/imageio-webp-3.8.1.jar)
|
||||
* [imageio-xwd-3.8.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-xwd/3.8.1/imageio-xwd-3.8.1.jar)
|
||||
|
||||
ImageIO plugins requiring 3rd party libs
|
||||
* [imageio-batik-3.12.0.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-batik/3.12.0/imageio-batik-3.12.0.jar)
|
||||
* [imageio-batik-3.8.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-batik/3.8.1/imageio-batik-3.8.1.jar)
|
||||
|
||||
Photoshop Path support for ImageIO
|
||||
* [imageio-clippath-3.12.0.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-clippath/3.12.0/imageio-clippath-3.12.0.jar)
|
||||
* [imageio-clippath-3.8.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-clippath/3.8.1/imageio-clippath-3.8.1.jar)
|
||||
|
||||
Servlet support
|
||||
* [servlet-3.12.0.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/servlet/servlet/3.12.0/servlet-3.12.0.jar) for legacy Java EE (javax.servlet)
|
||||
* [servlet-3.12.0-jakarta.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/servlet/servlet/3.12.0/servlet-3.12.0-jakrta.jar) for Jakarta EE (jakarta.servlet)
|
||||
* [servlet-3.8.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/servlet/servlet/3.8.1/servlet-3.8.1.jar)
|
||||
|
||||
##### Old version (3.0.x)
|
||||
|
||||
Use this version for projects that requires Java 6 or need the JMagick support. *Does not support Java 8 or later*.
|
||||
|
||||
Common dependencies
|
||||
* [common-lang-3.0.2.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/common/common-lang/3.0.2/common-lang-3.0.2.jar)
|
||||
* [common-io-3.0.2.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/common/common-io/3.0.2/common-io-3.0.2.jar)
|
||||
* [common-image-3.0.2.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/common/common-image/3.0.2/common-image-3.0.2.jar)
|
||||
|
||||
ImageIO dependencies
|
||||
* [imageio-core-3.0.2.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-core/3.0.2/imageio-core-3.0.2.jar)
|
||||
* [imageio-metadata-3.0.2.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-metadata/3.0.2/imageio-metadata-3.0.2.jar)
|
||||
|
||||
ImageIO plugins
|
||||
* [imageio-jpeg-3.0.2.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-jpeg/3.0.2/imageio-jpeg-3.0.2.jar)
|
||||
* [imageio-tiff-3.0.2.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-tiff/3.0.2/imageio-tiff-3.0.2.jar)
|
||||
* [imageio-psd-3.0.2.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-psd/3.0.2/imageio-psd-3.0.2.jar)
|
||||
* [imageio-pict-3.0.2.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-pict/3.0.2/imageio-pict-3.0.2.jar)
|
||||
* [imageio-iff-3.0.2.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-iff/3.0.2/imageio-iff-3.0.2.jar)
|
||||
* [imageio-icns-3.0.2.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-icns/3.0.2/imageio-icns-3.0.2.jar)
|
||||
* [imageio-ico-3.0.2.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-ico/3.0.2/imageio-ico-3.0.2.jar)
|
||||
* [imageio-thumbsdb-3.0.2.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-thumbsdb/3.0.2/imageio-thumbsdb-3.0.2.jar)
|
||||
|
||||
ImageIO plugins requiring 3rd party libs
|
||||
* [imageio-batik-3.0.2.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-batik/3.0.2/imageio-batik-3.0.2.jar)
|
||||
* [imageio-jmagick-3.0.2.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-jmagick/3.0.2/imageio-jmagick-3.0.2.jar)
|
||||
|
||||
Servlet support
|
||||
* [servlet-3.0.2.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/servlet/servlet/3.0.2/servlet-3.0.2.jar)
|
||||
|
||||
|
||||
## License
|
||||
|
||||
This project is provided under the OSI approved [BSD license](https://opensource.org/licenses/BSD-3-Clause):
|
||||
|
||||
Copyright (c) 2008-2022, Harald Kuhr
|
||||
Copyright (c) 2008-2020, Harald Kuhr
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
@@ -509,9 +484,8 @@ This project is provided under the OSI approved [BSD license](https://opensource
|
||||
|
||||
q: How do I use it?
|
||||
|
||||
a: The easiest way is to build your own project using Maven, Gradle or other build tool with dependency management,
|
||||
and just add dependencies to the specific plug-ins you need.
|
||||
If you don't use such a build tool, make sure you have all the necessary JARs in classpath. See the Install section above.
|
||||
a: The easiest way is to build your own project using Maven, and just add dependencies to the specific plug-ins you need.
|
||||
If you don't use Maven, make sure you have all the necessary JARs in classpath. See the Install section above.
|
||||
|
||||
|
||||
q: What changes do I have to make to my code in order to use the plug-ins?
|
||||
@@ -529,41 +503,27 @@ q: How does it work?
|
||||
|
||||
a: The TwelveMonkeys ImageIO project contains plug-ins for ImageIO. ImageIO uses a service lookup mechanism, to discover plug-ins at runtime.
|
||||
|
||||
All you have to do, is to make sure you have the TwelveMonkeys ImageIO JARs in your classpath.
|
||||
All you have have to do, is to make sure you have the TwelveMonkeys JARs in your classpath.
|
||||
|
||||
You can read more about the registry and the lookup mechanism in the [IIORegistry API doc](https://docs.oracle.com/javase/7/docs/api/javax/imageio/spi/IIORegistry.html).
|
||||
|
||||
The fine print: The TwelveMonkeys service providers for JPEG, BMP and TIFF, overrides the onRegistration method, and
|
||||
utilizes the pairwise partial ordering mechanism of the `IIOServiceRegistry` to make sure it is installed before
|
||||
the Sun/Oracle provided `JPEGImageReader`, `BMPImageReader` `TIFFImageReader`, and the Apple provided `TIFFImageReader` on OS X,
|
||||
the Sun/Oracle provided `JPEGImageReader` and `BMPImageReader`, and the Apple provided `TIFFImageReader` on OS X,
|
||||
respectively. Using the pairwise ordering will not remove any functionality form these implementations, but in most
|
||||
cases you'll end up using the TwelveMonkeys plug-ins instead.
|
||||
|
||||
|
||||
q: Why is there no support for common formats like GIF or PNG?
|
||||
|
||||
a: The short answer is simply that the built-in support in ImageIO for these formats are considered good enough as-is.
|
||||
a: The short answer is simply that the built-in support in ImageIO for these formats are good enough as-is.
|
||||
If you are looking for better PNG write performance on Java 7 and 8, see [JDK9 PNG Writer Backport](https://github.com/gredler/jdk9-png-writer-backport).
|
||||
|
||||
|
||||
q: When is the next release? What is the current release schedule?
|
||||
|
||||
a: The goal is to make monthly releases, containing bug fixes and minor new features.
|
||||
And quarterly releases with more "major" features.
|
||||
|
||||
|
||||
q: I love this project! How can I help?
|
||||
|
||||
a: Have a look at the open issues, and see if there are any issues you can help fix, or provide sample file or create test cases for.
|
||||
It is also possible for you or your organization to become a sponsor, through GitHub Sponsors.
|
||||
Providing funding will allow us to spend more time on fixing bugs and implementing new features.
|
||||
|
||||
|
||||
q: What about JAI? Several of the formats are already supported by JAI.
|
||||
|
||||
a: While JAI (and jai-imageio in particular) have support for some of the same formats, JAI has some major issues.
|
||||
The most obvious being:
|
||||
- It's not actively developed. No issue has been fixed for years.
|
||||
- It's not actively developed. No issues has been fixed for years.
|
||||
- To get full format support, you need native libs.
|
||||
Native libs does not exist for several popular platforms/architectures, and further the native libs are not open source.
|
||||
Some environments may also prevent deployment of native libs, which brings us back to square one.
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
# Security Policy
|
||||
|
||||
To report a security issue, please disclose it at [security advisory](https://github.com/haraldk/TwelveMonkeys/security/advisories/new).
|
||||
|
||||
Vulnerabilities will be disclosed in a best effort base.
|
||||
+1
-6
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<groupId>com.twelvemonkeys</groupId>
|
||||
<artifactId>twelvemonkeys</artifactId>
|
||||
<version>3.13.0</version>
|
||||
<version>3.8.3</version>
|
||||
</parent>
|
||||
|
||||
<groupId>com.twelvemonkeys.bom</groupId>
|
||||
@@ -63,11 +63,6 @@
|
||||
<artifactId>imageio-hdr</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.twelvemonkeys.imageio</groupId>
|
||||
<artifactId>imageio-dds</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.twelvemonkeys.imageio</groupId>
|
||||
<artifactId>imageio-icns</artifactId>
|
||||
|
||||
@@ -4,13 +4,13 @@
|
||||
<parent>
|
||||
<groupId>com.twelvemonkeys.common</groupId>
|
||||
<artifactId>common</artifactId>
|
||||
<version>3.13.0</version>
|
||||
<version>3.8.3</version>
|
||||
</parent>
|
||||
<artifactId>common-image</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
<name>TwelveMonkeys :: Common :: Image</name>
|
||||
<description>
|
||||
TwelveMonkeys Common image support classes.
|
||||
The TwelveMonkeys Common Image support
|
||||
</description>
|
||||
|
||||
<properties>
|
||||
@@ -28,14 +28,12 @@
|
||||
<artifactId>common-io</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>jmagick</groupId>
|
||||
<artifactId>jmagick</artifactId>
|
||||
<version>6.6.9</version>
|
||||
<optional>true</optional>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.felix</groupId>
|
||||
<artifactId>maven-bundle-plugin</artifactId>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
|
||||
+87
-97
@@ -79,7 +79,7 @@ public final class BufferedImageFactory {
|
||||
private int scanSize;
|
||||
|
||||
private ColorModel sourceColorModel;
|
||||
private Hashtable<?, ?> sourceProperties; // ImageConsumer API dictates Hashtable
|
||||
private Hashtable sourceProperties; // ImageConsumer API dictates Hashtable
|
||||
|
||||
private Object sourcePixels;
|
||||
|
||||
@@ -91,21 +91,21 @@ public final class BufferedImageFactory {
|
||||
|
||||
/**
|
||||
* Creates a {@code BufferedImageFactory}.
|
||||
* @param source the source image
|
||||
* @throws IllegalArgumentException if {@code source == null}
|
||||
* @param pSource the source image
|
||||
* @throws IllegalArgumentException if {@code pSource == null}
|
||||
*/
|
||||
public BufferedImageFactory(final Image source) {
|
||||
this(source != null ? source.getSource() : null);
|
||||
public BufferedImageFactory(final Image pSource) {
|
||||
this(pSource != null ? pSource.getSource() : null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@code BufferedImageFactory}.
|
||||
* @param source the source image producer
|
||||
* @throws IllegalArgumentException if {@code source == null}
|
||||
* @param pSource the source image producer
|
||||
* @throws IllegalArgumentException if {@code pSource == null}
|
||||
*/
|
||||
public BufferedImageFactory(final ImageProducer source) {
|
||||
Validate.notNull(source, "source");
|
||||
producer = source;
|
||||
public BufferedImageFactory(final ImageProducer pSource) {
|
||||
Validate.notNull(pSource, "source");
|
||||
producer = pSource;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -155,44 +155,44 @@ public final class BufferedImageFactory {
|
||||
/**
|
||||
* Sets the source region (AOI) for the new image.
|
||||
*
|
||||
* @param region the source region
|
||||
* @param pRegion the source region
|
||||
*/
|
||||
public void setSourceRegion(final Rectangle region) {
|
||||
public void setSourceRegion(final Rectangle pRegion) {
|
||||
// Re-fetch everything, if region changed
|
||||
if (x != region.x || y != region.y || width != region.width || height != region.height) {
|
||||
if (x != pRegion.x || y != pRegion.y || width != pRegion.width || height != pRegion.height) {
|
||||
dispose();
|
||||
}
|
||||
|
||||
x = region.x;
|
||||
y = region.y;
|
||||
width = region.width;
|
||||
height = region.height;
|
||||
x = pRegion.x;
|
||||
y = pRegion.y;
|
||||
width = pRegion.width;
|
||||
height = pRegion.height;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the source subsampling for the new image.
|
||||
*
|
||||
* @param xSubsampling horizontal subsampling factor
|
||||
* @param ySubsampling vertical subsampling factor
|
||||
* @param pXSub horizontal subsampling factor
|
||||
* @param pYSub vertical subsampling factor
|
||||
*/
|
||||
public void setSourceSubsampling(int xSubsampling, int ySubsampling) {
|
||||
public void setSourceSubsampling(int pXSub, int pYSub) {
|
||||
// Re-fetch everything, if subsampling changed
|
||||
if (xSub != xSubsampling || ySub != ySubsampling) {
|
||||
if (xSub != pXSub || ySub != pYSub) {
|
||||
dispose();
|
||||
}
|
||||
|
||||
if (xSubsampling > 1) {
|
||||
xSub = xSubsampling;
|
||||
if (pXSub > 1) {
|
||||
xSub = pXSub;
|
||||
}
|
||||
if (ySubsampling > 1) {
|
||||
ySub = ySubsampling;
|
||||
if (pYSub > 1) {
|
||||
ySub = pYSub;
|
||||
}
|
||||
}
|
||||
|
||||
private synchronized void doFetch(final boolean colorModelOnly) throws ImageConversionException {
|
||||
if (!fetching && (!colorModelOnly && buffered == null || buffered == null && sourceColorModel == null)) {
|
||||
private synchronized void doFetch(boolean pColorModelOnly) throws ImageConversionException {
|
||||
if (!fetching && (!pColorModelOnly && buffered == null || buffered == null && sourceColorModel == null)) {
|
||||
// NOTE: Subsampling is only applied if extracting full image
|
||||
if (!colorModelOnly && (xSub > 1 || ySub > 1)) {
|
||||
if (!pColorModelOnly && (xSub > 1 || ySub > 1)) {
|
||||
// If only sampling a region, the region must be scaled too
|
||||
if (width > 0 && height > 0) {
|
||||
width = (width + xSub - 1) / xSub;
|
||||
@@ -207,41 +207,38 @@ public final class BufferedImageFactory {
|
||||
|
||||
// Start fetching
|
||||
fetching = true;
|
||||
readColorModelOnly = colorModelOnly;
|
||||
readColorModelOnly = pColorModelOnly;
|
||||
|
||||
producer.startProduction(consumer); // Note: If single-thread (synchronous), this call will block
|
||||
|
||||
// Wait until the producer wakes us up, by calling imageComplete
|
||||
while (fetching) {
|
||||
try {
|
||||
wait(200L);
|
||||
wait(200l);
|
||||
}
|
||||
catch (InterruptedException e) {
|
||||
throw new ImageConversionException("Image conversion aborted: " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
if (consumerException != null) {
|
||||
throw new ImageConversionException("Image conversion failed: " + consumerException.getMessage(), consumerException);
|
||||
}
|
||||
|
||||
if (colorModelOnly) {
|
||||
createColorModel();
|
||||
}
|
||||
else {
|
||||
createBuffered();
|
||||
}
|
||||
if (consumerException != null) {
|
||||
throw new ImageConversionException("Image conversion failed: " + consumerException.getMessage(), consumerException);
|
||||
}
|
||||
finally {
|
||||
// Clean up, in case any objects are copied/cloned, so we can free resources
|
||||
freeResources();
|
||||
|
||||
if (pColorModelOnly) {
|
||||
createColorModel();
|
||||
}
|
||||
else {
|
||||
createBuffered();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void createColorModel() {
|
||||
colorModel = sourceColorModel;
|
||||
|
||||
// Clean up, in case any objects are copied/cloned, so we can free resources
|
||||
freeResources();
|
||||
}
|
||||
|
||||
private void createBuffered() {
|
||||
@@ -256,9 +253,8 @@ public final class BufferedImageFactory {
|
||||
}
|
||||
}
|
||||
|
||||
if (buffered == null) {
|
||||
throw new ImageConversionException("Could not create BufferedImage");
|
||||
}
|
||||
// Clean up, in case any objects are copied/cloned, so we can free resources
|
||||
freeResources();
|
||||
}
|
||||
|
||||
private void freeResources() {
|
||||
@@ -284,27 +280,27 @@ public final class BufferedImageFactory {
|
||||
/**
|
||||
* Adds a progress listener to this factory.
|
||||
*
|
||||
* @param listener the progress listener
|
||||
* @param pListener the progress listener
|
||||
*/
|
||||
public void addProgressListener(ProgressListener listener) {
|
||||
if (listener == null) {
|
||||
public void addProgressListener(ProgressListener pListener) {
|
||||
if (pListener == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (listeners == null) {
|
||||
listeners = new CopyOnWriteArrayList<>();
|
||||
listeners = new CopyOnWriteArrayList<ProgressListener>();
|
||||
}
|
||||
|
||||
listeners.add(listener);
|
||||
listeners.add(pListener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a progress listener from this factory.
|
||||
*
|
||||
* @param listener the progress listener
|
||||
* @param pListener the progress listener
|
||||
*/
|
||||
public void removeProgressListener(ProgressListener listener) {
|
||||
if (listener == null) {
|
||||
public void removeProgressListener(ProgressListener pListener) {
|
||||
if (pListener == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -312,7 +308,7 @@ public final class BufferedImageFactory {
|
||||
return;
|
||||
}
|
||||
|
||||
listeners.remove(listener);
|
||||
listeners.remove(pListener);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -328,22 +324,21 @@ public final class BufferedImageFactory {
|
||||
* Converts an array of {@code int} pixels to an array of {@code short}
|
||||
* pixels. The conversion is done, by masking out the
|
||||
* <em>higher 16 bits</em> of the {@code int}.
|
||||
* <p>
|
||||
*
|
||||
* For any given {@code int}, the {@code short} value is computed as
|
||||
* follows:
|
||||
* <blockquote>{@code
|
||||
* short value = (short) (intValue & 0x0000ffff);
|
||||
* }</blockquote>
|
||||
* </p>
|
||||
*
|
||||
* @param inputPixels the pixel data to convert
|
||||
* @return an array of {@code short}s, same length as {@code inputPixels}
|
||||
* @param pPixels the pixel data to convert
|
||||
* @return an array of {@code short}s, same lenght as {@code pPixels}
|
||||
*/
|
||||
private static short[] toShortPixels(int[] inputPixels) {
|
||||
short[] pixels = new short[inputPixels.length];
|
||||
private static short[] toShortPixels(int[] pPixels) {
|
||||
short[] pixels = new short[pPixels.length];
|
||||
|
||||
for (int i = 0; i < pixels.length; i++) {
|
||||
pixels[i] = (short) (inputPixels[i] & 0xffff);
|
||||
pixels[i] = (short) (pPixels[i] & 0xffff);
|
||||
}
|
||||
|
||||
return pixels;
|
||||
@@ -356,17 +351,17 @@ public final class BufferedImageFactory {
|
||||
* @see BufferedImageFactory#addProgressListener
|
||||
* @see BufferedImageFactory#removeProgressListener
|
||||
*/
|
||||
public interface ProgressListener extends EventListener {
|
||||
public static interface ProgressListener extends EventListener {
|
||||
|
||||
/**
|
||||
* Reports progress to this listener.
|
||||
* Invoked by the {@code BufferedImageFactory} to report progress in
|
||||
* the image decoding.
|
||||
*
|
||||
* @param factory the factory reporting the progress
|
||||
* @param percentage the percentage of progress
|
||||
* @param pFactory the factory reporting the progress
|
||||
* @param pPercentage the percentage of progress
|
||||
*/
|
||||
void progress(BufferedImageFactory factory, float percentage);
|
||||
void progress(BufferedImageFactory pFactory, float pPercentage);
|
||||
}
|
||||
|
||||
private class Consumer implements ImageConsumer {
|
||||
@@ -451,18 +446,18 @@ public final class BufferedImageFactory {
|
||||
processProgress(pY + pHeight);
|
||||
}
|
||||
|
||||
public void setPixels(int x, int y, int width, int height, ColorModel colorModel, short[] pixels, int offset, int scanSize) {
|
||||
setPixelsImpl(x, y, width, height, colorModel, pixels, offset, scanSize);
|
||||
public void setPixels(int pX, int pY, int pWidth, int pHeight, ColorModel pModel, short[] pPixels, int pOffset, int pScanSize) {
|
||||
setPixelsImpl(pX, pY, pWidth, pHeight, pModel, pPixels, pOffset, pScanSize);
|
||||
}
|
||||
|
||||
private void setColorModelOnce(final ColorModel colorModel) {
|
||||
private void setColorModelOnce(final ColorModel pModel) {
|
||||
// NOTE: There seems to be a "bug" in AreaAveragingScaleFilter, as it
|
||||
// first passes the original color model through in setColorModel, then
|
||||
// later replaces it with the default RGB in the first setPixels call
|
||||
// (this is probably allowed according to the spec, but it's a waste of time and space).
|
||||
if (sourceColorModel != colorModel) {
|
||||
if (sourcePixels == null) {
|
||||
sourceColorModel = colorModel;
|
||||
if (sourceColorModel != pModel) {
|
||||
if (/*sourceColorModel == null ||*/ sourcePixels == null) {
|
||||
sourceColorModel = pModel;
|
||||
}
|
||||
else {
|
||||
throw new IllegalStateException("Change of ColorModel after pixel delivery not supported");
|
||||
@@ -475,16 +470,17 @@ public final class BufferedImageFactory {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void imageComplete(int status) {
|
||||
public void imageComplete(int pStatus) {
|
||||
fetching = false;
|
||||
|
||||
if (producer != null) {
|
||||
producer.removeConsumer(this);
|
||||
}
|
||||
|
||||
if (status == ImageConsumer.IMAGEERROR) {
|
||||
consumerException = new ImageConversionException("ImageConsumer.IMAGEERROR");
|
||||
switch (pStatus) {
|
||||
case ImageConsumer.IMAGEERROR:
|
||||
consumerException = new ImageConversionException("ImageConsumer.IMAGEERROR");
|
||||
break;
|
||||
}
|
||||
|
||||
synchronized (BufferedImageFactory.this) {
|
||||
@@ -492,18 +488,16 @@ public final class BufferedImageFactory {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setColorModel(ColorModel colorModel) {
|
||||
setColorModelOnce(colorModel);
|
||||
public void setColorModel(ColorModel pModel) {
|
||||
setColorModelOnce(pModel);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDimensions(int w, int h) {
|
||||
public void setDimensions(int pWidth, int pHeight) {
|
||||
if (width < 0) {
|
||||
width = w - x;
|
||||
width = pWidth - x;
|
||||
}
|
||||
if (height < 0) {
|
||||
height = h - y;
|
||||
height = pHeight - y;
|
||||
}
|
||||
|
||||
// Hmm.. Special case, but is it a good idea?
|
||||
@@ -512,31 +506,27 @@ public final class BufferedImageFactory {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setHints(int hintFlags) {
|
||||
public void setHints(int pHintflags) {
|
||||
// ignore
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPixels(int x, int y, int width, int height, ColorModel colorModel, byte[] pixels, int offset, int scanSize) {
|
||||
setPixelsImpl(x, y, width, height, colorModel, pixels, offset, scanSize);
|
||||
public void setPixels(int pX, int pY, int pWidth, int pHeight, ColorModel pModel, byte[] pPixels, int pOffset, int pScanSize) {
|
||||
setPixelsImpl(pX, pY, pWidth, pHeight, pModel, pPixels, pOffset, pScanSize);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPixels(int x, int y, int width, int height, ColorModel colorModel, int[] pixels, int offset, int scanSize) {
|
||||
if (colorModel.getTransferType() == DataBuffer.TYPE_USHORT) {
|
||||
public void setPixels(int pX, int pY, int pWeigth, int pHeight, ColorModel pModel, int[] pPixels, int pOffset, int pScanSize) {
|
||||
if (pModel.getTransferType() == DataBuffer.TYPE_USHORT) {
|
||||
// NOTE: Workaround for limitation in ImageConsumer API
|
||||
// Convert int[] to short[], to be compatible with the ColorModel
|
||||
setPixelsImpl(x, y, width, height, colorModel, toShortPixels(pixels), offset, scanSize);
|
||||
setPixelsImpl(pX, pY, pWeigth, pHeight, pModel, toShortPixels(pPixels), pOffset, pScanSize);
|
||||
}
|
||||
else {
|
||||
setPixelsImpl(x, y, width, height, colorModel, pixels, offset, scanSize);
|
||||
setPixelsImpl(pX, pY, pWeigth, pHeight, pModel, pPixels, pOffset, pScanSize);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setProperties(Hashtable properties) {
|
||||
sourceProperties = properties;
|
||||
public void setProperties(Hashtable pProperties) {
|
||||
sourceProperties = pProperties;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -844,7 +844,7 @@ public final class ImageUtil {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int i = 0; i < mapSize1; i++) {
|
||||
for (int i = 0; i > mapSize1; i++) {
|
||||
if (icm1.getRGB(i) != icm2.getRGB(i)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Regular → Executable
+18
-12
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2024, Harald Kuhr
|
||||
* Copyright (c) 2008, Harald Kuhr
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -28,22 +28,28 @@
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package com.twelvemonkeys.imageio.plugins.dds;
|
||||
|
||||
import com.twelvemonkeys.imageio.spi.ReaderWriterProviderInfo;
|
||||
import com.twelvemonkeys.imageio.spi.ReaderWriterProviderInfoTest;
|
||||
package com.twelvemonkeys.image;
|
||||
|
||||
/**
|
||||
* DDSProviderInfoTest.
|
||||
* Magick
|
||||
*
|
||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||
* @author last modified by $Author: harald.kuhr$
|
||||
* @version $Id: DDSProviderInfoTest.java,v 1.0 02/06/16 harald.kuhr Exp$
|
||||
* @author last modified by $Author: haku $
|
||||
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-core/src/main/java/com/twelvemonkeys/image/Magick.java#1 $
|
||||
*/
|
||||
public class DDSProviderInfoTest extends ReaderWriterProviderInfoTest {
|
||||
final class Magick {
|
||||
static final boolean DEBUG = useDebug();
|
||||
|
||||
@Override
|
||||
protected ReaderWriterProviderInfo createProviderInfo() {
|
||||
return new DDSProviderInfo();
|
||||
private static boolean useDebug() {
|
||||
try {
|
||||
return "TRUE".equalsIgnoreCase(System.getProperty("com.twelvemonkeys.image.magick.debug"));
|
||||
}
|
||||
catch (Throwable t) {
|
||||
// Most probably in case of a SecurityManager
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Magick() {}
|
||||
}
|
||||
+187
@@ -0,0 +1,187 @@
|
||||
/*
|
||||
* Copyright (c) 2008, 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:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* * 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.
|
||||
*
|
||||
* * 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.
|
||||
*/
|
||||
|
||||
|
||||
package com.twelvemonkeys.image;
|
||||
|
||||
import com.twelvemonkeys.lang.SystemUtil;
|
||||
import magick.MagickImage;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
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>
|
||||
* 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>
|
||||
*
|
||||
* @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 $
|
||||
*/
|
||||
final class MagickAccelerator {
|
||||
|
||||
private static final boolean DEBUG = Magick.DEBUG;
|
||||
private static final boolean USE_MAGICK = useMagick();
|
||||
|
||||
private static final int RESAMPLE_OP = 0;
|
||||
|
||||
private static Class[] nativeOp = new Class[1];
|
||||
|
||||
static {
|
||||
try {
|
||||
nativeOp[RESAMPLE_OP] = Class.forName("com.twelvemonkeys.image.ResampleOp");
|
||||
}
|
||||
catch (ClassNotFoundException e) {
|
||||
System.err.println("Could not find class: " + e);
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean useMagick() {
|
||||
try {
|
||||
boolean available = SystemUtil.isClassAvailable("magick.MagickImage");
|
||||
|
||||
if (DEBUG && !available) {
|
||||
System.err.print("ImageMagick bindings not available.");
|
||||
}
|
||||
|
||||
boolean useMagick =
|
||||
available && !"FALSE".equalsIgnoreCase(System.getProperty("com.twelvemonkeys.image.accel"));
|
||||
|
||||
if (DEBUG) {
|
||||
System.err.println(
|
||||
useMagick
|
||||
? "Will use ImageMagick bindings to accelerate image resampling operations."
|
||||
: "Will not use ImageMagick to accelerate image resampling operations."
|
||||
);
|
||||
}
|
||||
|
||||
return useMagick;
|
||||
}
|
||||
catch (Throwable t) {
|
||||
// Most probably in case of a SecurityManager
|
||||
System.err.println("Could not enable ImageMagick bindings: " + t);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static int getNativeOpIndex(Class pOpClass) {
|
||||
for (int i = 0; i < nativeOp.length; i++) {
|
||||
if (pOpClass == nativeOp[i]) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
public static BufferedImage filter(BufferedImageOp pOperation, BufferedImage pInput, BufferedImage pOutput) {
|
||||
if (!USE_MAGICK) {
|
||||
return null;
|
||||
}
|
||||
|
||||
BufferedImage result = null;
|
||||
switch (getNativeOpIndex(pOperation.getClass())) {
|
||||
case RESAMPLE_OP:
|
||||
ResampleOp resample = (ResampleOp) pOperation;
|
||||
result = resampleMagick(pInput, resample.width, resample.height, resample.filterType);
|
||||
|
||||
// NOTE: If output parameter is non-null, we have to return that
|
||||
// image, instead of result
|
||||
if (pOutput != null) {
|
||||
//pOutput.setData(result.getRaster()); // Fast, but less compatible
|
||||
// NOTE: For some reason, this is sometimes super-slow...?
|
||||
ImageUtil.drawOnto(pOutput, result);
|
||||
result = pOutput;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
// Simply fall through, allowing acceleration to be added later
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static BufferedImage resampleMagick(BufferedImage pSrc, int pWidth, int pHeight, int pFilterType) {
|
||||
// Convert to Magick, scale and convert back
|
||||
MagickImage image = null;
|
||||
MagickImage scaled = null;
|
||||
try {
|
||||
image = MagickUtil.toMagick(pSrc);
|
||||
|
||||
long start = 0;
|
||||
if (DEBUG) {
|
||||
start = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
// NOTE: setFilter affects zoomImage, NOT scaleImage
|
||||
image.setFilter(pFilterType);
|
||||
scaled = image.zoomImage(pWidth, pHeight);
|
||||
//scaled = image.scaleImage(pWidth, pHeight); // AREA_AVERAGING
|
||||
|
||||
if (DEBUG) {
|
||||
long time = System.currentTimeMillis() - start;
|
||||
System.out.println("Filtered: " + time + " ms");
|
||||
}
|
||||
|
||||
return MagickUtil.toBuffered(scaled);
|
||||
}
|
||||
//catch (MagickException e) {
|
||||
catch (Exception e) {
|
||||
// NOTE: Stupid workaround: If MagickException is caught, a
|
||||
// NoClassDefFoundError is thrown, when MagickException class is
|
||||
// unavailable...
|
||||
if (e instanceof RuntimeException) {
|
||||
throw (RuntimeException) e;
|
||||
}
|
||||
|
||||
throw new ImageConversionException(e.getMessage(), e);
|
||||
}
|
||||
finally {
|
||||
// NOTE: ImageMagick might be unstable after a while, if image data
|
||||
// is not deallocated. The GC/finalize method handles this, but in
|
||||
// special circumstances, it's not triggered often enough.
|
||||
if (image != null) {
|
||||
image.destroyImages();
|
||||
}
|
||||
if (scaled != null) {
|
||||
scaled.destroyImages();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,621 @@
|
||||
/*
|
||||
* Copyright (c) 2008, 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:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* * 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.
|
||||
*
|
||||
* * 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.
|
||||
*/
|
||||
|
||||
package com.twelvemonkeys.image;
|
||||
|
||||
import magick.ImageType;
|
||||
import magick.MagickException;
|
||||
import magick.MagickImage;
|
||||
import magick.PixelPacket;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.color.ColorSpace;
|
||||
import java.awt.color.ICC_ColorSpace;
|
||||
import java.awt.color.ICC_Profile;
|
||||
import java.awt.image.*;
|
||||
|
||||
/**
|
||||
* Utility for converting JMagick {@code MagickImage}s to standard Java
|
||||
* {@code BufferedImage}s and back.
|
||||
* <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 $
|
||||
*/
|
||||
public final class MagickUtil {
|
||||
// IMPORTANT NOTE: Disaster happens if any of these constants are used outside this class
|
||||
// because you then have a dependency on MagickException (this is due to Java class loading
|
||||
// and initialization magic).
|
||||
// Do not use outside this class. If the constants need to be shared, move to Magick or ImageUtil.
|
||||
|
||||
/** Color Model usesd for bilevel (B/W) */
|
||||
private static final IndexColorModel CM_MONOCHROME = MonochromeColorModel.getInstance();
|
||||
|
||||
/** Color Model usesd for raw ABGR */
|
||||
private static final ColorModel CM_COLOR_ALPHA =
|
||||
new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_sRGB), new int[] {8, 8, 8, 8},
|
||||
true, true, Transparency.TRANSLUCENT, DataBuffer.TYPE_BYTE);
|
||||
|
||||
/** Color Model usesd for raw BGR */
|
||||
private static final ColorModel CM_COLOR_OPAQUE =
|
||||
new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_sRGB), new int[] {8, 8, 8},
|
||||
false, false, Transparency.OPAQUE, DataBuffer.TYPE_BYTE);
|
||||
|
||||
/** Color Model usesd for raw RGB */
|
||||
//private static final ColorModel CM_COLOR_RGB = new DirectColorModel(24, 0x00ff0000, 0x0000ff00, 0x000000ff, 0x0);
|
||||
|
||||
/** Color Model usesd for raw GRAY + ALPHA */
|
||||
private static final ColorModel CM_GRAY_ALPHA =
|
||||
new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_GRAY),
|
||||
true, true, Transparency.TRANSLUCENT, DataBuffer.TYPE_BYTE);
|
||||
|
||||
/** Color Model usesd for raw GRAY */
|
||||
private static final ColorModel CM_GRAY_OPAQUE =
|
||||
new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_GRAY),
|
||||
false, false, Transparency.OPAQUE, DataBuffer.TYPE_BYTE);
|
||||
|
||||
/** Band offsets for raw ABGR */
|
||||
private static final int[] BAND_OFF_TRANS = new int[] {3, 2, 1, 0};
|
||||
|
||||
/** Band offsets for raw BGR */
|
||||
private static final int[] BAND_OFF_OPAQUE = new int[] {2, 1, 0};
|
||||
|
||||
/** The point at {@code 0, 0} */
|
||||
private static final Point LOCATION_UPPER_LEFT = new Point(0, 0);
|
||||
|
||||
private static final boolean DEBUG = Magick.DEBUG;
|
||||
|
||||
// Only static members and methods
|
||||
private MagickUtil() {}
|
||||
|
||||
/**
|
||||
* Converts a {@code MagickImage} to a {@code BufferedImage}.
|
||||
* <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>
|
||||
*
|
||||
* <dt>{@code ImageType.GrayscaleType}</dt>
|
||||
* <dd>{@code BufferedImage} of type {@code TYPE_BYTE_GRAY}</dd>
|
||||
* <dt>{@code ImageType.GrayscaleMatteType}</dt>
|
||||
* <dd>{@code BufferedImage} of type {@code TYPE_USHORT_GRAY}</dd>
|
||||
*
|
||||
* <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>
|
||||
* <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>
|
||||
*
|
||||
* <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}
|
||||
*
|
||||
* @throws IllegalArgumentException if {@code pImage} is {@code null}
|
||||
* or if the {@code ImageType} is not one mentioned above.
|
||||
* @throws MagickException if an exception occurs during conversion
|
||||
*
|
||||
* @see BufferedImage
|
||||
*/
|
||||
public static BufferedImage toBuffered(MagickImage pImage) throws MagickException {
|
||||
if (pImage == null) {
|
||||
throw new IllegalArgumentException("image == null");
|
||||
}
|
||||
|
||||
long start = 0L;
|
||||
if (DEBUG) {
|
||||
start = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
BufferedImage image = null;
|
||||
try {
|
||||
switch (pImage.getImageType()) {
|
||||
case ImageType.BilevelType:
|
||||
image = bilevelToBuffered(pImage);
|
||||
break;
|
||||
case ImageType.GrayscaleType:
|
||||
image = grayToBuffered(pImage, false);
|
||||
break;
|
||||
case ImageType.GrayscaleMatteType:
|
||||
image = grayToBuffered(pImage, true);
|
||||
break;
|
||||
case ImageType.PaletteType:
|
||||
image = paletteToBuffered(pImage, false);
|
||||
break;
|
||||
case ImageType.PaletteMatteType:
|
||||
image = paletteToBuffered(pImage, true);
|
||||
break;
|
||||
case ImageType.TrueColorType:
|
||||
image = rgbToBuffered(pImage, false);
|
||||
break;
|
||||
case ImageType.TrueColorMatteType:
|
||||
image = rgbToBuffered(pImage, true);
|
||||
break;
|
||||
case ImageType.ColorSeparationType:
|
||||
image = cmykToBuffered(pImage, false);
|
||||
break;
|
||||
case ImageType.ColorSeparationMatteType:
|
||||
image = cmykToBuffered(pImage, true);
|
||||
break;
|
||||
case ImageType.OptimizeType:
|
||||
default:
|
||||
throw new IllegalArgumentException("Unknown JMagick image type: " + pImage.getImageType());
|
||||
}
|
||||
|
||||
}
|
||||
finally {
|
||||
if (DEBUG) {
|
||||
long time = System.currentTimeMillis() - start;
|
||||
System.out.println("Converted JMagick image type: " + pImage.getImageType() + " to BufferedImage: " + image);
|
||||
System.out.println("Conversion to BufferedImage: " + time + " ms");
|
||||
}
|
||||
}
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a {@code BufferedImage} to a {@code MagickImage}.
|
||||
* <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()</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()</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}
|
||||
*
|
||||
* @throws IllegalArgumentException if {@code pImage} is {@code null}
|
||||
* or if the {@code ColorModel} is not one mentioned above.
|
||||
* @throws MagickException if an exception occurs during conversion
|
||||
*
|
||||
* @see BufferedImage
|
||||
*/
|
||||
public static MagickImage toMagick(BufferedImage pImage) throws MagickException {
|
||||
if (pImage == null) {
|
||||
throw new IllegalArgumentException("image == null");
|
||||
}
|
||||
|
||||
long start = 0L;
|
||||
if (DEBUG) {
|
||||
start = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
try {
|
||||
ColorModel cm = pImage.getColorModel();
|
||||
if (cm instanceof IndexColorModel) {
|
||||
// Handles both BilevelType, PaletteType and PaletteMatteType
|
||||
return indexedToMagick(pImage, (IndexColorModel) cm, cm.hasAlpha());
|
||||
}
|
||||
|
||||
switch (cm.getColorSpace().getType()) {
|
||||
case ColorSpace.TYPE_GRAY:
|
||||
// Handles GrayType and GrayMatteType
|
||||
return grayToMagick(pImage, cm.hasAlpha());
|
||||
case ColorSpace.TYPE_RGB:
|
||||
// Handles TrueColorType and TrueColorMatteType
|
||||
return rgbToMagic(pImage, cm.hasAlpha());
|
||||
case ColorSpace.TYPE_CMY:
|
||||
case ColorSpace.TYPE_CMYK:
|
||||
case ColorSpace.TYPE_HLS:
|
||||
case ColorSpace.TYPE_HSV:
|
||||
// Other types not supported yet
|
||||
default:
|
||||
throw new IllegalArgumentException("Unknown buffered image type: " + pImage);
|
||||
}
|
||||
}
|
||||
finally {
|
||||
if (DEBUG) {
|
||||
long time = System.currentTimeMillis() - start;
|
||||
System.out.println("Conversion to MagickImage: " + time + " ms");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static MagickImage rgbToMagic(BufferedImage pImage, boolean pAlpha) throws MagickException {
|
||||
MagickImage image = new MagickImage();
|
||||
|
||||
BufferedImage buffered = ImageUtil.toBuffered(pImage, pAlpha ? BufferedImage.TYPE_4BYTE_ABGR : BufferedImage.TYPE_3BYTE_BGR);
|
||||
|
||||
// Need to get data of sub raster, not the full data array, this is
|
||||
// just a convenient way
|
||||
Raster raster;
|
||||
if (buffered.getRaster().getParent() != null) {
|
||||
raster = buffered.getData(new Rectangle(buffered.getWidth(), buffered.getHeight()));
|
||||
}
|
||||
else {
|
||||
raster = buffered.getRaster();
|
||||
}
|
||||
|
||||
image.constituteImage(buffered.getWidth(), buffered.getHeight(), pAlpha ? "ABGR" : "BGR",
|
||||
((DataBufferByte) raster.getDataBuffer()).getData());
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
private static MagickImage grayToMagick(BufferedImage pImage, boolean pAlpha) throws MagickException {
|
||||
MagickImage image = new MagickImage();
|
||||
|
||||
// TODO: Make a fix for TYPE_USHORT_GRAY
|
||||
// The code below does not seem to work (JMagick issues?)...
|
||||
/*
|
||||
if (pImage.getType() == BufferedImage.TYPE_USHORT_GRAY) {
|
||||
short[] data = ((DataBufferUShort) pImage.getRaster().getDataBuffer()).getData();
|
||||
int[] intData = new int[data.length];
|
||||
for (int i = 0; i < data.length; i++) {
|
||||
intData[i] = (data[i] & 0xffff) * 0xffff;
|
||||
}
|
||||
image.constituteImage(pImage.getWidth(), pImage.getHeight(), "I", intData);
|
||||
|
||||
System.out.println("storageClass: " + image.getStorageClass());
|
||||
System.out.println("depth: " + image.getDepth());
|
||||
System.out.println("imageType: " + image.getImageType());
|
||||
}
|
||||
else {
|
||||
*/
|
||||
BufferedImage buffered = ImageUtil.toBuffered(pImage, pAlpha ? BufferedImage.TYPE_4BYTE_ABGR : BufferedImage.TYPE_BYTE_GRAY);
|
||||
|
||||
// Need to get data of sub raster, not the full data array, this is
|
||||
// just a convenient way
|
||||
Raster raster;
|
||||
if (buffered.getRaster().getParent() != null) {
|
||||
raster = buffered.getData(new Rectangle(buffered.getWidth(), buffered.getHeight()));
|
||||
}
|
||||
else {
|
||||
raster = buffered.getRaster();
|
||||
}
|
||||
|
||||
image.constituteImage(buffered.getWidth(), buffered.getHeight(), pAlpha ? "ABGR" : "I", ((DataBufferByte) raster.getDataBuffer()).getData());
|
||||
//}
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
private static MagickImage indexedToMagick(BufferedImage pImage, IndexColorModel pColorModel, boolean pAlpha) throws MagickException {
|
||||
MagickImage image = rgbToMagic(pImage, pAlpha);
|
||||
|
||||
int mapSize = pColorModel.getMapSize();
|
||||
image.setNumberColors(mapSize);
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
/*
|
||||
public static MagickImage toMagick(BufferedImage pImage) throws MagickException {
|
||||
if (pImage == null) {
|
||||
throw new IllegalArgumentException("image == null");
|
||||
}
|
||||
|
||||
final int width = pImage.getWidth();
|
||||
final int height = pImage.getHeight();
|
||||
|
||||
// int ARGB -> byte RGBA conversion
|
||||
// NOTE: This is ImageMagick Q16 compatible raw RGBA format with 16 bits/sample...
|
||||
// For a Q8 build, we could probably go with half the space...
|
||||
// NOTE: This is close to insanity, as it wastes extreme ammounts of memory
|
||||
final int[] argb = new int[width];
|
||||
final byte[] raw16 = new byte[width * height * 8];
|
||||
for (int y = 0; y < height; y++) {
|
||||
// Fetch one line of ARGB data
|
||||
pImage.getRGB(0, y, width, 1, argb, 0, width);
|
||||
|
||||
for (int x = 0; x < width; x++) {
|
||||
int pixel = (x + (y * width)) * 8;
|
||||
raw16[pixel ] = (byte) ((argb[x] >> 16) & 0xff); // R
|
||||
raw16[pixel + 2] = (byte) ((argb[x] >> 8) & 0xff); // G
|
||||
raw16[pixel + 4] = (byte) ((argb[x] ) & 0xff); // B
|
||||
raw16[pixel + 6] = (byte) ((argb[x] >> 24) & 0xff); // A
|
||||
}
|
||||
}
|
||||
|
||||
// Create magick image
|
||||
ImageInfo info = new ImageInfo();
|
||||
info.setMagick("RGBA"); // Raw RGBA samples
|
||||
info.setSize(width + "x" + height); // String?!?
|
||||
|
||||
MagickImage image = new MagickImage(info);
|
||||
image.setImageAttribute("depth", "8");
|
||||
|
||||
// Set pixel data in 16 bit raw RGBA format
|
||||
image.blobToImage(info, raw16);
|
||||
|
||||
return image;
|
||||
}
|
||||
*/
|
||||
|
||||
/**
|
||||
* Converts a bi-level {@code MagickImage} to a {@code BufferedImage}, of
|
||||
* type {@code TYPE_BYTE_BINARY}.
|
||||
*
|
||||
* @param pImage the original {@code MagickImage}
|
||||
* @return a new {@code BufferedImage}
|
||||
*
|
||||
* @throws MagickException if an exception occurs during conversion
|
||||
*
|
||||
* @see BufferedImage
|
||||
*/
|
||||
private static BufferedImage bilevelToBuffered(MagickImage pImage) throws MagickException {
|
||||
// As there is no way to get the binary representation of the image,
|
||||
// convert to gray, and the create a binary image from it
|
||||
BufferedImage temp = grayToBuffered(pImage, false);
|
||||
|
||||
BufferedImage image = new BufferedImage(temp.getWidth(), temp.getHeight(), BufferedImage.TYPE_BYTE_BINARY, CM_MONOCHROME);
|
||||
|
||||
ImageUtil.drawOnto(image, temp);
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a gray {@code MagickImage} to a {@code BufferedImage}, of
|
||||
* type {@code TYPE_USHORT_GRAY} or {@code TYPE_BYTE_GRAY}.
|
||||
*
|
||||
* @param pImage the original {@code MagickImage}
|
||||
* @param pAlpha keep alpha channel
|
||||
* @return a new {@code BufferedImage}
|
||||
*
|
||||
* @throws MagickException if an exception occurs during conversion
|
||||
*
|
||||
* @see BufferedImage
|
||||
*/
|
||||
private static BufferedImage grayToBuffered(MagickImage pImage, boolean pAlpha) throws MagickException {
|
||||
Dimension size = pImage.getDimension();
|
||||
int length = size.width * size.height;
|
||||
int bands = pAlpha ? 2 : 1;
|
||||
byte[] pixels = new byte[length * bands];
|
||||
|
||||
// TODO: Make a fix for 16 bit TYPE_USHORT_GRAY?!
|
||||
// Note: The ordering AI or I corresponds to BufferedImage
|
||||
// TYPE_CUSTOM and TYPE_BYTE_GRAY respectively
|
||||
pImage.dispatchImage(0, 0, size.width, size.height, pAlpha ? "AI" : "I", pixels);
|
||||
|
||||
// Init databuffer with array, to avoid allocation of empty array
|
||||
DataBuffer buffer = new DataBufferByte(pixels, pixels.length);
|
||||
|
||||
int[] bandOffsets = pAlpha ? new int[] {1, 0} : new int[] {0};
|
||||
|
||||
WritableRaster raster =
|
||||
Raster.createInterleavedRaster(buffer, size.width, size.height,
|
||||
size.width * bands, bands, bandOffsets, LOCATION_UPPER_LEFT);
|
||||
|
||||
return new BufferedImage(pAlpha ? CM_GRAY_ALPHA : CM_GRAY_OPAQUE, raster, pAlpha, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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}.
|
||||
*
|
||||
* @param pImage the original {@code MagickImage}
|
||||
* @param pAlpha keep alpha channel
|
||||
* @return a new {@code BufferedImage}
|
||||
*
|
||||
* @throws MagickException if an exception occurs during conversion
|
||||
*
|
||||
* @see BufferedImage
|
||||
*/
|
||||
private static BufferedImage paletteToBuffered(MagickImage pImage, boolean pAlpha) throws MagickException {
|
||||
// Create indexcolormodel for the image
|
||||
IndexColorModel cm;
|
||||
|
||||
try {
|
||||
cm = createIndexColorModel(pImage.getColormap(), pAlpha);
|
||||
}
|
||||
catch (MagickException e) {
|
||||
// NOTE: Some MagickImages incorrecly (?) reports to be paletteType,
|
||||
// but does not have a colormap, this is a workaround.
|
||||
return rgbToBuffered(pImage, pAlpha);
|
||||
}
|
||||
|
||||
// As there is no way to get the indexes of an indexed image, convert to
|
||||
// RGB, and the create an indexed image from it
|
||||
BufferedImage temp = rgbToBuffered(pImage, pAlpha);
|
||||
|
||||
BufferedImage image;
|
||||
if (cm.getMapSize() <= 16) {
|
||||
image = new BufferedImage(temp.getWidth(), temp.getHeight(), BufferedImage.TYPE_BYTE_BINARY, cm);
|
||||
}
|
||||
else {
|
||||
image = new BufferedImage(temp.getWidth(), temp.getHeight(), BufferedImage.TYPE_BYTE_INDEXED, cm);
|
||||
}
|
||||
|
||||
// Create transparent background for images containing alpha
|
||||
if (pAlpha) {
|
||||
Graphics2D g = image.createGraphics();
|
||||
try {
|
||||
g.setComposite(AlphaComposite.Clear);
|
||||
g.fillRect(0, 0, temp.getWidth(), temp.getHeight());
|
||||
}
|
||||
finally {
|
||||
g.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE: This is (surprisingly) much faster than using g2d.drawImage()..
|
||||
// (Tests shows 20-30ms, vs. 600-700ms on the same image)
|
||||
BufferedImageOp op = new CopyDither(cm);
|
||||
op.filter(temp, image);
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an {@code IndexColorModel} from an array of
|
||||
* {@code PixelPacket}s.
|
||||
*
|
||||
* @param pColormap the original colormap as a {@code PixelPacket} array
|
||||
* @param pAlpha keep alpha channel
|
||||
*
|
||||
* @return a new {@code IndexColorModel}
|
||||
*/
|
||||
public static IndexColorModel createIndexColorModel(PixelPacket[] pColormap, boolean pAlpha) {
|
||||
int[] colors = new int[pColormap.length];
|
||||
|
||||
// TODO: Verify if this is correct for alpha...?
|
||||
int trans = pAlpha ? colors.length - 1 : -1;
|
||||
|
||||
//for (int i = 0; i < pColormap.length; i++) {
|
||||
for (int i = pColormap.length - 1; i != 0; i--) {
|
||||
PixelPacket color = pColormap[i];
|
||||
if (pAlpha) {
|
||||
colors[i] = (0xff - (color.getOpacity() & 0xff)) << 24 |
|
||||
(color.getRed() & 0xff) << 16 |
|
||||
(color.getGreen() & 0xff) << 8 |
|
||||
(color.getBlue() & 0xff);
|
||||
}
|
||||
else {
|
||||
colors[i] = (color.getRed() & 0xff) << 16 |
|
||||
(color.getGreen() & 0xff) << 8 |
|
||||
(color.getBlue() & 0xff);
|
||||
}
|
||||
}
|
||||
|
||||
return new InverseColorMapIndexColorModel(8, colors.length, colors, 0, pAlpha, trans, DataBuffer.TYPE_BYTE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts an (A)RGB {@code MagickImage} to a {@code BufferedImage}, of
|
||||
* type {@code TYPE_4BYTE_ABGR} or {@code TYPE_3BYTE_BGR}.
|
||||
*
|
||||
* @param pImage the original {@code MagickImage}
|
||||
* @param pAlpha keep alpha channel
|
||||
* @return a new {@code BufferedImage}
|
||||
*
|
||||
* @throws MagickException if an exception occurs during conversion
|
||||
*
|
||||
* @see BufferedImage
|
||||
*/
|
||||
private static BufferedImage rgbToBuffered(MagickImage pImage, boolean pAlpha) throws MagickException {
|
||||
Dimension size = pImage.getDimension();
|
||||
int length = size.width * size.height;
|
||||
int bands = pAlpha ? 4 : 3;
|
||||
byte[] pixels = new byte[length * bands];
|
||||
|
||||
// TODO: If we do multiple dispatches (one per line, typically), we could provide listener
|
||||
// feedback. But it's currently a lot slower than fetching all the pixels in one go.
|
||||
|
||||
// Note: The ordering ABGR or BGR corresponds to BufferedImage
|
||||
// TYPE_4BYTE_ABGR and TYPE_3BYTE_BGR respectively
|
||||
pImage.dispatchImage(0, 0, size.width, size.height, pAlpha ? "ABGR" : "BGR", pixels);
|
||||
|
||||
// Init databuffer with array, to avoid allocation of empty array
|
||||
DataBuffer buffer = new DataBufferByte(pixels, pixels.length);
|
||||
|
||||
int[] bandOffsets = pAlpha ? BAND_OFF_TRANS : BAND_OFF_OPAQUE;
|
||||
|
||||
WritableRaster raster =
|
||||
Raster.createInterleavedRaster(buffer, size.width, size.height,
|
||||
size.width * bands, bands, bandOffsets, LOCATION_UPPER_LEFT);
|
||||
|
||||
return new BufferedImage(pAlpha ? CM_COLOR_ALPHA : CM_COLOR_OPAQUE, raster, pAlpha, null);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Converts an {@code MagickImage} to a {@code BufferedImage} which holds an CMYK ICC profile
|
||||
*
|
||||
* @param pImage the original {@code MagickImage}
|
||||
* @param pAlpha keep alpha channel
|
||||
* @return a new {@code BufferedImage}
|
||||
*
|
||||
* @throws MagickException if an exception occurs during conversion
|
||||
*
|
||||
* @see BufferedImage
|
||||
*/
|
||||
private static BufferedImage cmykToBuffered(MagickImage pImage, boolean pAlpha) throws MagickException {
|
||||
Dimension size = pImage.getDimension();
|
||||
int length = size.width * size.height;
|
||||
|
||||
// Retreive the ICC profile
|
||||
ICC_Profile profile = ICC_Profile.getInstance(pImage.getColorProfile().getInfo());
|
||||
ColorSpace cs = new ICC_ColorSpace(profile);
|
||||
|
||||
int bands = cs.getNumComponents() + (pAlpha ? 1 : 0);
|
||||
|
||||
int[] bits = new int[bands];
|
||||
for (int i = 0; i < bands; i++) {
|
||||
bits[i] = 8;
|
||||
}
|
||||
|
||||
ColorModel cm = pAlpha ?
|
||||
new ComponentColorModel(cs, bits, true, true, Transparency.TRANSLUCENT, DataBuffer.TYPE_BYTE) :
|
||||
new ComponentColorModel(cs, bits, false, false, Transparency.OPAQUE, DataBuffer.TYPE_BYTE);
|
||||
|
||||
byte[] pixels = new byte[length * bands];
|
||||
|
||||
// TODO: If we do multiple dispatches (one per line, typically), we could provide listener
|
||||
// feedback. But it's currently a lot slower than fetching all the pixels in one go.
|
||||
// TODO: handle more generic cases if profile is not CMYK
|
||||
// TODO: Test "ACMYK"
|
||||
pImage.dispatchImage(0, 0, size.width, size.height, pAlpha ? "ACMYK" : "CMYK", pixels);
|
||||
|
||||
// Init databuffer with array, to avoid allocation of empty array
|
||||
DataBuffer buffer = new DataBufferByte(pixels, pixels.length);
|
||||
|
||||
// TODO: build array from bands variable, here it just works for CMYK
|
||||
// The values has not been tested with an alpha picture actually...
|
||||
int[] bandOffsets = pAlpha ? new int[] {0, 1, 2, 3, 4} : new int[] {0, 1, 2, 3};
|
||||
|
||||
WritableRaster raster =
|
||||
Raster.createInterleavedRaster(buffer, size.width, size.height,
|
||||
size.width * bands, bands, bandOffsets, LOCATION_UPPER_LEFT);
|
||||
|
||||
return new BufferedImage(cm, raster, pAlpha, null);
|
||||
|
||||
}
|
||||
}
|
||||
@@ -55,7 +55,9 @@
|
||||
package com.twelvemonkeys.image;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.geom.*;
|
||||
import java.awt.geom.AffineTransform;
|
||||
import java.awt.geom.Point2D;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
import java.awt.image.*;
|
||||
|
||||
/**
|
||||
@@ -101,6 +103,15 @@ import java.awt.image.*;
|
||||
* BufferedImage scaled = new ResampleOp(w, h).filter(temp, null);
|
||||
* </pre></blockquote>
|
||||
* <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.
|
||||
* Native code may be disabled globally, by setting the system property
|
||||
* {@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>
|
||||
* 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
|
||||
@@ -128,6 +139,9 @@ import java.awt.image.*;
|
||||
// TODO: Consider using AffineTransformOp for more operations!?
|
||||
public class ResampleOp implements BufferedImageOp/* TODO: RasterOp */ {
|
||||
|
||||
// NOTE: These MUST correspond to ImageMagick filter types, for the
|
||||
// MagickAccelerator to work consistently (see magick.FilterType).
|
||||
|
||||
/**
|
||||
* Undefined interpolation, filter method will use default filter.
|
||||
*/
|
||||
@@ -281,10 +295,11 @@ public class ResampleOp implements BufferedImageOp/* TODO: RasterOp */ {
|
||||
new Value(KEY_RESAMPLE_INTERPOLATION, "Blackman-Sinc", FILTER_BLACKMAN_SINC);
|
||||
|
||||
// Member variables
|
||||
private final int width;
|
||||
private final int height;
|
||||
// Package access, to allow access from MagickAccelerator
|
||||
int width;
|
||||
int height;
|
||||
|
||||
private final int filterType;
|
||||
int filterType;
|
||||
|
||||
/**
|
||||
* RendereingHints.Key implementation, works only with Value values.
|
||||
@@ -532,6 +547,16 @@ public class ResampleOp implements BufferedImageOp/* TODO: RasterOp */ {
|
||||
// Fall through
|
||||
}
|
||||
|
||||
// Try to use native ImageMagick code
|
||||
BufferedImage result = MagickAccelerator.filter(this, input, output);
|
||||
if (result != null) {
|
||||
return result;
|
||||
}
|
||||
|
||||
// Otherwise, continue in pure Java mode
|
||||
|
||||
// TODO: What if output != null and wrong size? Create new? Render on only a part? Document?
|
||||
|
||||
// If filter type != POINT or BOX and input has IndexColorModel, convert
|
||||
// to true color, with alpha reflecting that of the original color model.
|
||||
BufferedImage temp;
|
||||
@@ -546,7 +571,7 @@ public class ResampleOp implements BufferedImageOp/* TODO: RasterOp */ {
|
||||
|
||||
// Create or convert output to a suitable image
|
||||
// TODO: OPTIMIZE: Don't really need to convert all types to same as input
|
||||
BufferedImage result = output != null && temp.getType() != BufferedImage.TYPE_CUSTOM ? /*output*/ ImageUtil.toBuffered(output, temp.getType()) : createCompatibleDestImage(temp, null);
|
||||
result = output != null && temp.getType() != BufferedImage.TYPE_CUSTOM ? /*output*/ ImageUtil.toBuffered(output, temp.getType()) : createCompatibleDestImage(temp, null);
|
||||
|
||||
resample(temp, result, filter);
|
||||
|
||||
@@ -1255,12 +1280,12 @@ public class ResampleOp implements BufferedImageOp/* TODO: RasterOp */ {
|
||||
/*
|
||||
* image rescaling routine
|
||||
*/
|
||||
static class Contributor {
|
||||
class Contributor {
|
||||
int pixel;
|
||||
double weight;
|
||||
}
|
||||
|
||||
static class ContributorList {
|
||||
class ContributorList {
|
||||
int n;/* number of contributors (may be < p.length) */
|
||||
Contributor[] p;/* pointer to list of contributions */
|
||||
}
|
||||
|
||||
+26
-24
@@ -31,7 +31,9 @@
|
||||
package com.twelvemonkeys.image;
|
||||
|
||||
import static java.lang.Math.min;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
import java.awt.color.ColorSpace;
|
||||
import java.awt.geom.AffineTransform;
|
||||
@@ -47,7 +49,7 @@ import java.util.List;
|
||||
|
||||
import javax.imageio.ImageTypeSpecifier;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* AffineTransformOpTest.
|
||||
@@ -144,12 +146,12 @@ public class AffineTransformOpTest {
|
||||
BufferedImage jreResult = jreOp.filter(image, null);
|
||||
BufferedImage tmResult = tmOp.filter(image, null);
|
||||
|
||||
assertNotNull(tmResult, "No result!");
|
||||
assertEquals(jreResult.getType(), tmResult.getType(), "Bad type");
|
||||
assertEquals(jreResult.getColorModel(), tmResult.getColorModel(), "Incorrect color model");
|
||||
assertNotNull("No result!", tmResult);
|
||||
assertEquals("Bad type", jreResult.getType(), tmResult.getType());
|
||||
assertEquals("Incorrect color model", jreResult.getColorModel(), tmResult.getColorModel());
|
||||
|
||||
assertEquals(jreResult.getWidth(), tmResult.getWidth(), "Incorrect width");
|
||||
assertEquals(jreResult.getHeight(), tmResult.getHeight(), "Incorrect height");
|
||||
assertEquals("Incorrect width", jreResult.getWidth(), tmResult.getWidth());
|
||||
assertEquals("Incorrect height", jreResult.getHeight(), tmResult.getHeight());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -162,7 +164,7 @@ public class AffineTransformOpTest {
|
||||
BufferedImage image = spec.createBufferedImage(width, height);
|
||||
|
||||
BufferedImage tmResult = tmOp.filter(image, null);
|
||||
assertNotNull(tmResult, "No result!");
|
||||
assertNotNull("No result!", tmResult);
|
||||
|
||||
BufferedImage jreResult = null;
|
||||
|
||||
@@ -174,18 +176,18 @@ public class AffineTransformOpTest {
|
||||
}
|
||||
|
||||
if (jreResult != null) {
|
||||
assertEquals(jreResult.getType(), tmResult.getType(), "Bad type");
|
||||
assertEquals(jreResult.getColorModel(), tmResult.getColorModel(), "Incorrect color model");
|
||||
assertEquals("Bad type", jreResult.getType(), tmResult.getType());
|
||||
assertEquals("Incorrect color model", jreResult.getColorModel(), tmResult.getColorModel());
|
||||
|
||||
assertEquals(jreResult.getWidth(), tmResult.getWidth(), "Incorrect width");
|
||||
assertEquals(jreResult.getHeight(), tmResult.getHeight(), "Incorrect height");
|
||||
assertEquals("Incorrect width", jreResult.getWidth(), tmResult.getWidth());
|
||||
assertEquals("Incorrect height", jreResult.getHeight(), tmResult.getHeight());
|
||||
}
|
||||
else {
|
||||
assertEquals(spec.getBufferedImageType(), tmResult.getType(), "Bad type");
|
||||
assertEquals(spec.getColorModel(), tmResult.getColorModel(), "Incorrect color model");
|
||||
assertEquals("Bad type", spec.getBufferedImageType(), tmResult.getType());
|
||||
assertEquals("Incorrect color model", spec.getColorModel(), tmResult.getColorModel());
|
||||
|
||||
assertEquals(height, tmResult.getWidth(), "Incorrect width");
|
||||
assertEquals(width, tmResult.getHeight(), "Incorrect height");
|
||||
assertEquals("Incorrect width", height, tmResult.getWidth());
|
||||
assertEquals("Incorrect height", width, tmResult.getHeight());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -234,12 +236,12 @@ public class AffineTransformOpTest {
|
||||
}
|
||||
|
||||
if (jreResult != null) {
|
||||
assertEquals(jreResult.getWidth(), tmResult.getWidth(), "Incorrect width");
|
||||
assertEquals(jreResult.getHeight(), tmResult.getHeight(), "Incorrect height");
|
||||
assertEquals("Incorrect width", jreResult.getWidth(), tmResult.getWidth());
|
||||
assertEquals("Incorrect height", jreResult.getHeight(), tmResult.getHeight());
|
||||
}
|
||||
else {
|
||||
assertEquals(height, tmResult.getWidth(), "Incorrect width");
|
||||
assertEquals(width, tmResult.getHeight(), "Incorrect height");
|
||||
assertEquals("Incorrect width", height, tmResult.getWidth());
|
||||
assertEquals("Incorrect height", width, tmResult.getHeight());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -275,12 +277,12 @@ public class AffineTransformOpTest {
|
||||
}
|
||||
|
||||
if (jreResult != null) {
|
||||
assertEquals(jreResult.getWidth(), tmResult.getWidth(), "Incorrect width");
|
||||
assertEquals(jreResult.getHeight(), tmResult.getHeight(), "Incorrect height");
|
||||
assertEquals("Incorrect width", jreResult.getWidth(), tmResult.getWidth());
|
||||
assertEquals("Incorrect height", jreResult.getHeight(), tmResult.getHeight());
|
||||
}
|
||||
else {
|
||||
assertEquals(height, tmResult.getWidth(), "Incorrect width");
|
||||
assertEquals(width, tmResult.getHeight(), "Incorrect height");
|
||||
assertEquals("Incorrect width", height, tmResult.getWidth());
|
||||
assertEquals("Incorrect height", width, tmResult.getHeight());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+42
-48
@@ -30,16 +30,18 @@
|
||||
|
||||
package com.twelvemonkeys.image;
|
||||
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.color.*;
|
||||
import java.awt.image.*;
|
||||
import java.awt.color.ColorSpace;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.awt.image.ColorModel;
|
||||
import java.awt.image.ImageProducer;
|
||||
import java.awt.image.IndexColorModel;
|
||||
import java.net.URL;
|
||||
import java.time.Duration;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* BufferedImageFactoryTestCase
|
||||
@@ -49,58 +51,50 @@ import static org.junit.jupiter.api.Assertions.*;
|
||||
* @version $Id: BufferedImageFactoryTestCase.java,v 1.0 May 7, 2010 12:40:08 PM haraldk Exp$
|
||||
*/
|
||||
public class BufferedImageFactoryTest {
|
||||
@Test
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testCreateNullImage() {
|
||||
assertThrows(IllegalArgumentException.class, () -> {
|
||||
new BufferedImageFactory((Image) null);
|
||||
});
|
||||
new BufferedImageFactory((Image) null);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testCreateNullProducer() {
|
||||
assertThrows(IllegalArgumentException.class, () -> {
|
||||
new BufferedImageFactory((ImageProducer) null);
|
||||
});
|
||||
new BufferedImageFactory((ImageProducer) null);
|
||||
}
|
||||
|
||||
// NPE in Toolkit, ok
|
||||
@Test
|
||||
@Test(expected = RuntimeException.class)
|
||||
public void testGetBufferedImageErrorSourceByteArray() {
|
||||
assertThrows(RuntimeException.class, () -> {
|
||||
Image source = Toolkit.getDefaultToolkit().createImage((byte[]) null);
|
||||
new BufferedImageFactory(source);
|
||||
});
|
||||
Image source = Toolkit.getDefaultToolkit().createImage((byte[]) null);
|
||||
|
||||
new BufferedImageFactory(source);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testGetBufferedImageErrorSourceImageProducer() {
|
||||
Image source = Toolkit.getDefaultToolkit().createImage((ImageProducer) null);
|
||||
assertThrows(IllegalArgumentException.class, () -> {
|
||||
new BufferedImageFactory(source);
|
||||
});
|
||||
|
||||
new BufferedImageFactory(source);
|
||||
}
|
||||
|
||||
// TODO: This is a quite serious bug, however, the bug is in the Toolkit, allowing such images in the first place...
|
||||
// In any case, there's not much we can do, except until someone is bored and kills the app/thread... :-P
|
||||
@Disabled("Bug in Toolkit")
|
||||
@Test
|
||||
@Ignore("Bug in Toolkit")
|
||||
@Test(timeout = 1000, expected = ImageConversionException.class)
|
||||
public void testGetBufferedImageErrorSourceString() {
|
||||
assertTimeoutPreemptively(Duration.ofMillis(1000), () -> {
|
||||
Image source = Toolkit.getDefaultToolkit().createImage((String) null);
|
||||
BufferedImageFactory factory = new BufferedImageFactory(source);
|
||||
assertThrows(ImageConversionException.class, factory::getBufferedImage);
|
||||
});
|
||||
Image source = Toolkit.getDefaultToolkit().createImage((String) null);
|
||||
|
||||
BufferedImageFactory factory = new BufferedImageFactory(source);
|
||||
factory.getBufferedImage();
|
||||
}
|
||||
|
||||
// This is a little random, and it would be nicer if we could throw an IllegalArgumentException on create.
|
||||
// Unfortunately, the API doesn't allow this...
|
||||
@Test
|
||||
@Test(timeout = 1000, expected = ImageConversionException.class)
|
||||
public void testGetBufferedImageErrorSourceURL() {
|
||||
assertTimeoutPreemptively(Duration.ofMillis(1000), () -> {
|
||||
Image source = Toolkit.getDefaultToolkit().createImage((String) null);
|
||||
BufferedImageFactory factory = new BufferedImageFactory(source);
|
||||
assertThrows(ImageConversionException.class, factory::getBufferedImage);
|
||||
});
|
||||
Image source = Toolkit.getDefaultToolkit().createImage(getClass().getResource("/META-INF/MANIFEST.MF"));
|
||||
|
||||
BufferedImageFactory factory = new BufferedImageFactory(source);
|
||||
factory.getBufferedImage();
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -172,7 +166,7 @@ public class BufferedImageFactoryTest {
|
||||
|
||||
assertEquals(3, colorModel.getNumColorComponents());
|
||||
assertEquals(ColorSpace.getInstance(ColorSpace.CS_sRGB), colorModel.getColorSpace());
|
||||
assertInstanceOf(IndexColorModel.class, colorModel);
|
||||
assertTrue(colorModel instanceof IndexColorModel);
|
||||
|
||||
assertTrue(colorModel.hasAlpha());
|
||||
assertEquals(4, colorModel.getNumComponents());
|
||||
@@ -203,7 +197,7 @@ public class BufferedImageFactoryTest {
|
||||
|
||||
for (int y = 0; y < image.getHeight(); y++) {
|
||||
for (int x = 0; x < image.getWidth(); x++) {
|
||||
assertEquals(original.getRGB(x * 2, y * 2), image.getRGB(x, y), "RGB[" + x + ", " + y + "]");
|
||||
assertEquals("RGB[" + x + ", " + y + "]", original.getRGB(x * 2, y * 2), image.getRGB(x, y));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -226,7 +220,7 @@ public class BufferedImageFactoryTest {
|
||||
|
||||
for (int y = 0; y < image.getHeight(); y++) {
|
||||
for (int x = 0; x < image.getWidth(); x++) {
|
||||
assertEquals(original.getRGB(40 + x, 40 + y), image.getRGB(x, y), "RGB[" + x + ", " + y + "]");
|
||||
assertEquals("RGB[" + x + ", " + y + "]", original.getRGB(40 + x, 40 + y), image.getRGB(x, y));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -250,7 +244,7 @@ public class BufferedImageFactoryTest {
|
||||
|
||||
for (int y = 0; y < image.getHeight(); y++) {
|
||||
for (int x = 0; x < image.getWidth(); x++) {
|
||||
assertEquals(original.getRGB(40 + x * 2, 40 + y * 2), image.getRGB(x, y), "RGB[" + x + ", " + y + "]");
|
||||
assertEquals("RGB[" + x + ", " + y + "]", original.getRGB(40 + x * 2, 40 + y * 2), image.getRGB(x, y));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -266,9 +260,9 @@ public class BufferedImageFactoryTest {
|
||||
|
||||
// Listener should abort ASAP
|
||||
factory.addProgressListener(new BufferedImageFactory.ProgressListener() {
|
||||
public void progress(BufferedImageFactory factory, float percentage) {
|
||||
if (percentage > 5) {
|
||||
factory.abort();
|
||||
public void progress(BufferedImageFactory pFactory, float pPercentage) {
|
||||
if (pPercentage > 5) {
|
||||
pFactory.abort();
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -349,7 +343,7 @@ public class BufferedImageFactoryTest {
|
||||
VerifyingListener listener = new VerifyingListener(factory);
|
||||
factory.addProgressListener(listener);
|
||||
factory.removeProgressListener(new BufferedImageFactory.ProgressListener() {
|
||||
public void progress(BufferedImageFactory factory, float percentage) {
|
||||
public void progress(BufferedImageFactory pFactory, float pPercentage) {
|
||||
}
|
||||
});
|
||||
factory.getBufferedImage();
|
||||
@@ -386,11 +380,11 @@ public class BufferedImageFactoryTest {
|
||||
this.factory = factory;
|
||||
}
|
||||
|
||||
public void progress(BufferedImageFactory factory, float percentage) {
|
||||
assertEquals(this.factory, factory);
|
||||
assertTrue(percentage >= progress && percentage <= 100f);
|
||||
public void progress(BufferedImageFactory pFactory, float pPercentage) {
|
||||
assertEquals(factory, pFactory);
|
||||
assertTrue(pPercentage >= progress && pPercentage <= 100f);
|
||||
|
||||
progress = percentage;
|
||||
progress = pPercentage;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
|
||||
package com.twelvemonkeys.image;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.Test;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import java.awt.*;
|
||||
@@ -39,7 +39,7 @@ import java.awt.image.IndexColorModel;
|
||||
import java.awt.image.RenderedImage;
|
||||
import java.io.InputStream;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
public class ImageUtilTest {
|
||||
|
||||
@@ -116,8 +116,8 @@ public class ImageUtilTest {
|
||||
public void testImageIsNotBufferedImage() {
|
||||
// Should not be a buffered image
|
||||
assertFalse(
|
||||
scaled instanceof BufferedImage,
|
||||
"FOR SOME IMPLEMENTATIONS THIS MIGHT FAIL!\nIn that case, testToBufferedImage() will fail too."
|
||||
"FOR SOME IMPLEMENTATIONS THIS MIGHT FAIL!\nIn that case, testToBufferedImage() will fail too.",
|
||||
scaled instanceof BufferedImage
|
||||
);
|
||||
}
|
||||
|
||||
@@ -247,7 +247,7 @@ public class ImageUtilTest {
|
||||
if (original != notContrasted) { // Don't care to test if images are same
|
||||
for (int y = 0; y < original.getHeight(); y++) {
|
||||
for (int x = 0; x < original.getWidth(); x++) {
|
||||
assertEquals(original.getRGB(x, y), notContrasted.getRGB(x, y), "0 constrast should not change image");
|
||||
assertEquals("0 constrast should not change image", original.getRGB(x, y), notContrasted.getRGB(x, y));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -275,24 +275,24 @@ public class ImageUtilTest {
|
||||
|
||||
// RED
|
||||
if (oR < 127) {
|
||||
assertTrue(oR >= cR && cR >= dR, "Contrast should be decreased or same");
|
||||
assertTrue("Contrast should be decreased or same", oR >= cR && cR >= dR);
|
||||
}
|
||||
else {
|
||||
assertTrue(oR <= cR && cR <= dR, "Contrast should be increased or same");
|
||||
assertTrue("Contrast should be increased or same", oR <= cR && cR <= dR);
|
||||
}
|
||||
// GREEN
|
||||
if (oG < 127) {
|
||||
assertTrue(oG >= cG && cG >= dG, "Contrast should be decreased or same");
|
||||
assertTrue("Contrast should be decreased or same", oG >= cG && cG >= dG);
|
||||
}
|
||||
else {
|
||||
assertTrue(oG <= cG && cG <= dG, "Contrast should be increased or same");
|
||||
assertTrue("Contrast should be increased or same", oG <= cG && cG <= dG);
|
||||
}
|
||||
// BLUE
|
||||
if (oB < 127) {
|
||||
assertTrue(oB >= cB && cB >= dB, "Contrast should be decreased or same");
|
||||
assertTrue("Contrast should be decreased or same", oB >= cB && cB >= dB);
|
||||
}
|
||||
else {
|
||||
assertTrue(oB <= cB && cB <= dB, "Contrast should be increased or same");
|
||||
assertTrue("Contrast should be increased or same", oB <= cB && cB <= dB);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -304,9 +304,9 @@ public class ImageUtilTest {
|
||||
int r = rgb >> 16 & 0xFF;
|
||||
int g = rgb >> 8 & 0xFF;
|
||||
int b = rgb & 0xFF;
|
||||
assertTrue(r == 0 || r == 255, "Max contrast should only produce primary colors");
|
||||
assertTrue(g == 0 || g == 255, "Max contrast should only produce primary colors");
|
||||
assertTrue(b == 0 || b == 255, "Max contrast should only produce primary colors");
|
||||
assertTrue("Max contrast should only produce primary colors", r == 0 || r == 255);
|
||||
assertTrue("Max contrast should only produce primary colors", g == 0 || g == 255);
|
||||
assertTrue("Max contrast should only produce primary colors", b == 0 || b == 255);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -327,24 +327,24 @@ public class ImageUtilTest {
|
||||
|
||||
// RED
|
||||
if (oR >= 127) {
|
||||
assertTrue(oR >= cR, "Contrast should be decreased or same");
|
||||
assertTrue("Contrast should be decreased or same", oR >= cR);
|
||||
}
|
||||
else {
|
||||
assertTrue(oR <= cR, "Contrast should be increased or same");
|
||||
assertTrue("Contrast should be increased or same", oR <= cR);
|
||||
}
|
||||
// GREEN
|
||||
if (oG >= 127) {
|
||||
assertTrue(oG >= cG, "Contrast should be decreased or same");
|
||||
assertTrue("Contrast should be decreased or same", oG >= cG);
|
||||
}
|
||||
else {
|
||||
assertTrue(oG <= cG, "Contrast should be increased or same");
|
||||
assertTrue("Contrast should be increased or same", oG <= cG);
|
||||
}
|
||||
// BLUE
|
||||
if (oB >= 127) {
|
||||
assertTrue(oB >= cB, "Contrast should be decreased or same");
|
||||
assertTrue("Contrast should be decreased or same", oB >= cB);
|
||||
}
|
||||
else {
|
||||
assertTrue(oB <= cB, "Contrast should be increased or same");
|
||||
assertTrue("Contrast should be increased or same", oB <= cB);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -357,7 +357,7 @@ public class ImageUtilTest {
|
||||
int r = rgb >> 16 & 0xFF;
|
||||
int g = rgb >> 8 & 0xFF;
|
||||
int b = rgb & 0xFF;
|
||||
assertTrue(r == 127 && g == 127 && b == 127, "Minimum contrast should be all gray");
|
||||
assertTrue("Minimum contrast should be all gray", r == 127 && g == 127 && b == 127);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -400,7 +400,7 @@ public class ImageUtilTest {
|
||||
if (original != notSharpened) { // Don't care to test if images are same
|
||||
for (int y = 0; y < original.getHeight(); y++) {
|
||||
for (int x = 0; x < original.getWidth(); x++) {
|
||||
assertEquals(original.getRGB(x, y), notSharpened.getRGB(x, y), "0 sharpen should not change image");
|
||||
assertEquals("0 sharpen should not change image", original.getRGB(x, y), notSharpened.getRGB(x, y));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -446,13 +446,13 @@ public class ImageUtilTest {
|
||||
}
|
||||
|
||||
// assertEquals("Difference should not change", diffOriginal, diffSharpened);
|
||||
assertTrue(absDiffOriginal < absDiffSharpened, "Abs difference should increase");
|
||||
assertTrue("Abs difference should increase", absDiffOriginal < absDiffSharpened);
|
||||
// assertEquals("Difference should not change", diffOriginal, diffDefault);
|
||||
assertTrue(absDiffOriginal < absDiffDefault, "Abs difference should increase");
|
||||
assertTrue("Abs difference should increase", absDiffOriginal < absDiffDefault);
|
||||
// assertEquals("Difference should not change", diffOriginal, diffMore);
|
||||
assertTrue(absDiffOriginal < absDiffMore, "Abs difference should increase");
|
||||
assertTrue("Abs difference should increase", absDiffOriginal < absDiffMore);
|
||||
// assertEquals("Difference should not change", diffSharpened, diffMore);
|
||||
assertTrue(absDiffSharpened < absDiffMore, "Abs difference should increase");
|
||||
assertTrue("Abs difference should increase", absDiffSharpened < absDiffMore);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -466,7 +466,7 @@ public class ImageUtilTest {
|
||||
if (original != notBlurred) { // Don't care to test if images are same
|
||||
for (int y = 0; y < original.getHeight(); y++) {
|
||||
for (int x = 0; x < original.getWidth(); x++) {
|
||||
assertEquals(original.getRGB(x, y), notBlurred.getRGB(x, y), "0 blur should not change image");
|
||||
assertEquals("0 blur should not change image", original.getRGB(x, y), notBlurred.getRGB(x, y));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -512,13 +512,13 @@ public class ImageUtilTest {
|
||||
}
|
||||
|
||||
// assertEquals("Difference should not change", diffOriginal, diffBlurred);
|
||||
assertTrue(absDiffOriginal > absDiffBlurred, String.format("Abs difference should decrease: %s <= %s", absDiffOriginal, absDiffBlurred));
|
||||
assertTrue(String.format("Abs difference should decrease: %s <= %s", absDiffOriginal, absDiffBlurred), absDiffOriginal > absDiffBlurred);
|
||||
// assertEquals("Difference should not change", diffOriginal, diffDefault);
|
||||
assertTrue(absDiffOriginal > absDiffDefault, "Abs difference should decrease");
|
||||
assertTrue("Abs difference should decrease", absDiffOriginal > absDiffDefault);
|
||||
// assertEquals("Difference should not change", diffOriginal, diffMore);
|
||||
assertTrue(absDiffOriginal > absDiffMore, "Abs difference should decrease");
|
||||
assertTrue("Abs difference should decrease", absDiffOriginal > absDiffMore);
|
||||
// assertEquals("Difference should not change", diffBlurred, diffMore);
|
||||
assertTrue(absDiffBlurred > absDiffMore, "Abs difference should decrease");
|
||||
assertTrue("Abs difference should decrease", absDiffBlurred > absDiffMore);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -528,7 +528,7 @@ public class ImageUtilTest {
|
||||
assertNotNull(sunflower);
|
||||
|
||||
BufferedImage image = ImageUtil.createIndexed(sunflower);
|
||||
assertNotNull(image, "Image was null");
|
||||
assertInstanceOf(IndexColorModel.class, image.getColorModel());
|
||||
assertNotNull("Image was null", image);
|
||||
assertTrue(image.getColorModel() instanceof IndexColorModel);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,8 +30,8 @@
|
||||
|
||||
package com.twelvemonkeys.image;
|
||||
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.image.BufferedImage;
|
||||
@@ -40,7 +40,7 @@ import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* ResampleOpTestCase
|
||||
@@ -124,7 +124,7 @@ public class ResampleOpTest {
|
||||
}
|
||||
}
|
||||
|
||||
assertEquals(Collections.EMPTY_LIST, exceptions, "Filter threw exceptions: ");
|
||||
assertEquals("Filter threw exceptions: ", Collections.EMPTY_LIST, exceptions);
|
||||
}
|
||||
|
||||
// 1x1
|
||||
@@ -358,7 +358,7 @@ public class ResampleOpTest {
|
||||
}
|
||||
}
|
||||
|
||||
@Disabled("Not for general unit testing")
|
||||
@Ignore("Not for general unit testing")
|
||||
@Test
|
||||
public void testTime() {
|
||||
int iterations = 1000;
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
TODO:
|
||||
Remove compile-time dependency on JMagick:
|
||||
- Extract interface for MagickAccelerator
|
||||
- Move implementation to separate module
|
||||
- Instantiate impl via reflection
|
||||
DONE:
|
||||
@@ -4,13 +4,13 @@
|
||||
<parent>
|
||||
<groupId>com.twelvemonkeys.common</groupId>
|
||||
<artifactId>common</artifactId>
|
||||
<version>3.13.0</version>
|
||||
<version>3.8.3</version>
|
||||
</parent>
|
||||
<artifactId>common-io</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
<name>TwelveMonkeys :: Common :: IO</name>
|
||||
<description>
|
||||
TwelveMonkeys Common I/O support classes.
|
||||
The TwelveMonkeys Common IO support
|
||||
</description>
|
||||
|
||||
<properties>
|
||||
@@ -31,12 +31,4 @@
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.felix</groupId>
|
||||
<artifactId>maven-bundle-plugin</artifactId>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
|
||||
@@ -56,8 +56,8 @@ public class CompoundReader extends Reader {
|
||||
|
||||
private int currentReader;
|
||||
private int markedReader;
|
||||
private long mark;
|
||||
private long next;
|
||||
private int mark;
|
||||
private int mNext;
|
||||
|
||||
/**
|
||||
* Create a new compound reader.
|
||||
@@ -76,7 +76,7 @@ public class CompoundReader extends Reader {
|
||||
finalLock = pReaders; // NOTE: It's ok to sync on pReaders, as the
|
||||
// reference can't change, only it's elements
|
||||
|
||||
readers = new ArrayList<>();
|
||||
readers = new ArrayList<Reader>();
|
||||
|
||||
boolean markSupported = true;
|
||||
while (pReaders.hasNext()) {
|
||||
@@ -101,7 +101,7 @@ public class CompoundReader extends Reader {
|
||||
}
|
||||
|
||||
// NOTE: Reset mNext for every reader, and record marked reader in mark/reset methods!
|
||||
next = 0;
|
||||
mNext = 0;
|
||||
return current;
|
||||
}
|
||||
|
||||
@@ -135,7 +135,7 @@ public class CompoundReader extends Reader {
|
||||
|
||||
synchronized (finalLock) {
|
||||
ensureOpen();
|
||||
mark = next;
|
||||
mark = mNext;
|
||||
markedReader = currentReader;
|
||||
|
||||
current.mark(pReadLimit);
|
||||
@@ -158,7 +158,7 @@ public class CompoundReader extends Reader {
|
||||
}
|
||||
current.reset();
|
||||
|
||||
next = mark;
|
||||
mNext = mark;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -177,13 +177,13 @@ public class CompoundReader extends Reader {
|
||||
return read(); // In case of 0-length readers
|
||||
}
|
||||
|
||||
next++;
|
||||
mNext++;
|
||||
|
||||
return read;
|
||||
}
|
||||
}
|
||||
|
||||
public int read(char[] pBuffer, int pOffset, int pLength) throws IOException {
|
||||
public int read(char pBuffer[], int pOffset, int pLength) throws IOException {
|
||||
synchronized (finalLock) {
|
||||
int read = current.read(pBuffer, pOffset, pLength);
|
||||
|
||||
@@ -192,7 +192,7 @@ public class CompoundReader extends Reader {
|
||||
return read(pBuffer, pOffset, pLength); // In case of 0-length readers
|
||||
}
|
||||
|
||||
next += read;
|
||||
mNext += read;
|
||||
|
||||
return read;
|
||||
}
|
||||
@@ -213,7 +213,7 @@ public class CompoundReader extends Reader {
|
||||
return skip(pChars); // In case of 0-length readers
|
||||
}
|
||||
|
||||
next += skipped;
|
||||
mNext += skipped;
|
||||
|
||||
return skipped;
|
||||
}
|
||||
|
||||
@@ -50,8 +50,8 @@ public class StringArrayReader extends StringReader {
|
||||
protected final Object finalLock;
|
||||
private int currentSting;
|
||||
private int markedString;
|
||||
private long mark;
|
||||
private long next;
|
||||
private int mark;
|
||||
private int next;
|
||||
|
||||
/**
|
||||
* Create a new string array reader.
|
||||
@@ -151,7 +151,7 @@ public class StringArrayReader extends StringReader {
|
||||
}
|
||||
}
|
||||
|
||||
public int read(char[] pBuffer, int pOffset, int pLength) throws IOException {
|
||||
public int read(char pBuffer[], int pOffset, int pLength) throws IOException {
|
||||
synchronized (finalLock) {
|
||||
int read = current.read(pBuffer, pOffset, pLength);
|
||||
|
||||
|
||||
@@ -41,20 +41,21 @@ import java.io.InputStream;
|
||||
* underlying stream.
|
||||
*
|
||||
* @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 $
|
||||
*/
|
||||
public final class SubStream extends FilterInputStream {
|
||||
private long bytesLeft;
|
||||
private int markLimit;
|
||||
|
||||
/**
|
||||
* Creates a {@code SubStream} of the given {@code stream}.
|
||||
* Creates a {@code SubStream} of the given {@code pStream}.
|
||||
*
|
||||
* @param stream the underlying input stream
|
||||
* @param length maximum number of bytes to read from this stream
|
||||
* @param pStream the underlying input stream
|
||||
* @param pLength maximum number of bytes to read drom this stream
|
||||
*/
|
||||
public SubStream(final InputStream stream, final long length) {
|
||||
super(Validate.notNull(stream, "stream"));
|
||||
bytesLeft = Validate.isTrue(length >= 0, length, "length < 0: %s");
|
||||
public SubStream(final InputStream pStream, final long pLength) {
|
||||
super(Validate.notNull(pStream, "stream"));
|
||||
bytesLeft = pLength;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -63,23 +64,22 @@ public final class SubStream extends FilterInputStream {
|
||||
*/
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
// NOTE: Do not close the underlying stream, but consume it
|
||||
// NOTE: Do not close the underlying stream
|
||||
while (bytesLeft > 0) {
|
||||
if (skip(bytesLeft) <= 0 && read() < 0) {
|
||||
break;
|
||||
}
|
||||
//noinspection ResultOfMethodCallIgnored
|
||||
skip(bytesLeft);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int available() throws IOException {
|
||||
return (int) findMaxLen(super.available());
|
||||
return (int) Math.min(super.available(), bytesLeft);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mark(int readLimit) {
|
||||
super.mark(readLimit);// This either succeeds or does nothing...
|
||||
markLimit = readLimit;
|
||||
public void mark(int pReadLimit) {
|
||||
super.mark(pReadLimit);// This either succeeds or does nothing...
|
||||
markLimit = pReadLimit;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -93,42 +93,44 @@ public final class SubStream extends FilterInputStream {
|
||||
if (bytesLeft-- <= 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return super.read();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read(byte[] bytes) throws IOException {
|
||||
return read(bytes, 0, bytes.length);
|
||||
public final int read(byte[] pBytes) throws IOException {
|
||||
return read(pBytes, 0, pBytes.length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read(final byte[] bytes, final int off, final int len) throws IOException {
|
||||
public int read(final byte[] pBytes, final int pOffset, final int pLength) throws IOException {
|
||||
if (bytesLeft <= 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
int read = super.read(bytes, off, (int) findMaxLen(len));
|
||||
int read = super.read(pBytes, pOffset, (int) findMaxLen(pLength));
|
||||
bytesLeft = read < 0 ? 0 : bytesLeft - read;
|
||||
|
||||
return read;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long skip(long length) throws IOException {
|
||||
long skipped = super.skip(findMaxLen(length)); // Skips 0 or more, never -1
|
||||
bytesLeft -= skipped;
|
||||
|
||||
return skipped;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the maximum number of bytes we can read or skip, from this stream.
|
||||
*
|
||||
* @param length the requested length
|
||||
* @param pLength the requested length
|
||||
* @return the maximum number of bytes to read
|
||||
*/
|
||||
private long findMaxLen(long length) {
|
||||
return bytesLeft < length ? Math.max(bytesLeft, 0) : length;
|
||||
private long findMaxLen(long pLength) {
|
||||
if (bytesLeft < pLength) {
|
||||
return (int) Math.max(bytesLeft, 0);
|
||||
}
|
||||
else {
|
||||
return pLength;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public long skip(long pLength) throws IOException {
|
||||
long skipped = super.skip(findMaxLen(pLength));// Skips 0 or more, never -1
|
||||
bytesLeft -= skipped;
|
||||
return skipped;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,7 +59,7 @@ public final class DecoderStream extends FilterInputStream {
|
||||
* @see java.io.FilterInputStream#in
|
||||
*/
|
||||
public DecoderStream(final InputStream stream, final Decoder decoder) {
|
||||
// TODO: Let the decoder decide preferred buffer size
|
||||
// TODO: Let the decoder decide preferred buffer size
|
||||
this(stream, decoder, 1024);
|
||||
}
|
||||
|
||||
@@ -77,7 +77,7 @@ public final class DecoderStream extends FilterInputStream {
|
||||
super(stream);
|
||||
|
||||
this.decoder = decoder;
|
||||
buffer = ByteBuffer.allocate(bufferSize); // TODO: Allow decoder to specify minimum buffer size
|
||||
buffer = ByteBuffer.allocate(bufferSize);
|
||||
buffer.flip();
|
||||
}
|
||||
|
||||
|
||||
@@ -32,6 +32,7 @@ package com.twelvemonkeys.io;
|
||||
|
||||
import com.twelvemonkeys.lang.StringUtil;
|
||||
import com.twelvemonkeys.util.CollectionUtil;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Reader;
|
||||
@@ -39,8 +40,7 @@ import java.io.StringReader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* CompoundReaderTestCase
|
||||
|
||||
+3
-2
@@ -30,11 +30,12 @@
|
||||
|
||||
package com.twelvemonkeys.io;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
/**
|
||||
* FastByteArrayOutputStreamTestCase
|
||||
|
||||
@@ -30,10 +30,11 @@
|
||||
|
||||
package com.twelvemonkeys.io;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* MemoryCacheSeekableStreamTestCase
|
||||
@@ -91,13 +92,13 @@ public class FileSeekableStreamTest extends SeekableInputStreamAbstractTest {
|
||||
try {
|
||||
FileUtil.read(stream); // Read until EOF
|
||||
|
||||
assertEquals(-1, stream.read(), "EOF not reached (test case broken)");
|
||||
assertFalse(closed[0], "Underlying stream closed before close");
|
||||
assertEquals("EOF not reached (test case broken)", -1, stream.read());
|
||||
assertFalse("Underlying stream closed before close", closed[0]);
|
||||
}
|
||||
finally {
|
||||
stream.close();
|
||||
}
|
||||
|
||||
assertTrue(closed[0], "Underlying stream not closed");
|
||||
assertTrue("Underlying stream not closed", closed[0]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,14 +46,14 @@
|
||||
package com.twelvemonkeys.io;
|
||||
|
||||
import com.twelvemonkeys.lang.ObjectAbstractTest;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Random;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* InputStreamAbstractTestCase
|
||||
@@ -104,15 +104,15 @@ public abstract class InputStreamAbstractTest extends ObjectAbstractTest {
|
||||
int size = 5;
|
||||
InputStream input = makeInputStream(makeOrderedArray(size));
|
||||
for (int i = 0; i < size; i++) {
|
||||
assertTrue((size - i) >= input.available(), "Check Size [" + i + "]");
|
||||
assertEquals(i, input.read(), "Check Value [" + i + "]");
|
||||
assertTrue("Check Size [" + i + "]", (size - i) >= input.available());
|
||||
assertEquals("Check Value [" + i + "]", i, input.read());
|
||||
}
|
||||
assertEquals(0, input.available(), "Available after contents all read");
|
||||
assertEquals("Available after contents all read", 0, input.available());
|
||||
|
||||
// Test reading after the end of file
|
||||
try {
|
||||
int result = input.read();
|
||||
assertEquals( -1, result, "Wrong value read after end of file");
|
||||
assertEquals("Wrong value read after end of file", -1, result);
|
||||
}
|
||||
catch (IOException e) {
|
||||
fail("Should not have thrown an IOException: " + e.getMessage());
|
||||
@@ -122,12 +122,12 @@ public abstract class InputStreamAbstractTest extends ObjectAbstractTest {
|
||||
@Test
|
||||
public void testAvailable() throws Exception {
|
||||
InputStream input = makeInputStream(1);
|
||||
assertFalse(input.read() < 0, "Unexpected EOF");
|
||||
assertEquals(0, input.available(), "Available after contents all read");
|
||||
assertFalse("Unexpected EOF", input.read() < 0);
|
||||
assertEquals("Available after contents all read", 0, input.available());
|
||||
|
||||
// Check availbale is zero after End of file
|
||||
assertEquals(-1, input.read(), "End of File");
|
||||
assertEquals( 0, input.available(), "Available after End of File");
|
||||
assertEquals("End of File", -1, input.read());
|
||||
assertEquals("Available after End of File", 0, input.available());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -138,26 +138,26 @@ public abstract class InputStreamAbstractTest extends ObjectAbstractTest {
|
||||
|
||||
// Read into array
|
||||
int count1 = input.read(bytes);
|
||||
assertEquals(bytes.length, count1, "Read 1");
|
||||
assertEquals("Read 1", bytes.length, count1);
|
||||
for (int i = 0; i < count1; i++) {
|
||||
assertEquals(i, bytes[i], "Check Bytes 1");
|
||||
assertEquals("Check Bytes 1", i, bytes[i]);
|
||||
}
|
||||
|
||||
// Read into array
|
||||
int count2 = input.read(bytes);
|
||||
assertEquals(5, count2, "Read 2");
|
||||
assertEquals("Read 2", 5, count2);
|
||||
for (int i = 0; i < count2; i++) {
|
||||
assertEquals(count1 + i, bytes[i], "Check Bytes 2");
|
||||
assertEquals("Check Bytes 2", count1 + i, bytes[i]);
|
||||
}
|
||||
|
||||
// End of File
|
||||
int count3 = input.read(bytes);
|
||||
assertEquals(-1, count3, "Read 3 (EOF)");
|
||||
assertEquals("Read 3 (EOF)", -1, count3);
|
||||
|
||||
// Test reading after the end of file
|
||||
try {
|
||||
int result = input.read(bytes);
|
||||
assertEquals(-1, result, "Wrong value read after end of file");
|
||||
assertEquals("Wrong value read after end of file", -1, result);
|
||||
}
|
||||
catch (IOException e) {
|
||||
fail("Should not have thrown an IOException: " + e.getMessage());
|
||||
@@ -170,20 +170,20 @@ public abstract class InputStreamAbstractTest extends ObjectAbstractTest {
|
||||
int offset = 2;
|
||||
int lth = 4;
|
||||
int count5 = input.read(bytes, offset, lth);
|
||||
assertEquals(lth, count5, "Read 5");
|
||||
assertEquals("Read 5", lth, count5);
|
||||
for (int i = offset; i < lth; i++) {
|
||||
assertEquals(i - offset, bytes[i], "Check Bytes 2");
|
||||
assertEquals("Check Bytes 2", i - offset, bytes[i]);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEOF() throws Exception {
|
||||
InputStream input = makeInputStream(makeOrderedArray(2));
|
||||
assertEquals(0, input.read(), "Read 1");
|
||||
assertEquals(1, input.read(), "Read 2");
|
||||
assertEquals(-1, input.read(), "Read 3");
|
||||
assertEquals(-1, input.read(), "Read 4");
|
||||
assertEquals(-1, input.read(), "Read 5");
|
||||
assertEquals("Read 1", 0, input.read());
|
||||
assertEquals("Read 2", 1, input.read());
|
||||
assertEquals("Read 3", -1, input.read());
|
||||
assertEquals("Read 4", -1, input.read());
|
||||
assertEquals("Read 5", -1, input.read());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -205,7 +205,7 @@ public abstract class InputStreamAbstractTest extends ObjectAbstractTest {
|
||||
fail("Should throw IOException");
|
||||
}
|
||||
catch (IOException e) {
|
||||
assertTrue(e.getMessage().contains("reset"), "Wrong messge: " + e.getMessage());
|
||||
assertTrue("Wrong messge: " + e.getMessage(), e.getMessage().contains("reset"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -223,10 +223,10 @@ public abstract class InputStreamAbstractTest extends ObjectAbstractTest {
|
||||
// No mark may either throw exception, or reset to beginning of stream.
|
||||
try {
|
||||
input.reset();
|
||||
assertEquals(0, input.read(), "Re-read of reset data should be same");
|
||||
assertEquals("Re-read of reset data should be same", 0, input.read());
|
||||
}
|
||||
catch (Exception e) {
|
||||
assertTrue(e.getMessage().contains("mark"), "Wrong no mark IOException message");
|
||||
assertTrue("Wrong no mark IOException message", e.getMessage().contains("mark"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -249,7 +249,7 @@ public abstract class InputStreamAbstractTest extends ObjectAbstractTest {
|
||||
|
||||
// Read further
|
||||
for (int i = 0; i < 3; i++) {
|
||||
assertEquals((position + i), input.read(), "Read After Mark [" + i + "]");
|
||||
assertEquals("Read After Mark [" + i + "]", (position + i), input.read());
|
||||
}
|
||||
|
||||
// Reset
|
||||
@@ -257,7 +257,7 @@ public abstract class InputStreamAbstractTest extends ObjectAbstractTest {
|
||||
|
||||
// Read from marked position
|
||||
for (int i = 0; i < readlimit + 1; i++) {
|
||||
assertEquals((position + i), input.read(), "Read After Reset [" + i + "]");
|
||||
assertEquals("Read After Reset [" + i + "]", (position + i), input.read());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -280,16 +280,16 @@ public abstract class InputStreamAbstractTest extends ObjectAbstractTest {
|
||||
|
||||
// Read past marked position
|
||||
for (int i = 0; i < readlimit + 1; i++) {
|
||||
assertEquals((position + i), input.read(), "Read After Reset [" + i + "]");
|
||||
assertEquals("Read After Reset [" + i + "]", (position + i), input.read());
|
||||
}
|
||||
|
||||
// Reset after read limit passed, may either throw exception, or reset to last mark
|
||||
try {
|
||||
input.reset();
|
||||
assertEquals(1, input.read(), "Re-read of reset data should be same");
|
||||
assertEquals("Re-read of reset data should be same", 1, input.read());
|
||||
}
|
||||
catch (Exception e) {
|
||||
assertTrue(e.getMessage().contains("mark"), "Wrong read-limit IOException message");
|
||||
assertTrue("Wrong read-limit IOException message", e.getMessage().contains("mark"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -302,29 +302,29 @@ public abstract class InputStreamAbstractTest extends ObjectAbstractTest {
|
||||
}
|
||||
|
||||
int first = input.read();
|
||||
assertTrue(first >= 0, "Expected to read positive value");
|
||||
assertTrue("Expected to read positive value", first >= 0);
|
||||
|
||||
int readlimit = 5;
|
||||
|
||||
// Mark
|
||||
input.mark(readlimit);
|
||||
int read = input.read();
|
||||
assertTrue(read >= 0, "Expected to read positive value");
|
||||
assertTrue("Expected to read positive value", read >= 0);
|
||||
|
||||
assertTrue(input.read() >= 0);
|
||||
assertTrue(input.read() >= 0);
|
||||
|
||||
input.reset();
|
||||
assertEquals(read, input.read(), "Expected value read differs from actual");
|
||||
assertEquals("Expected value read differs from actual", read, input.read());
|
||||
|
||||
// Reset after read limit passed, may either throw exception, or reset to last good mark
|
||||
try {
|
||||
input.reset();
|
||||
int reRead = input.read();
|
||||
assertTrue(reRead == read || reRead == first, "Re-read of reset data should be same as initially marked or first");
|
||||
assertTrue("Re-read of reset data should be same as initially marked or first", reRead == read || reRead == first);
|
||||
}
|
||||
catch (Exception e) {
|
||||
assertTrue(e.getMessage().contains("mark"), "Wrong read-limit IOException message");
|
||||
assertTrue("Wrong read-limit IOException message", e.getMessage().contains("mark"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -332,17 +332,17 @@ public abstract class InputStreamAbstractTest extends ObjectAbstractTest {
|
||||
public void testSkip() throws Exception {
|
||||
InputStream input = makeInputStream(makeOrderedArray(10));
|
||||
|
||||
assertEquals(0, input.read(), "Unexpected value read");
|
||||
assertEquals(1, input.read(), "Unexpected value read");
|
||||
assertEquals(5, input.skip(5), "Unexpected number of bytes skipped");
|
||||
assertEquals(7, input.read(), "Unexpected value read");
|
||||
assertEquals("Unexpected value read", 0, input.read());
|
||||
assertEquals("Unexpected value read", 1, input.read());
|
||||
assertEquals("Unexpected number of bytes skipped", 5, input.skip(5));
|
||||
assertEquals("Unexpected value read", 7, input.read());
|
||||
|
||||
assertEquals(2, input.skip(5), "Unexpected number of bytes skipped"); // only 2 left to skip
|
||||
assertEquals(-1, input.read(), "Unexpected value read after EOF");
|
||||
assertEquals("Unexpected number of bytes skipped", 2, input.skip(5)); // only 2 left to skip
|
||||
assertEquals("Unexpected value read after EOF", -1, input.read());
|
||||
|
||||
// Spec says skip might return 0 or negative after EOF...
|
||||
assertTrue(input.skip(5) <= 0, "Positive value skipped after EOF"); // End of file
|
||||
assertEquals(-1, input.read(), "Unexpected value read after EOF");
|
||||
assertTrue("Positive value skipped after EOF", input.skip(5) <= 0); // End of file
|
||||
assertEquals("Unexpected value read after EOF", -1, input.read());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
+3
-2
@@ -30,11 +30,12 @@
|
||||
|
||||
package com.twelvemonkeys.io;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* LittleEndianDataInputStreamTest
|
||||
|
||||
@@ -31,12 +31,13 @@
|
||||
package com.twelvemonkeys.io;
|
||||
|
||||
import com.twelvemonkeys.lang.ObjectAbstractTest;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
/**
|
||||
* InputStreamAbstractTestCase
|
||||
|
||||
@@ -31,12 +31,12 @@
|
||||
package com.twelvemonkeys.io;
|
||||
|
||||
import com.twelvemonkeys.lang.ObjectAbstractTest;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Reader;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* ReaderAbstractTestCase
|
||||
@@ -112,7 +112,7 @@ public abstract class ReaderAbstractTest extends ObjectAbstractTest {
|
||||
int toSkip = mInput.length();
|
||||
while (toSkip > 0) {
|
||||
long skipped = reader.skip(toSkip);
|
||||
assertFalse(skipped < 0, "Skipped < 0");
|
||||
assertFalse("Skipped < 0", skipped < 0);
|
||||
toSkip -= skipped;
|
||||
}
|
||||
|
||||
|
||||
@@ -30,8 +30,10 @@
|
||||
|
||||
package com.twelvemonkeys.io;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
/**
|
||||
* SeekableAbstractTestCase
|
||||
|
||||
+23
-22
@@ -30,13 +30,14 @@
|
||||
|
||||
package com.twelvemonkeys.io;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.EOFException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* SeekableInputStreamAbstractTest
|
||||
@@ -78,25 +79,25 @@ public abstract class SeekableInputStreamAbstractTest extends InputStreamAbstrac
|
||||
return; // Not supported, skip test
|
||||
}
|
||||
|
||||
assertTrue(input.read() >= 0, "Expected to read positive value");
|
||||
assertTrue("Expected to read positive value", input.read() >= 0);
|
||||
|
||||
int readlimit = 5;
|
||||
|
||||
// Mark
|
||||
input.mark(readlimit);
|
||||
int read = input.read();
|
||||
assertTrue(read >= 0, "Expected to read positive value");
|
||||
assertTrue("Expected to read positive value", read >= 0);
|
||||
|
||||
input.reset();
|
||||
assertEquals(read, input.read(), "Expected value read differs from actual");
|
||||
assertEquals("Expected value read differs from actual", read, input.read());
|
||||
|
||||
// Reset after read limit passed, may either throw exception, or reset to last good mark
|
||||
try {
|
||||
input.reset();
|
||||
assertEquals(0, input.read(), "Re-read of reset data should be first");
|
||||
assertEquals("Re-read of reset data should be first", 0, input.read());
|
||||
}
|
||||
catch (Exception e) {
|
||||
assertTrue(e.getMessage().contains("mark"), "Wrong read-limit IOException message");
|
||||
assertTrue("Wrong read-limit IOException message", e.getMessage().contains("mark"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -126,7 +127,7 @@ public abstract class SeekableInputStreamAbstractTest extends InputStreamAbstrac
|
||||
|
||||
seekable.seek(pos);
|
||||
long streamPos = seekable.getStreamPosition();
|
||||
assertEquals(pos, streamPos, "Stream positon should match seeked position");
|
||||
assertEquals("Stream positon should match seeked position", pos, streamPos);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -136,7 +137,7 @@ public abstract class SeekableInputStreamAbstractTest extends InputStreamAbstrac
|
||||
seekable.seek(pos);
|
||||
seekable.flushBefore(pos);
|
||||
long flushedPos = seekable.getFlushedPosition();
|
||||
assertEquals(pos, flushedPos, "Flushed positon should match position");
|
||||
assertEquals("Flushed positon should match position", pos, flushedPos);
|
||||
|
||||
try {
|
||||
seekable.seek(pos - 1);
|
||||
@@ -381,13 +382,13 @@ public abstract class SeekableInputStreamAbstractTest extends InputStreamAbstrac
|
||||
int val;
|
||||
|
||||
val = stream.read();
|
||||
assertFalse(val == -1, "Unexepected EOF");
|
||||
assertFalse("Unexepected EOF", val == -1);
|
||||
val = stream.read();
|
||||
assertFalse(val == -1, "Unexepected EOF");
|
||||
assertFalse("Unexepected EOF", val == -1);
|
||||
val = stream.read();
|
||||
assertFalse(val == -1, "Unexepected EOF");
|
||||
assertFalse("Unexepected EOF", val == -1);
|
||||
val = stream.read();
|
||||
assertFalse(val == -1, "Unexepected EOF");
|
||||
assertFalse("Unexepected EOF", val == -1);
|
||||
|
||||
stream.seek(0);
|
||||
|
||||
@@ -421,19 +422,19 @@ public abstract class SeekableInputStreamAbstractTest extends InputStreamAbstrac
|
||||
|
||||
stream.seek(0);
|
||||
for (int i = 0; i < bytes.length; i += 2) {
|
||||
assertEquals(i, stream.getStreamPosition(), "Wrong stream position");
|
||||
assertEquals("Wrong stream position", i, stream.getStreamPosition());
|
||||
int count = stream.read(buffer, 0, 2);
|
||||
assertEquals(2, count);
|
||||
assertEquals(bytes[i], buffer[0], String.format("Wrong value read at pos %d", stream.getStreamPosition()));
|
||||
assertEquals(bytes[i + 1], buffer[1], String.format("Wrong value read at pos %d", stream.getStreamPosition()));
|
||||
assertEquals(String.format("Wrong value read at pos %d", stream.getStreamPosition()), bytes[i], buffer[0]);
|
||||
assertEquals(String.format("Wrong value read at pos %d", stream.getStreamPosition()), bytes[i + 1], buffer[1]);
|
||||
}
|
||||
|
||||
stream.seek(0);
|
||||
for (int i = 0; i < bytes.length; i++) {
|
||||
assertEquals(i, stream.getStreamPosition(), "Wrong stream position");
|
||||
assertEquals("Wrong stream position", i, stream.getStreamPosition());
|
||||
int actual = stream.read();
|
||||
assertEquals(bytes[i] & 0xff, actual, String.format("Wrong value read at pos %d", stream.getStreamPosition()));
|
||||
assertEquals(bytes[i], (byte) actual, String.format("Wrong value read at pos %d", stream.getStreamPosition()));
|
||||
assertEquals(String.format("Wrong value read at pos %d", stream.getStreamPosition()), bytes[i] & 0xff, actual);
|
||||
assertEquals(String.format("Wrong value read at pos %d", stream.getStreamPosition()), bytes[i], (byte) actual);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -455,14 +456,14 @@ public abstract class SeekableInputStreamAbstractTest extends InputStreamAbstrac
|
||||
try {
|
||||
FileUtil.read(stream); // Read until EOF
|
||||
|
||||
assertEquals(-1, stream.read(), "EOF not reached (test case broken)");
|
||||
assertFalse(closed[0], "Underlying stream closed before close");
|
||||
assertEquals("EOF not reached (test case broken)", -1, stream.read());
|
||||
assertFalse("Underlying stream closed before close", closed[0]);
|
||||
}
|
||||
finally {
|
||||
stream.close();
|
||||
}
|
||||
|
||||
assertTrue(closed[0], "Underlying stream not closed");
|
||||
assertTrue("Underlying stream not closed", closed[0]);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -31,12 +31,12 @@
|
||||
package com.twelvemonkeys.io;
|
||||
|
||||
import com.twelvemonkeys.lang.StringUtil;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Reader;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* StringArrayReaderTestCase
|
||||
|
||||
@@ -1,119 +0,0 @@
|
||||
package com.twelvemonkeys.io;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.time.Duration;
|
||||
import java.util.Arrays;
|
||||
import java.util.Random;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
/**
|
||||
* SubStreamTest.
|
||||
*
|
||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||
* @author last modified by $Author: haraldk$
|
||||
* @version $Id: SubStreamTest.java,v 1.0 07/11/2023 haraldk Exp$
|
||||
*/
|
||||
public class SubStreamTest {
|
||||
|
||||
private final Random rng = new Random(2918475687L);
|
||||
|
||||
@SuppressWarnings("resource")
|
||||
@Test
|
||||
public void testCreateNullStream() {
|
||||
assertThrows(IllegalArgumentException.class, () -> {
|
||||
new SubStream(null, 42);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateNegativeLength() {
|
||||
assertThrows(IllegalArgumentException.class, () -> {
|
||||
new SubStream(new ByteArrayInputStream(new byte[1]), -1);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReadAll() throws IOException {
|
||||
byte[] buf = new byte[128];
|
||||
rng.nextBytes(buf);
|
||||
|
||||
try (InputStream stream = new SubStream(new ByteArrayInputStream(buf), buf.length)) {
|
||||
for (byte b : buf) {
|
||||
assertEquals(b, (byte) stream.read());
|
||||
}
|
||||
|
||||
assertEquals(-1, stream.read());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReadAllArray() throws IOException {
|
||||
byte[] buf = new byte[128];
|
||||
rng.nextBytes(buf);
|
||||
|
||||
try (InputStream stream = new SubStream(new ByteArrayInputStream(buf), buf.length)) {
|
||||
byte[] temp = new byte[buf.length / 4];
|
||||
for (int i = 0; i < 4; i++) {
|
||||
assertEquals(temp.length, stream.read(temp)); // Depends on ByteArrayInputStream specifics...
|
||||
assertArrayEquals(Arrays.copyOfRange(buf, i * temp.length, (i + 1) * temp.length), temp);
|
||||
}
|
||||
|
||||
assertEquals(-1, stream.read());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSkipAll() throws IOException {
|
||||
byte[] buf = new byte[128];
|
||||
|
||||
try (InputStream stream = new SubStream(new ByteArrayInputStream(buf), buf.length)) {
|
||||
assertEquals(128, stream.skip(buf.length)); // Depends on ByteArrayInputStream specifics...
|
||||
assertEquals(-1, stream.read());
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("EmptyTryBlock")
|
||||
@Test
|
||||
public void testCloseConsumesAll() throws IOException {
|
||||
ByteArrayInputStream stream = new ByteArrayInputStream(new byte[128]);
|
||||
|
||||
try (InputStream ignore = new SubStream(stream, 128)) {
|
||||
// Nothing here...
|
||||
}
|
||||
|
||||
assertEquals(0, stream.available());
|
||||
assertEquals(-1, stream.read());
|
||||
}
|
||||
|
||||
@SuppressWarnings("EmptyTryBlock")
|
||||
@Test
|
||||
public void testCloseConsumesAllLongStream() throws IOException {
|
||||
ByteArrayInputStream stream = new ByteArrayInputStream(new byte[256]);
|
||||
|
||||
try (InputStream ignore = new SubStream(stream, 128)) {
|
||||
// Nothing here...
|
||||
}
|
||||
|
||||
assertEquals(128, stream.available());
|
||||
assertEquals(0, stream.read());
|
||||
}
|
||||
|
||||
@SuppressWarnings("EmptyTryBlock")
|
||||
@Test
|
||||
public void testCloseConsumesAllShortStream() throws IOException {
|
||||
assertTimeoutPreemptively(Duration.ofMillis(500), () -> {
|
||||
ByteArrayInputStream stream = new ByteArrayInputStream(new byte[13]);
|
||||
|
||||
try (InputStream ignore = new SubStream(stream, 42)) {
|
||||
// Nothing here...
|
||||
}
|
||||
|
||||
assertEquals(0, stream.available());
|
||||
assertEquals(-1, stream.read());
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -31,13 +31,15 @@
|
||||
package com.twelvemonkeys.io.enc;
|
||||
|
||||
import com.twelvemonkeys.io.FileUtil;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
/**
|
||||
* Base64DecoderTest
|
||||
* <p/>
|
||||
@@ -64,7 +66,7 @@ public class Base64DecoderTest extends DecoderAbstractTest {
|
||||
|
||||
FileUtil.copy(in, bytes);
|
||||
|
||||
assertEquals("", new String(bytes.toByteArray()), "Strings does not match");
|
||||
assertEquals("Strings does not match", "", new String(bytes.toByteArray()));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -76,7 +78,7 @@ public class Base64DecoderTest extends DecoderAbstractTest {
|
||||
|
||||
FileUtil.copy(in, bytes);
|
||||
|
||||
assertEquals("test", new String(bytes.toByteArray()), "Strings does not match");
|
||||
assertEquals("Strings does not match", "test", new String(bytes.toByteArray()));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -91,12 +93,11 @@ public class Base64DecoderTest extends DecoderAbstractTest {
|
||||
|
||||
FileUtil.copy(in, bytes);
|
||||
|
||||
assertEquals(
|
||||
assertEquals("Strings does not match",
|
||||
"Lorem ipsum dolor sit amet, consectetuer adipiscing " +
|
||||
"elit. Fusce est. Morbi luctus consectetuer justo. Vivamus " +
|
||||
"dapibus laoreet purus. Nunc viverra dictum nisl. Integer " +
|
||||
"ullamcorper, nisi in dictum amet.",
|
||||
new String(bytes.toByteArray()),
|
||||
"Strings does not match");
|
||||
new String(bytes.toByteArray()));
|
||||
}
|
||||
}
|
||||
@@ -30,12 +30,13 @@
|
||||
|
||||
package com.twelvemonkeys.io.enc;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
/**
|
||||
* Base64EncoderTest
|
||||
@@ -62,7 +63,7 @@ public class Base64EncoderTest extends EncoderAbstractTest {
|
||||
OutputStream out = new EncoderStream(bytes, createEncoder(), true);
|
||||
out.write(data.getBytes());
|
||||
|
||||
assertEquals("", new String(bytes.toByteArray()), "Strings does not match");
|
||||
assertEquals("Strings does not match", "", new String(bytes.toByteArray()));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -73,7 +74,7 @@ public class Base64EncoderTest extends EncoderAbstractTest {
|
||||
OutputStream out = new EncoderStream(bytes, createEncoder(), true);
|
||||
out.write(data.getBytes());
|
||||
|
||||
assertEquals("dGVzdA==", new String(bytes.toByteArray()), "Strings does not match");
|
||||
assertEquals("Strings does not match", "dGVzdA==", new String(bytes.toByteArray()));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -87,12 +88,11 @@ public class Base64EncoderTest extends EncoderAbstractTest {
|
||||
OutputStream out = new EncoderStream(bytes, createEncoder(), true);
|
||||
out.write(data.getBytes());
|
||||
|
||||
assertEquals(
|
||||
assertEquals("Strings does not match",
|
||||
"TG9yZW0gaXBzdW0gZG9sb3Igc2l0IGFtZXQsIGNvbnNlY3RldHVlciBhZGlwaXNjaW5nIGVsaXQuIEZ1" +
|
||||
"c2NlIGVzdC4gTW9yYmkgbHVjdHVzIGNvbnNlY3RldHVlciBqdXN0by4gVml2YW11cyBkYXBpYnVzIGxh" +
|
||||
"b3JlZXQgcHVydXMuIE51bmMgdml2ZXJyYSBkaWN0dW0gbmlzbC4gSW50ZWdlciB1bGxhbWNvcnBlciwg" +
|
||||
"bmlzaSBpbiBkaWN0dW0gYW1ldC4=",
|
||||
new String(bytes.toByteArray()),
|
||||
"Strings does not match");
|
||||
new String(bytes.toByteArray()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,13 +32,12 @@ package com.twelvemonkeys.io.enc;
|
||||
|
||||
import com.twelvemonkeys.io.FileUtil;
|
||||
import com.twelvemonkeys.lang.ObjectAbstractTest;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.awt.image.ImageProducer;
|
||||
import java.io.*;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* AbstractDecoderTest
|
||||
@@ -56,13 +55,13 @@ public abstract class DecoderAbstractTest extends ObjectAbstractTest {
|
||||
return createDecoder();
|
||||
}
|
||||
|
||||
@Test
|
||||
@Test(expected = NullPointerException.class)
|
||||
public final void testNullDecode() throws IOException {
|
||||
Decoder decoder = createDecoder();
|
||||
ByteArrayInputStream bytes = new ByteArrayInputStream(new byte[20]);
|
||||
assertThrows(NullPointerException.class, () -> {
|
||||
decoder.decode(bytes, null);
|
||||
});
|
||||
|
||||
decoder.decode(bytes, null);
|
||||
fail("null should throw NullPointerException");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -72,7 +71,7 @@ public abstract class DecoderAbstractTest extends ObjectAbstractTest {
|
||||
|
||||
try {
|
||||
int count = decoder.decode(bytes, ByteBuffer.allocate(128));
|
||||
assertEquals( 0, count, "Should not be able to read any bytes");
|
||||
assertEquals("Should not be able to read any bytes", 0, count);
|
||||
}
|
||||
catch (EOFException allowed) {
|
||||
// Okay
|
||||
@@ -95,7 +94,7 @@ public abstract class DecoderAbstractTest extends ObjectAbstractTest {
|
||||
byte[] encoded = outBytes.toByteArray();
|
||||
|
||||
byte[] decoded = FileUtil.read(new DecoderStream(new ByteArrayInputStream(encoded), createDecoder()));
|
||||
assertArrayEquals(data, decoded, String.format("Data %d", pLength));
|
||||
assertArrayEquals(String.format("Data %d", pLength), data, decoded);
|
||||
|
||||
InputStream in = new DecoderStream(new ByteArrayInputStream(encoded), createDecoder());
|
||||
outBytes = new ByteArrayOutputStream();
|
||||
@@ -104,7 +103,7 @@ public abstract class DecoderAbstractTest extends ObjectAbstractTest {
|
||||
in.close();
|
||||
|
||||
decoded = outBytes.toByteArray();
|
||||
assertArrayEquals(data, decoded, String.format("Data %d", pLength));
|
||||
assertArrayEquals(String.format("Data %d", pLength), data, decoded);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
|
||||
package com.twelvemonkeys.io.enc;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
@@ -38,8 +39,7 @@ import java.nio.ByteBuffer;
|
||||
import java.util.Arrays;
|
||||
import java.util.Random;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
public class DecoderStreamTest {
|
||||
|
||||
|
||||
@@ -33,12 +33,13 @@ package com.twelvemonkeys.io.enc;
|
||||
import com.twelvemonkeys.io.FileUtil;
|
||||
import com.twelvemonkeys.lang.ObjectAbstractTest;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.Random;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import static org.junit.Assert.assertArrayEquals;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
/**
|
||||
* AbstractEncoderTest
|
||||
|
||||
@@ -30,6 +30,8 @@
|
||||
|
||||
package com.twelvemonkeys.io.enc;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
@@ -37,8 +39,7 @@ import java.nio.ByteBuffer;
|
||||
import java.util.Arrays;
|
||||
import java.util.Random;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import static org.junit.Assert.assertArrayEquals;
|
||||
|
||||
public class EncoderStreamTest {
|
||||
|
||||
|
||||
+16
-17
@@ -31,9 +31,9 @@
|
||||
package com.twelvemonkeys.io.ole2;
|
||||
|
||||
import com.twelvemonkeys.io.MemoryCacheSeekableStream;
|
||||
import org.junit.Test;
|
||||
|
||||
import javax.imageio.stream.MemoryCacheImageInputStream;
|
||||
import java.awt.image.ImageProducer;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
@@ -43,8 +43,8 @@ import java.nio.ByteOrder;
|
||||
import java.util.SortedSet;
|
||||
import java.util.TreeSet;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* CompoundDocumentTestCase
|
||||
*
|
||||
@@ -59,8 +59,8 @@ public class CompoundDocumentTest {
|
||||
protected final CompoundDocument createTestDocument() throws IOException {
|
||||
URL input = getClass().getResource(SAMPLE_DATA);
|
||||
|
||||
assertNotNull(input, "Missing test resource!");
|
||||
assertEquals( "file", input.getProtocol(), "Test resource not a file:// resource");
|
||||
assertNotNull("Missing test resource!", input);
|
||||
assertEquals("Test resource not a file:// resource", "file", input.getProtocol());
|
||||
|
||||
try {
|
||||
return new CompoundDocument(new File(input.toURI()));
|
||||
@@ -103,7 +103,7 @@ public class CompoundDocumentTest {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@Test(expected = UnsupportedOperationException.class)
|
||||
public void testChildEntriesUnmodifiable() throws IOException {
|
||||
try (CompoundDocument document = createTestDocument()) {
|
||||
Entry root = document.getRootEntry();
|
||||
@@ -111,10 +111,9 @@ public class CompoundDocumentTest {
|
||||
assertNotNull(root);
|
||||
|
||||
SortedSet<Entry> children = root.getChildEntries();
|
||||
assertThrows(UnsupportedOperationException.class, () -> {
|
||||
// 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());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -129,7 +128,7 @@ public class CompoundDocumentTest {
|
||||
Entry catalog = root.getChildEntry("Catalog");
|
||||
|
||||
assertNotNull(catalog);
|
||||
assertNotNull(catalog.getInputStream(), "Input stream may not be null");
|
||||
assertNotNull("Input stream may not be null", catalog.getInputStream());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -137,7 +136,7 @@ public class CompoundDocumentTest {
|
||||
public void testReadCatalogInputStream() throws IOException {
|
||||
InputStream input = getClass().getResourceAsStream(SAMPLE_DATA);
|
||||
|
||||
assertNotNull(input, "Missing test resource!");
|
||||
assertNotNull("Missing test resource!", input);
|
||||
|
||||
CompoundDocument document = new CompoundDocument(input);
|
||||
Entry root = document.getRootEntry();
|
||||
@@ -146,14 +145,14 @@ public class CompoundDocumentTest {
|
||||
|
||||
Entry catalog = root.getChildEntry("Catalog");
|
||||
assertNotNull(catalog);
|
||||
assertNotNull(catalog.getInputStream(), "Input stream may not be null");
|
||||
assertNotNull("Input stream may not be null", catalog.getInputStream());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReadCatalogSeekableStream() throws IOException {
|
||||
InputStream input = getClass().getResourceAsStream(SAMPLE_DATA);
|
||||
|
||||
assertNotNull(input, "Missing test resource!");
|
||||
assertNotNull("Missing test resource!", input);
|
||||
|
||||
CompoundDocument document = new CompoundDocument(new MemoryCacheSeekableStream(input));
|
||||
Entry root = document.getRootEntry();
|
||||
@@ -162,14 +161,14 @@ public class CompoundDocumentTest {
|
||||
|
||||
Entry catalog = root.getChildEntry("Catalog");
|
||||
assertNotNull(catalog);
|
||||
assertNotNull(catalog.getInputStream(), "Input stream may not be null");
|
||||
assertNotNull("Input stream may not be null", catalog.getInputStream());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReadCatalogImageInputStream() throws IOException {
|
||||
InputStream input = getClass().getResourceAsStream(SAMPLE_DATA);
|
||||
|
||||
assertNotNull(input, "Missing test resource!");
|
||||
assertNotNull("Missing test resource!", input);
|
||||
|
||||
MemoryCacheImageInputStream stream = new MemoryCacheImageInputStream(input);
|
||||
stream.setByteOrder(ByteOrder.LITTLE_ENDIAN);
|
||||
@@ -184,6 +183,6 @@ public class CompoundDocumentTest {
|
||||
Entry catalog = root.getChildEntry("Catalog");
|
||||
|
||||
assertNotNull(catalog);
|
||||
assertNotNull(catalog.getInputStream(), "Input stream may not be null");
|
||||
assertNotNull("Input stream may not be null", catalog.getInputStream());
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -31,7 +31,7 @@
|
||||
package com.twelvemonkeys.io.ole2;
|
||||
|
||||
import com.twelvemonkeys.io.*;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
|
||||
|
||||
+4
-4
@@ -33,6 +33,7 @@ package com.twelvemonkeys.io.ole2;
|
||||
import com.twelvemonkeys.io.InputStreamAbstractTest;
|
||||
import com.twelvemonkeys.io.LittleEndianDataOutputStream;
|
||||
import com.twelvemonkeys.io.MemoryCacheSeekableStream;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
@@ -41,8 +42,7 @@ import java.io.InputStream;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* CompoundDocument_StreamTestCase
|
||||
@@ -165,8 +165,8 @@ public class CompoundDocument_StreamTest extends InputStreamAbstractTest {
|
||||
count++;
|
||||
}
|
||||
|
||||
assertFalse(count < 32, "Short stream");
|
||||
assertFalse(count > 32, "Stream overrun");
|
||||
assertFalse("Short stream", count < 32);
|
||||
assertFalse("Stream overrun", count > 32);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -30,8 +30,9 @@
|
||||
|
||||
package com.twelvemonkeys.net;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
/**
|
||||
* HTTPUtilTest
|
||||
|
||||
@@ -4,25 +4,17 @@
|
||||
<parent>
|
||||
<groupId>com.twelvemonkeys.common</groupId>
|
||||
<artifactId>common</artifactId>
|
||||
<version>3.13.0</version>
|
||||
<version>3.8.3</version>
|
||||
</parent>
|
||||
<artifactId>common-lang</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
<name>TwelveMonkeys :: Common :: Language support</name>
|
||||
<description>
|
||||
TwelveMonkeys Common language support classes.
|
||||
The TwelveMonkeys Common Language support
|
||||
</description>
|
||||
|
||||
<properties>
|
||||
<project.jpms.module.name>com.twelvemonkeys.common.lang</project.jpms.module.name>
|
||||
</properties>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.felix</groupId>
|
||||
<artifactId>maven-bundle-plugin</artifactId>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
|
||||
@@ -904,7 +904,7 @@ public final class StringUtil {
|
||||
}
|
||||
catch (ParseException pe) {
|
||||
// Wrap in RuntimeException
|
||||
throw new IllegalArgumentException(pe.getMessage() + " at pos " + pe.getErrorOffset());
|
||||
throw new IllegalArgumentException(pe.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -30,13 +30,14 @@
|
||||
|
||||
package com.twelvemonkeys.lang;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* BeanUtilTestCase
|
||||
@@ -160,8 +161,10 @@ public class BeanUtilTest {
|
||||
}
|
||||
|
||||
assertNotNull(bean.getAmbiguous());
|
||||
assertEquals("one", bean.getAmbiguous(), "String converted rather than invoking setAmbiguous(String), ordering not predictable");
|
||||
assertSame(value, bean.getAmbiguous(), "String converted rather than invoking setAmbiguous(String), ordering not predictable");
|
||||
assertEquals("String converted rather than invoking setAmbiguous(String), ordering not predictable",
|
||||
"one", bean.getAmbiguous());
|
||||
assertSame("String converted rather than invoking setAmbiguous(String), ordering not predictable",
|
||||
value, bean.getAmbiguous());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -181,10 +184,10 @@ public class BeanUtilTest {
|
||||
}
|
||||
|
||||
assertNotNull(bean.getAmbiguous());
|
||||
assertEquals(2, bean.getAmbiguous(),
|
||||
"Integer converted rather than invoking setAmbiguous(Integer), ordering not predictable");
|
||||
assertSame(value, bean.getAmbiguous(),
|
||||
"Integer converted rather than invoking setAmbiguous(Integer), ordering not predictable");
|
||||
assertEquals("Integer converted rather than invoking setAmbiguous(Integer), ordering not predictable",
|
||||
2, bean.getAmbiguous());
|
||||
assertSame("Integer converted rather than invoking setAmbiguous(Integer), ordering not predictable",
|
||||
value, bean.getAmbiguous());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -204,8 +207,10 @@ public class BeanUtilTest {
|
||||
}
|
||||
|
||||
assertNotNull(bean.getAmbiguous());
|
||||
assertEquals(value.getClass(), bean.getAmbiguous().getClass(), "Object converted rather than invoking setAmbiguous(Object), ordering not predictable");
|
||||
assertSame(value, bean.getAmbiguous(), "Object converted rather than invoking setAmbiguous(Object), ordering not predictable");
|
||||
assertEquals("Object converted rather than invoking setAmbiguous(Object), ordering not predictable",
|
||||
value.getClass(), bean.getAmbiguous().getClass());
|
||||
assertSame("Object converted rather than invoking setAmbiguous(Object), ordering not predictable",
|
||||
value, bean.getAmbiguous());
|
||||
}
|
||||
|
||||
static class TestBean {
|
||||
|
||||
@@ -30,16 +30,16 @@
|
||||
|
||||
package com.twelvemonkeys.lang;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.Parameterized;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Calendar;
|
||||
import java.util.List;
|
||||
import java.util.TimeZone;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
/**
|
||||
* DateUtilTest
|
||||
@@ -48,9 +48,12 @@ import static org.junit.jupiter.api.Assertions.*;
|
||||
* @author last modified by $Author: haraldk$
|
||||
* @version $Id: DateUtilTest.java,v 1.0 11.04.12 16:21 haraldk Exp$
|
||||
*/
|
||||
|
||||
@RunWith(Parameterized.class)
|
||||
public class DateUtilTest {
|
||||
|
||||
private final TimeZone timeZone;
|
||||
|
||||
@Parameterized.Parameters
|
||||
public static List<Object[]> timeZones() {
|
||||
return Arrays.asList(new Object[][] {
|
||||
{TimeZone.getTimeZone("UTC")},
|
||||
@@ -59,6 +62,10 @@ public class DateUtilTest {
|
||||
});
|
||||
}
|
||||
|
||||
public DateUtilTest(final TimeZone timeZone) {
|
||||
this.timeZone = timeZone;
|
||||
}
|
||||
|
||||
private Calendar getCalendar(long time) {
|
||||
return getCalendar(time, TimeZone.getDefault());
|
||||
}
|
||||
@@ -94,9 +101,8 @@ public class DateUtilTest {
|
||||
assertEquals(0, calendar.get(Calendar.MINUTE));
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("timeZones")
|
||||
public void testRoundToHourTZ(TimeZone timeZone) {
|
||||
@Test
|
||||
public void testRoundToHourTZ() {
|
||||
Calendar calendar = getCalendar(DateUtil.roundToHour(System.currentTimeMillis(), timeZone), timeZone);
|
||||
|
||||
assertEquals(0, calendar.get(Calendar.MILLISECOND));
|
||||
@@ -114,9 +120,8 @@ public class DateUtilTest {
|
||||
assertEquals(0, calendar.get(Calendar.HOUR_OF_DAY));
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("timeZones")
|
||||
public void testRoundToDayTZ(TimeZone timeZone) {
|
||||
@Test
|
||||
public void testRoundToDayTZ() {
|
||||
Calendar calendar = getCalendar(DateUtil.roundToDay(System.currentTimeMillis(), timeZone), timeZone);
|
||||
|
||||
assertEquals(0, calendar.get(Calendar.MILLISECOND));
|
||||
|
||||
@@ -30,11 +30,12 @@
|
||||
|
||||
package com.twelvemonkeys.lang;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.*;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* AbstractObjectTestCase
|
||||
@@ -78,10 +79,10 @@ public abstract class ObjectAbstractTest {
|
||||
|
||||
Class cl = obj.getClass();
|
||||
if (isEqualsOverriden(cl)) {
|
||||
assertTrue(isHashCodeOverriden(cl), "Class " + cl.getName() + " implements equals but not hashCode");
|
||||
assertTrue("Class " + cl.getName() + " implements equals but not hashCode", isHashCodeOverriden(cl));
|
||||
}
|
||||
else if (isHashCodeOverriden(cl)) {
|
||||
assertTrue(isEqualsOverriden(cl), "Class " + cl.getName() + " implements hashCode but not equals");
|
||||
assertTrue("Class " + cl.getName() + " implements hashCode but not equals", isEqualsOverriden(cl));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -106,7 +107,7 @@ public abstract class ObjectAbstractTest {
|
||||
@Test
|
||||
public void testObjectEqualsSelf() {
|
||||
Object obj = makeObject();
|
||||
assertEquals(obj, obj, "An Object should equal itself");
|
||||
assertEquals("An Object should equal itself", obj, obj);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -114,26 +115,32 @@ public abstract class ObjectAbstractTest {
|
||||
Object obj = makeObject();
|
||||
// NOTE: Makes sure this doesn't throw NPE either
|
||||
//noinspection ObjectEqualsNull
|
||||
assertFalse(obj.equals(null), "An object should never equal null");
|
||||
assertFalse("An object should never equal null", obj.equals(null));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testObjectHashCodeEqualsSelfHashCode() {
|
||||
Object obj = makeObject();
|
||||
assertEquals(obj.hashCode(), obj.hashCode(), "hashCode should be repeatable");
|
||||
assertEquals("hashCode should be repeatable", obj.hashCode(), obj.hashCode());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testObjectHashCodeEqualsContract() {
|
||||
Object obj1 = makeObject();
|
||||
if (obj1.equals(obj1)) {
|
||||
assertEquals(obj1.hashCode(), obj1.hashCode(), "[1] When two objects are equal, their hashCodes should be also.");
|
||||
assertEquals(
|
||||
"[1] When two objects are equal, their hashCodes should be also.",
|
||||
obj1.hashCode(), obj1.hashCode());
|
||||
}
|
||||
// TODO: Make sure we create at least one equal object, and one different object
|
||||
Object obj2 = makeObject();
|
||||
if (obj1.equals(obj2)) {
|
||||
assertEquals(obj1.hashCode(), obj2.hashCode(), "[2] When two objects are equal, their hashCodes should be also.");
|
||||
assertTrue(obj2.equals(obj1), "When obj1.equals(obj2) is true, then obj2.equals(obj1) should also be true");
|
||||
assertEquals(
|
||||
"[2] When two objects are equal, their hashCodes should be also.",
|
||||
obj1.hashCode(), obj2.hashCode());
|
||||
assertTrue(
|
||||
"When obj1.equals(obj2) is true, then obj2.equals(obj1) should also be true",
|
||||
obj2.equals(obj1));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -162,14 +169,14 @@ public abstract class ObjectAbstractTest {
|
||||
|
||||
Object cloned = clone.invoke(obj);
|
||||
|
||||
assertNotNull(cloned, "Cloned object should never be null");
|
||||
assertNotNull("Cloned object should never be null", cloned);
|
||||
|
||||
// TODO: This can only be asserted if equals() test is based on
|
||||
// value equality, not reference (identity) equality
|
||||
// Maybe it's possible to do a reflective introspection of
|
||||
// the objects fields?
|
||||
if (isHashCodeOverriden(cl)) {
|
||||
assertEquals(obj, cloned, "Cloned object not equal");
|
||||
assertEquals("Cloned object not equal", obj, cloned);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -228,7 +235,7 @@ public abstract class ObjectAbstractTest {
|
||||
// Maybe it's possible to do a reflective introspection of
|
||||
// the objects fields?
|
||||
if (isEqualsOverriden(obj.getClass())) {
|
||||
assertEquals(obj, dest, "obj != deserialize(serialize(obj))");
|
||||
assertEquals("obj != deserialize(serialize(obj))", obj, dest);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,11 +30,13 @@
|
||||
|
||||
package com.twelvemonkeys.lang;
|
||||
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.Properties;
|
||||
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
|
||||
/**
|
||||
* PlatformTest
|
||||
@@ -119,7 +121,7 @@ public class PlatformTest {
|
||||
assertEquals(Platform.Architecture.X86, platform.getArchitecture());
|
||||
}
|
||||
|
||||
@Disabled("Known issue, needs resolve")
|
||||
@Ignore("Known issue, needs resolve")
|
||||
@Test
|
||||
public void testCreateWindows686() {
|
||||
Platform platform = new Platform(createProperties("Windows", "5.1", "686"));
|
||||
@@ -127,7 +129,7 @@ public class PlatformTest {
|
||||
assertEquals(Platform.Architecture.X86, platform.getArchitecture());
|
||||
}
|
||||
|
||||
@Disabled("Known issue, needs resolve")
|
||||
@Ignore("Known issue, needs resolve")
|
||||
@Test
|
||||
public void testCreateLinuxX86() {
|
||||
Platform platform = new Platform(createProperties("Linux", "3.0.18", "x86"));
|
||||
|
||||
@@ -30,6 +30,8 @@
|
||||
|
||||
package com.twelvemonkeys.lang;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.awt.*;
|
||||
import java.sql.Timestamp;
|
||||
import java.text.DateFormat;
|
||||
@@ -39,8 +41,8 @@ import java.util.Date;
|
||||
import java.util.GregorianCalendar;
|
||||
import java.util.Locale;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* StringUtilTestCase
|
||||
*
|
||||
@@ -163,10 +165,10 @@ public class StringUtilTest {
|
||||
// Test all alpha-chars
|
||||
for (int i = 'a'; i < 'z'; i++) {
|
||||
if (TEST_STRING.indexOf(i) < 0) {
|
||||
assertFalse(StringUtil.contains(TEST_STRING, i), TEST_STRING + " seems to contain '" + (char) i + "', at index " + TEST_STRING.indexOf(i));
|
||||
assertFalse(TEST_STRING + " seems to contain '" + (char) i + "', at index " + TEST_STRING.indexOf(i), StringUtil.contains(TEST_STRING, i));
|
||||
}
|
||||
else {
|
||||
assertTrue(StringUtil.contains(TEST_STRING, i), TEST_STRING + " seems to not contain '" + (char) i + "', at index " + TEST_STRING.indexOf(i));
|
||||
assertTrue(TEST_STRING + " seems to not contain '" + (char) i + "', at index " + TEST_STRING.indexOf(i), StringUtil.contains(TEST_STRING, i));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -197,10 +199,10 @@ public class StringUtilTest {
|
||||
// Test all alpha-chars
|
||||
for (int i = 'a'; i < 'z'; i++) {
|
||||
if ((TEST_STRING.indexOf(i) < 0) && (TEST_STRING.indexOf(Character.toUpperCase((char) i)) < 0)) {
|
||||
assertFalse(StringUtil.containsIgnoreCase(TEST_STRING, i), TEST_STRING + " seems to contain '" + (char) i + "', at index " + Math.max(TEST_STRING.indexOf(i), TEST_STRING.indexOf(Character.toUpperCase((char) i))));
|
||||
assertFalse(TEST_STRING + " seems to contain '" + (char) i + "', at index " + Math.max(TEST_STRING.indexOf(i), TEST_STRING.indexOf(Character.toUpperCase((char) i))), StringUtil.containsIgnoreCase(TEST_STRING, i));
|
||||
}
|
||||
else {
|
||||
assertTrue(StringUtil.containsIgnoreCase(TEST_STRING, i), TEST_STRING + " seems to not contain '" + (char) i + "', at index " + TEST_STRING.indexOf(i));
|
||||
assertTrue(TEST_STRING + " seems to not contain '" + (char) i + "', at index " + TEST_STRING.indexOf(i), StringUtil.containsIgnoreCase(TEST_STRING, i));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -348,10 +350,10 @@ public class StringUtilTest {
|
||||
// Test all alpha-chars
|
||||
for (int i = 'a'; i < 'z'; i++) {
|
||||
if ((TEST_STRING.indexOf(i) < 0) && (TEST_STRING.indexOf(Character.toUpperCase((char) i)) < 0)) {
|
||||
assertEquals(-1, StringUtil.indexOfIgnoreCase(TEST_STRING, i), TEST_STRING + " seems to contain '" + (char) i + "', at index " + Math.max(TEST_STRING.indexOf(i), TEST_STRING.indexOf(Character.toUpperCase((char) i))));
|
||||
assertEquals(TEST_STRING + " seems to contain '" + (char) i + "', at index " + Math.max(TEST_STRING.indexOf(i), TEST_STRING.indexOf(Character.toUpperCase((char) i))), -1, StringUtil.indexOfIgnoreCase(TEST_STRING, i));
|
||||
}
|
||||
else {
|
||||
assertTrue(0 <= StringUtil.indexOfIgnoreCase(TEST_STRING, i), TEST_STRING + " seems to not contain '" + (char) i + "', at index " + TEST_STRING.indexOf(i));
|
||||
assertTrue(TEST_STRING + " seems to not contain '" + (char) i + "', at index " + TEST_STRING.indexOf(i), 0 <= StringUtil.indexOfIgnoreCase(TEST_STRING, i));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -383,10 +385,10 @@ public class StringUtilTest {
|
||||
// Test all alpha-chars
|
||||
for (int i = 'a'; i < 'z'; i++) {
|
||||
if ((TEST_STRING.indexOf(i) < 0) && (TEST_STRING.indexOf(Character.toUpperCase((char) i)) < 0)) {
|
||||
assertEquals(-1, StringUtil.indexOfIgnoreCase(TEST_STRING, i, 0), TEST_STRING + " seems to contain '" + (char) i + "', at index " + Math.max(TEST_STRING.indexOf(i), TEST_STRING.indexOf(Character.toUpperCase((char) i))));
|
||||
assertEquals(TEST_STRING + " seems to contain '" + (char) i + "', at index " + Math.max(TEST_STRING.indexOf(i), TEST_STRING.indexOf(Character.toUpperCase((char) i))), -1, StringUtil.indexOfIgnoreCase(TEST_STRING, i, 0));
|
||||
}
|
||||
else {
|
||||
assertTrue(0 <= StringUtil.indexOfIgnoreCase(TEST_STRING, i, 0), TEST_STRING + " seems to not contain '" + (char) i + "', at index " + TEST_STRING.indexOf(i));
|
||||
assertTrue(TEST_STRING + " seems to not contain '" + (char) i + "', at index " + TEST_STRING.indexOf(i), 0 <= StringUtil.indexOfIgnoreCase(TEST_STRING, i, 0));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -418,10 +420,10 @@ public class StringUtilTest {
|
||||
// Test all alpha-chars
|
||||
for (int i = 'a'; i < 'z'; i++) {
|
||||
if ((TEST_STRING.indexOf(i) < 0) && (TEST_STRING.indexOf(Character.toUpperCase((char) i)) < 0)) {
|
||||
assertEquals(-1, StringUtil.lastIndexOfIgnoreCase(TEST_STRING, i), TEST_STRING + " seems to contain '" + (char) i + "', at index " + Math.max(TEST_STRING.indexOf(i), TEST_STRING.indexOf(Character.toUpperCase((char) i))));
|
||||
assertEquals(TEST_STRING + " seems to contain '" + (char) i + "', at index " + Math.max(TEST_STRING.indexOf(i), TEST_STRING.indexOf(Character.toUpperCase((char) i))), -1, StringUtil.lastIndexOfIgnoreCase(TEST_STRING, i));
|
||||
}
|
||||
else {
|
||||
assertTrue(0 <= StringUtil.lastIndexOfIgnoreCase(TEST_STRING, i), TEST_STRING + " seems to not contain '" + (char) i + "', at index " + TEST_STRING.indexOf(i));
|
||||
assertTrue(TEST_STRING + " seems to not contain '" + (char) i + "', at index " + TEST_STRING.indexOf(i), 0 <= StringUtil.lastIndexOfIgnoreCase(TEST_STRING, i));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -453,10 +455,10 @@ public class StringUtilTest {
|
||||
// Test all alpha-chars
|
||||
for (int i = 'a'; i < 'z'; i++) {
|
||||
if ((TEST_STRING.indexOf(i) < 0) && (TEST_STRING.indexOf(Character.toUpperCase((char) i)) < 0)) {
|
||||
assertEquals(-1, StringUtil.lastIndexOfIgnoreCase(TEST_STRING, i, TEST_STRING.length()), TEST_STRING + " seems to contain '" + (char) i + "', at index " + Math.max(TEST_STRING.indexOf(i), TEST_STRING.indexOf(Character.toUpperCase((char) i))));
|
||||
assertEquals(TEST_STRING + " seems to contain '" + (char) i + "', at index " + Math.max(TEST_STRING.indexOf(i), TEST_STRING.indexOf(Character.toUpperCase((char) i))), -1, StringUtil.lastIndexOfIgnoreCase(TEST_STRING, i, TEST_STRING.length()));
|
||||
}
|
||||
else {
|
||||
assertTrue(0 <= StringUtil.lastIndexOfIgnoreCase(TEST_STRING, i, TEST_STRING.length()), TEST_STRING + " seems to not contain '" + (char) i + "', at index " + TEST_STRING.indexOf(i));
|
||||
assertTrue(TEST_STRING + " seems to not contain '" + (char) i + "', at index " + TEST_STRING.indexOf(i), 0 <= StringUtil.lastIndexOfIgnoreCase(TEST_STRING, i, TEST_STRING.length()));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -591,8 +593,8 @@ public class StringUtilTest {
|
||||
cal.clear();
|
||||
cal.set(Calendar.HOUR, 1);
|
||||
cal.set(Calendar.MINUTE, 2);
|
||||
format = new SimpleDateFormat("HH:mm");
|
||||
date = StringUtil.toDate("1:02", format);
|
||||
date = StringUtil.toDate("1:02 am",
|
||||
DateFormat.getTimeInstance(DateFormat.SHORT, Locale.US));
|
||||
assertNotNull(date);
|
||||
assertEquals(cal.getTime(), date);
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
|
||||
package com.twelvemonkeys.lang;
|
||||
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.Ignore;
|
||||
|
||||
/**
|
||||
* SystemUtilTest
|
||||
@@ -39,6 +39,6 @@ import org.junit.jupiter.api.Disabled;
|
||||
* @author last modified by $Author: haraldk$
|
||||
* @version $Id: SystemUtilTest.java,v 1.0 11.04.12 16:21 haraldk Exp$
|
||||
*/
|
||||
@Disabled
|
||||
@Ignore
|
||||
public class SystemUtilTest {
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
+137
-91
@@ -45,11 +45,12 @@
|
||||
|
||||
package com.twelvemonkeys.util;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import java.lang.reflect.Array;
|
||||
import java.util.*;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* Abstract test class for {@link java.util.Collection} methods and contracts.
|
||||
@@ -250,8 +251,11 @@ public abstract class CollectionAbstractTest extends ObjectAbstractTest {
|
||||
*/
|
||||
public void verifyAll() {
|
||||
int confirmedSize = confirmed.size();
|
||||
assertEquals(confirmedSize, collection.size(), "Collection size should match confirmed collection's");
|
||||
assertEquals(confirmed.isEmpty(), collection.isEmpty(), "Collection isEmpty() result should match confirmed collection's");
|
||||
assertEquals("Collection size should match confirmed collection's",
|
||||
confirmedSize, collection.size());
|
||||
assertEquals("Collection isEmpty() result should match confirmed " +
|
||||
" collection's",
|
||||
confirmed.isEmpty(), collection.isEmpty());
|
||||
|
||||
// verify the collections are the same by attempting to match each
|
||||
// object in the collection and confirmed collection. To account for
|
||||
@@ -517,8 +521,8 @@ public abstract class CollectionAbstractTest extends ObjectAbstractTest {
|
||||
boolean r = collection.add(elements[i]);
|
||||
confirmed.add(elements[i]);
|
||||
verifyAll();
|
||||
assertTrue(r, "Empty collection changed after add");
|
||||
assertEquals(1, collection.size(), "Collection size is 1 after first add");
|
||||
assertTrue("Empty collection changed after add", r);
|
||||
assertEquals("Collection size is 1 after first add", 1, collection.size());
|
||||
}
|
||||
|
||||
resetEmpty();
|
||||
@@ -528,8 +532,10 @@ public abstract class CollectionAbstractTest extends ObjectAbstractTest {
|
||||
confirmed.add(elements[i]);
|
||||
verifyAll();
|
||||
if (r) size++;
|
||||
assertEquals(size, collection.size(), "Collection size should grow after add");
|
||||
assertTrue(collection.contains(elements[i]), "Collection should contain added element");
|
||||
assertEquals("Collection size should grow after add",
|
||||
size, collection.size());
|
||||
assertTrue("Collection should contain added element",
|
||||
collection.contains(elements[i]));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -546,9 +552,10 @@ public abstract class CollectionAbstractTest extends ObjectAbstractTest {
|
||||
boolean r = collection.addAll(Arrays.asList(elements));
|
||||
confirmed.addAll(Arrays.asList(elements));
|
||||
verifyAll();
|
||||
assertTrue(r, "Empty collection should change after addAll");
|
||||
assertTrue("Empty collection should change after addAll", r);
|
||||
for (int i = 0; i < elements.length; i++) {
|
||||
assertTrue(collection.contains(elements[i]), "Collection should contain added element");
|
||||
assertTrue("Collection should contain added element",
|
||||
collection.contains(elements[i]));
|
||||
}
|
||||
|
||||
resetFull();
|
||||
@@ -557,11 +564,13 @@ public abstract class CollectionAbstractTest extends ObjectAbstractTest {
|
||||
r = collection.addAll(Arrays.asList(elements));
|
||||
confirmed.addAll(Arrays.asList(elements));
|
||||
verifyAll();
|
||||
assertTrue(r, "Full collection should change after addAll");
|
||||
assertTrue("Full collection should change after addAll", r);
|
||||
for (int i = 0; i < elements.length; i++) {
|
||||
assertTrue(collection.contains(elements[i]), "Full collection should contain added element");
|
||||
assertTrue("Full collection should contain added element",
|
||||
collection.contains(elements[i]));
|
||||
}
|
||||
assertEquals(size + elements.length, collection.size(), "Size should increase after addAll");
|
||||
assertEquals("Size should increase after addAll",
|
||||
size + elements.length, collection.size());
|
||||
|
||||
resetFull();
|
||||
size = collection.size();
|
||||
@@ -569,9 +578,11 @@ public abstract class CollectionAbstractTest extends ObjectAbstractTest {
|
||||
confirmed.addAll(Arrays.asList(getFullElements()));
|
||||
verifyAll();
|
||||
if (r) {
|
||||
assertTrue(size < collection.size(), "Size should increase if addAll returns true");
|
||||
assertTrue("Size should increase if addAll returns true",
|
||||
size < collection.size());
|
||||
} else {
|
||||
assertEquals(size, collection.size(), "Size should not change if addAll returns false");
|
||||
assertEquals("Size should not change if addAll returns false",
|
||||
size, collection.size());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -655,14 +666,16 @@ public abstract class CollectionAbstractTest extends ObjectAbstractTest {
|
||||
resetEmpty();
|
||||
elements = getFullElements();
|
||||
for(int i = 0; i < elements.length; i++) {
|
||||
assertTrue(!collection.contains(elements[i]), "Empty collection shouldn't contain element[" + i + "]");
|
||||
assertTrue("Empty collection shouldn't contain element[" + i + "]",
|
||||
!collection.contains(elements[i]));
|
||||
}
|
||||
// make sure calls to "contains" don't change anything
|
||||
verifyAll();
|
||||
|
||||
elements = getOtherElements();
|
||||
for(int i = 0; i < elements.length; i++) {
|
||||
assertTrue(!collection.contains(elements[i]), "Empty collection shouldn't contain element[" + i + "]");
|
||||
assertTrue("Empty collection shouldn't contain element[" + i + "]",
|
||||
!collection.contains(elements[i]));
|
||||
}
|
||||
// make sure calls to "contains" don't change anything
|
||||
verifyAll();
|
||||
@@ -670,7 +683,8 @@ public abstract class CollectionAbstractTest extends ObjectAbstractTest {
|
||||
resetFull();
|
||||
elements = getFullElements();
|
||||
for(int i = 0; i < elements.length; i++) {
|
||||
assertTrue(collection.contains(elements[i]), "Full collection should contain element[" + i + "]");
|
||||
assertTrue("Full collection should contain element[" + i + "]",
|
||||
collection.contains(elements[i]));
|
||||
}
|
||||
// make sure calls to "contains" don't change anything
|
||||
verifyAll();
|
||||
@@ -678,7 +692,8 @@ public abstract class CollectionAbstractTest extends ObjectAbstractTest {
|
||||
resetFull();
|
||||
elements = getOtherElements();
|
||||
for(int i = 0; i < elements.length; i++) {
|
||||
assertTrue(!collection.contains(elements[i]), "Full collection shouldn't contain element");
|
||||
assertTrue("Full collection shouldn't contain element",
|
||||
!collection.contains(elements[i]));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -690,22 +705,22 @@ public abstract class CollectionAbstractTest extends ObjectAbstractTest {
|
||||
public void testCollectionContainsAll() {
|
||||
resetEmpty();
|
||||
Collection col = new HashSet();
|
||||
assertTrue(collection.containsAll(col),
|
||||
"Every Collection should contain all elements of an " +
|
||||
"empty Collection.");
|
||||
assertTrue("Every Collection should contain all elements of an " +
|
||||
"empty Collection.", collection.containsAll(col));
|
||||
col.addAll(Arrays.asList(getOtherElements()));
|
||||
assertTrue(!collection.containsAll(col),
|
||||
"Empty Collection shouldn't contain all elements of " +
|
||||
"a non-empty Collection.");
|
||||
assertTrue("Empty Collection shouldn't contain all elements of " +
|
||||
"a non-empty Collection.", !collection.containsAll(col));
|
||||
// make sure calls to "containsAll" don't change anything
|
||||
verifyAll();
|
||||
|
||||
resetFull();
|
||||
assertTrue(!collection.containsAll(col), "Full collection shouldn't contain other elements");
|
||||
assertTrue("Full collection shouldn't contain other elements",
|
||||
!collection.containsAll(col));
|
||||
|
||||
col.clear();
|
||||
col.addAll(Arrays.asList(getFullElements()));
|
||||
assertTrue(collection.containsAll(col), "Full collection should containAll full elements");
|
||||
assertTrue("Full collection should containAll full elements",
|
||||
collection.containsAll(col));
|
||||
// make sure calls to "containsAll" don't change anything
|
||||
verifyAll();
|
||||
|
||||
@@ -713,17 +728,18 @@ public abstract class CollectionAbstractTest extends ObjectAbstractTest {
|
||||
int max = (getFullElements().length == 1 ? 1 :
|
||||
(getFullElements().length <= 5 ? getFullElements().length - 1 : 5));
|
||||
col = Arrays.asList(getFullElements()).subList(min, max);
|
||||
assertTrue(collection.containsAll(col), "Full collection should containAll partial full " +
|
||||
"elements");
|
||||
assertTrue(collection.containsAll(collection), "Full collection should containAll itself");
|
||||
assertTrue("Full collection should containAll partial full " +
|
||||
"elements", collection.containsAll(col));
|
||||
assertTrue("Full collection should containAll itself",
|
||||
collection.containsAll(collection));
|
||||
// make sure calls to "containsAll" don't change anything
|
||||
verifyAll();
|
||||
|
||||
col = new ArrayList();
|
||||
col.addAll(Arrays.asList(getFullElements()));
|
||||
col.addAll(Arrays.asList(getFullElements()));
|
||||
assertTrue(collection.containsAll(col), "Full collection should containAll duplicate full " +
|
||||
"elements");
|
||||
assertTrue("Full collection should containAll duplicate full " +
|
||||
"elements", collection.containsAll(col));
|
||||
|
||||
// make sure calls to "containsAll" don't change anything
|
||||
verifyAll();
|
||||
@@ -735,12 +751,14 @@ public abstract class CollectionAbstractTest extends ObjectAbstractTest {
|
||||
@Test
|
||||
public void testCollectionIsEmpty() {
|
||||
resetEmpty();
|
||||
assertEquals(true, collection.isEmpty(), "New Collection should be empty.");
|
||||
assertEquals("New Collection should be empty.",
|
||||
true, collection.isEmpty());
|
||||
// make sure calls to "isEmpty() don't change anything
|
||||
verifyAll();
|
||||
|
||||
resetFull();
|
||||
assertEquals(false, collection.isEmpty(), "Full collection shouldn't be empty");
|
||||
assertEquals("Full collection shouldn't be empty",
|
||||
false, collection.isEmpty());
|
||||
// make sure calls to "isEmpty() don't change anything
|
||||
verifyAll();
|
||||
}
|
||||
@@ -753,7 +771,8 @@ public abstract class CollectionAbstractTest extends ObjectAbstractTest {
|
||||
public void testCollectionIterator() {
|
||||
resetEmpty();
|
||||
Iterator it1 = collection.iterator();
|
||||
assertEquals(false, it1.hasNext(), "Iterator for empty Collection shouldn't have next.");
|
||||
assertEquals("Iterator for empty Collection shouldn't have next.",
|
||||
false, it1.hasNext());
|
||||
try {
|
||||
it1.next();
|
||||
fail("Iterator at end of Collection should throw " +
|
||||
@@ -767,17 +786,18 @@ public abstract class CollectionAbstractTest extends ObjectAbstractTest {
|
||||
resetFull();
|
||||
it1 = collection.iterator();
|
||||
for (int i = 0; i < collection.size(); i++) {
|
||||
assertTrue(it1.hasNext(), "Iterator for full collection should haveNext");
|
||||
assertTrue("Iterator for full collection should haveNext",
|
||||
it1.hasNext());
|
||||
it1.next();
|
||||
}
|
||||
assertTrue(!it1.hasNext(), "Iterator should be finished");
|
||||
assertTrue("Iterator should be finished", !it1.hasNext());
|
||||
|
||||
ArrayList list = new ArrayList();
|
||||
it1 = collection.iterator();
|
||||
for (int i = 0; i < collection.size(); i++) {
|
||||
Object next = it1.next();
|
||||
assertTrue(collection.contains(next), "Collection should contain element returned by " +
|
||||
"its iterator");
|
||||
assertTrue("Collection should contain element returned by " +
|
||||
"its iterator", collection.contains(next));
|
||||
list.add(next);
|
||||
}
|
||||
try {
|
||||
@@ -845,10 +865,11 @@ public abstract class CollectionAbstractTest extends ObjectAbstractTest {
|
||||
}
|
||||
|
||||
size--;
|
||||
assertEquals(size, collection.size(), "Collection should shrink by one after " +
|
||||
"iterator.remove");
|
||||
assertEquals("Collection should shrink by one after " +
|
||||
"iterator.remove", size, collection.size());
|
||||
}
|
||||
assertTrue(collection.isEmpty(), "Collection should be empty after iterator purge");
|
||||
assertTrue("Collection should be empty after iterator purge",
|
||||
collection.isEmpty());
|
||||
|
||||
resetFull();
|
||||
iter = collection.iterator();
|
||||
@@ -873,7 +894,8 @@ public abstract class CollectionAbstractTest extends ObjectAbstractTest {
|
||||
resetEmpty();
|
||||
Object[] elements = getFullElements();
|
||||
for (int i = 0; i < elements.length; i++) {
|
||||
assertTrue(!collection.remove(elements[i]), "Shouldn't remove nonexistent element");
|
||||
assertTrue("Shouldn't remove nonexistent element",
|
||||
!collection.remove(elements[i]));
|
||||
verifyAll();
|
||||
}
|
||||
|
||||
@@ -881,14 +903,16 @@ public abstract class CollectionAbstractTest extends ObjectAbstractTest {
|
||||
|
||||
resetFull();
|
||||
for (int i = 0; i < other.length; i++) {
|
||||
assertTrue(!collection.remove(other[i]), "Shouldn't remove nonexistent other element");
|
||||
assertTrue("Shouldn't remove nonexistent other element",
|
||||
!collection.remove(other[i]));
|
||||
verifyAll();
|
||||
}
|
||||
|
||||
int size = collection.size();
|
||||
for (int i = 0; i < elements.length; i++) {
|
||||
resetFull();
|
||||
assertTrue(collection.remove(elements[i]), "Collection should remove extant element: " + elements[i]);
|
||||
assertTrue("Collection should remove extant element: " + elements[i],
|
||||
collection.remove(elements[i]));
|
||||
|
||||
// if the elements aren't distinguishable, we can just remove a
|
||||
// matching element from the confirmed collection and verify
|
||||
@@ -903,7 +927,8 @@ public abstract class CollectionAbstractTest extends ObjectAbstractTest {
|
||||
verifyAll();
|
||||
}
|
||||
|
||||
assertEquals(size - 1, collection.size(), "Collection should shrink after remove");
|
||||
assertEquals("Collection should shrink after remove",
|
||||
size - 1, collection.size());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -916,28 +941,28 @@ public abstract class CollectionAbstractTest extends ObjectAbstractTest {
|
||||
if (!isRemoveSupported()) return;
|
||||
|
||||
resetEmpty();
|
||||
assertTrue(!collection.removeAll(Collections.EMPTY_SET),
|
||||
"Emtpy collection removeAll should return false for " +
|
||||
"empty input");
|
||||
assertTrue("Emtpy collection removeAll should return false for " +
|
||||
"empty input",
|
||||
!collection.removeAll(Collections.EMPTY_SET));
|
||||
verifyAll();
|
||||
|
||||
assertTrue(!collection.removeAll(new ArrayList(collection)),
|
||||
"Emtpy collection removeAll should return false for " +
|
||||
"nonempty input");
|
||||
assertTrue("Emtpy collection removeAll should return false for " +
|
||||
"nonempty input",
|
||||
!collection.removeAll(new ArrayList(collection)));
|
||||
verifyAll();
|
||||
|
||||
resetFull();
|
||||
assertTrue(!collection.removeAll(Collections.EMPTY_SET),
|
||||
"Full collection removeAll should return false for " +
|
||||
"empty input");
|
||||
assertTrue("Full collection removeAll should return false for " +
|
||||
"empty input",
|
||||
!collection.removeAll(Collections.EMPTY_SET));
|
||||
verifyAll();
|
||||
|
||||
assertTrue(!collection.removeAll(Arrays.asList(getOtherElements())),
|
||||
"Full collection removeAll should return false for other elements");
|
||||
assertTrue("Full collection removeAll should return false for other elements",
|
||||
!collection.removeAll(Arrays.asList(getOtherElements())));
|
||||
verifyAll();
|
||||
|
||||
assertTrue(collection.removeAll(new HashSet(collection)),
|
||||
"Full collection removeAll should return true for full elements");
|
||||
assertTrue("Full collection removeAll should return true for full elements",
|
||||
collection.removeAll(new HashSet(collection)));
|
||||
confirmed.removeAll(new HashSet(confirmed));
|
||||
verifyAll();
|
||||
|
||||
@@ -947,14 +972,17 @@ public abstract class CollectionAbstractTest extends ObjectAbstractTest {
|
||||
int max = (getFullElements().length == 1 ? 1 :
|
||||
(getFullElements().length <= 5 ? getFullElements().length - 1 : 5));
|
||||
Collection all = Arrays.asList(getFullElements()).subList(min, max);
|
||||
assertTrue(collection.removeAll(all), "Full collection removeAll should work");
|
||||
assertTrue("Full collection removeAll should work",
|
||||
collection.removeAll(all));
|
||||
confirmed.removeAll(all);
|
||||
verifyAll();
|
||||
|
||||
assertTrue(collection.size() < size, "Collection should shrink after removeAll");
|
||||
assertTrue("Collection should shrink after removeAll",
|
||||
collection.size() < size);
|
||||
Iterator iter = all.iterator();
|
||||
while (iter.hasNext()) {
|
||||
assertTrue(!collection.contains(iter.next()), "Collection shouldn't contain removed element");
|
||||
assertTrue("Collection shouldn't contain removed element",
|
||||
!collection.contains(iter.next()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -970,51 +998,59 @@ public abstract class CollectionAbstractTest extends ObjectAbstractTest {
|
||||
List elements = Arrays.asList(getFullElements());
|
||||
List other = Arrays.asList(getOtherElements());
|
||||
|
||||
assertTrue(!collection.retainAll(Collections.EMPTY_SET), "Empty retainAll() should return false");
|
||||
assertTrue("Empty retainAll() should return false",
|
||||
!collection.retainAll(Collections.EMPTY_SET));
|
||||
verifyAll();
|
||||
|
||||
assertTrue(!collection.retainAll(elements), "Empty retainAll() should return false");
|
||||
assertTrue("Empty retainAll() should return false",
|
||||
!collection.retainAll(elements));
|
||||
verifyAll();
|
||||
|
||||
resetFull();
|
||||
assertTrue(collection.retainAll(Collections.EMPTY_SET), "Collection should change from retainAll empty");
|
||||
assertTrue("Collection should change from retainAll empty",
|
||||
collection.retainAll(Collections.EMPTY_SET));
|
||||
confirmed.retainAll(Collections.EMPTY_SET);
|
||||
verifyAll();
|
||||
|
||||
resetFull();
|
||||
assertTrue(collection.retainAll(other), "Collection changed from retainAll other");
|
||||
assertTrue("Collection changed from retainAll other",
|
||||
collection.retainAll(other));
|
||||
confirmed.retainAll(other);
|
||||
verifyAll();
|
||||
|
||||
resetFull();
|
||||
int size = collection.size();
|
||||
assertTrue(!collection.retainAll(elements), "Collection shouldn't change from retainAll elements");
|
||||
assertTrue("Collection shouldn't change from retainAll elements",
|
||||
!collection.retainAll(elements));
|
||||
verifyAll();
|
||||
assertEquals(size, collection.size(), "Collection size shouldn't change");
|
||||
assertEquals("Collection size shouldn't change", size,
|
||||
collection.size());
|
||||
|
||||
if (getFullElements().length > 1) {
|
||||
resetFull();
|
||||
size = collection.size();
|
||||
int min = (getFullElements().length < 2 ? 0 : 2);
|
||||
int max = (getFullElements().length <= 5 ? getFullElements().length - 1 : 5);
|
||||
assertTrue(collection.retainAll(elements.subList(min, max)), "Collection should changed by partial retainAll");
|
||||
assertTrue("Collection should changed by partial retainAll",
|
||||
collection.retainAll(elements.subList(min, max)));
|
||||
confirmed.retainAll(elements.subList(min, max));
|
||||
verifyAll();
|
||||
|
||||
Iterator iter = collection.iterator();
|
||||
while (iter.hasNext()) {
|
||||
assertTrue(elements.subList(min, max).contains(iter.next()), "Collection only contains retained element");
|
||||
assertTrue("Collection only contains retained element",
|
||||
elements.subList(min, max).contains(iter.next()));
|
||||
}
|
||||
}
|
||||
|
||||
resetFull();
|
||||
HashSet set = new HashSet(elements);
|
||||
size = collection.size();
|
||||
assertTrue(!collection.retainAll(set),
|
||||
"Collection shouldn't change from retainAll without duplicate elements");
|
||||
assertTrue("Collection shouldn't change from retainAll without " +
|
||||
"duplicate elements", !collection.retainAll(set));
|
||||
verifyAll();
|
||||
assertEquals( size, collection.size(),
|
||||
"Collection size didn't change from nonduplicate retainAll");
|
||||
assertEquals("Collection size didn't change from nonduplicate " +
|
||||
"retainAll", size, collection.size());
|
||||
}
|
||||
|
||||
|
||||
@@ -1024,10 +1060,11 @@ public abstract class CollectionAbstractTest extends ObjectAbstractTest {
|
||||
@Test
|
||||
public void testCollectionSize() {
|
||||
resetEmpty();
|
||||
assertEquals(0, collection.size(), "Size of new Collection is 0.");
|
||||
assertEquals("Size of new Collection is 0.", 0, collection.size());
|
||||
|
||||
resetFull();
|
||||
assertTrue(collection.size() > 0, "Size of full collection should be greater than zero");
|
||||
assertTrue("Size of full collection should be greater than zero",
|
||||
collection.size() > 0);
|
||||
}
|
||||
|
||||
|
||||
@@ -1036,18 +1073,22 @@ public abstract class CollectionAbstractTest extends ObjectAbstractTest {
|
||||
*/
|
||||
public void testCollectionToArray() {
|
||||
resetEmpty();
|
||||
assertEquals(0, collection.toArray().length, "Empty Collection should return empty array for toArray");
|
||||
assertEquals("Empty Collection should return empty array for toArray",
|
||||
0, collection.toArray().length);
|
||||
|
||||
resetFull();
|
||||
Object[] array = collection.toArray();
|
||||
assertEquals(array.length, collection.size(), "Full collection toArray should be same size as collection");
|
||||
assertEquals("Full collection toArray should be same size as " +
|
||||
"collection", array.length, collection.size());
|
||||
Object[] confirmedArray = confirmed.toArray();
|
||||
assertEquals(confirmedArray.length, array.length,
|
||||
"length of array from confirmed collection should match the length of the collection's array");
|
||||
assertEquals("length of array from confirmed collection should " +
|
||||
"match the length of the collection's array",
|
||||
confirmedArray.length, array.length);
|
||||
boolean[] matched = new boolean[array.length];
|
||||
|
||||
for (int i = 0; i < array.length; i++) {
|
||||
assertTrue(collection.contains(array[i]), "Collection should contain element in toArray");
|
||||
assertTrue("Collection should contain element in toArray",
|
||||
collection.contains(array[i]));
|
||||
|
||||
boolean match = false;
|
||||
// find a match in the confirmed array
|
||||
@@ -1067,7 +1108,8 @@ public abstract class CollectionAbstractTest extends ObjectAbstractTest {
|
||||
}
|
||||
}
|
||||
for(int i = 0; i < matched.length; i++) {
|
||||
assertEquals(true, matched[i], "Collection should return all its elements in toArray");
|
||||
assertEquals("Collection should return all its elements in " +
|
||||
"toArray", true, matched[i]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1081,8 +1123,8 @@ public abstract class CollectionAbstractTest extends ObjectAbstractTest {
|
||||
resetEmpty();
|
||||
Object[] a = new Object[] { new Object(), null, null };
|
||||
Object[] array = collection.toArray(a);
|
||||
assertArrayEquals(array, a, "Given array shouldn't shrink");
|
||||
assertNull(a[0], "Last element should be set to null");
|
||||
assertArrayEquals("Given array shouldn't shrink", array, a);
|
||||
assertNull("Last element should be set to null", a[0]);
|
||||
verifyAll();
|
||||
|
||||
resetFull();
|
||||
@@ -1104,7 +1146,8 @@ public abstract class CollectionAbstractTest extends ObjectAbstractTest {
|
||||
|
||||
array = collection.toArray(new Object[0]);
|
||||
a = collection.toArray();
|
||||
assertEquals(Arrays.asList(array), Arrays.asList(a), "toArrays should be equal");
|
||||
assertEquals("toArrays should be equal",
|
||||
Arrays.asList(array), Arrays.asList(a));
|
||||
|
||||
// Figure out if they're all the same class
|
||||
// TODO: It'd be nicer to detect a common superclass
|
||||
@@ -1120,10 +1163,11 @@ public abstract class CollectionAbstractTest extends ObjectAbstractTest {
|
||||
}
|
||||
a = (Object[])Array.newInstance(cl, 0);
|
||||
array = collection.toArray(a);
|
||||
assertEquals(a.getClass(), array.getClass(), "toArray(Object[]) should return correct array type");
|
||||
assertEquals(Arrays.asList(array),
|
||||
Arrays.asList(collection.toArray()),
|
||||
"type-specific toArrays should be equal");
|
||||
assertEquals("toArray(Object[]) should return correct array type",
|
||||
a.getClass(), array.getClass());
|
||||
assertEquals("type-specific toArrays should be equal",
|
||||
Arrays.asList(array),
|
||||
Arrays.asList(collection.toArray()));
|
||||
verifyAll();
|
||||
}
|
||||
|
||||
@@ -1134,10 +1178,12 @@ public abstract class CollectionAbstractTest extends ObjectAbstractTest {
|
||||
@Test
|
||||
public void testCollectionToString() {
|
||||
resetEmpty();
|
||||
assertTrue(collection.toString() != null, "toString shouldn't return null");
|
||||
assertTrue("toString shouldn't return null",
|
||||
collection.toString() != null);
|
||||
|
||||
resetFull();
|
||||
assertTrue(collection.toString() != null, "toString shouldn't return null");
|
||||
assertTrue("toString shouldn't return null",
|
||||
collection.toString() != null);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -30,11 +30,13 @@
|
||||
|
||||
package com.twelvemonkeys.util;
|
||||
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* CollectionUtilTest
|
||||
*
|
||||
@@ -59,60 +61,44 @@ public class CollectionUtilTest {
|
||||
assertArrayEquals(new Object[] {"bar", "baz", 3}, merged);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Test(expected = IndexOutOfBoundsException.class)
|
||||
public void testMergeArraysObjectBadOffset() {
|
||||
assertThrows(IndexOutOfBoundsException.class, () -> {
|
||||
CollectionUtil.mergeArrays(stringObjects, 4, 2, integerObjects, 2, 1);
|
||||
});
|
||||
CollectionUtil.mergeArrays(stringObjects, 4, 2, integerObjects, 2, 1);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Test(expected = IndexOutOfBoundsException.class)
|
||||
public void testMergeArraysObjectBadSecondOffset() {
|
||||
assertThrows(IndexOutOfBoundsException.class, () -> {
|
||||
CollectionUtil.mergeArrays(stringObjects, 1, 2, integerObjects, 4, 1);
|
||||
});
|
||||
CollectionUtil.mergeArrays(stringObjects, 1, 2, integerObjects, 4, 1);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Test(expected = IndexOutOfBoundsException.class)
|
||||
public void testMergeArraysObjectBadLength() {
|
||||
assertThrows(IndexOutOfBoundsException.class, () -> {
|
||||
CollectionUtil.mergeArrays(stringObjects, 1, 4, integerObjects, 2, 1);
|
||||
});
|
||||
CollectionUtil.mergeArrays(stringObjects, 1, 4, integerObjects, 2, 1);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Test(expected = IndexOutOfBoundsException.class)
|
||||
public void testMergeArraysObjectBadSecondLength() {
|
||||
assertThrows(IndexOutOfBoundsException.class, () -> {
|
||||
CollectionUtil.mergeArrays(stringObjects, 1, 2, integerObjects, 2, 2);
|
||||
});
|
||||
CollectionUtil.mergeArrays(stringObjects, 1, 2, integerObjects, 2, 2);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Test(expected = IndexOutOfBoundsException.class)
|
||||
public void testMergeArraysObjectNegativeOffset() {
|
||||
assertThrows(IndexOutOfBoundsException.class, () -> {
|
||||
CollectionUtil.mergeArrays(stringObjects, -1, 2, integerObjects, 2, 1);
|
||||
});
|
||||
CollectionUtil.mergeArrays(stringObjects, -1, 2, integerObjects, 2, 1);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Test(expected = IndexOutOfBoundsException.class)
|
||||
public void testMergeArraysObjectNegativeSecondOffset() {
|
||||
assertThrows(IndexOutOfBoundsException.class, () -> {
|
||||
CollectionUtil.mergeArrays(stringObjects, 1, 2, integerObjects, -1, 1);
|
||||
});
|
||||
CollectionUtil.mergeArrays(stringObjects, 1, 2, integerObjects, -1, 1);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Test(expected = IndexOutOfBoundsException.class)
|
||||
public void testMergeArraysObjectNegativeLength() {
|
||||
assertThrows(IndexOutOfBoundsException.class, () -> {
|
||||
CollectionUtil.mergeArrays(stringObjects, 1, -1, integerObjects, 2, 1);
|
||||
});
|
||||
CollectionUtil.mergeArrays(stringObjects, 1, -1, integerObjects, 2, 1);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Test(expected = IndexOutOfBoundsException.class)
|
||||
public void testMergeArraysObjectNegativeSecondLength() {
|
||||
assertThrows(IndexOutOfBoundsException.class, () -> {
|
||||
CollectionUtil.mergeArrays(stringObjects, 1, 2, integerObjects, 2, -1);
|
||||
});
|
||||
CollectionUtil.mergeArrays(stringObjects, 1, 2, integerObjects, 2, -1);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -123,24 +109,20 @@ public class CollectionUtilTest {
|
||||
assertArrayEquals(new Object[] {"foo", "bar", "baz", 1, 2, 3}, merged);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Test(expected = ArrayStoreException.class)
|
||||
public void testMergeArraysObjectIllegalType() {
|
||||
String[] strings = {"foo", "bar", "baz"};
|
||||
Integer[] integers = {1, 2, 3}; // Integer not assignable to String
|
||||
|
||||
assertThrows(ArrayStoreException.class, () -> {
|
||||
CollectionUtil.mergeArrays(strings, integers);
|
||||
});
|
||||
CollectionUtil.mergeArrays(strings, integers);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Test(expected = ArrayStoreException.class)
|
||||
public void testMergeArraysNativeIllegalType() {
|
||||
char[] chars = {'a', 'b', 'c'};
|
||||
int[] integers = {1, 2, 3}; // Integer not assignable to String
|
||||
|
||||
assertThrows(ArrayStoreException.class, () -> {
|
||||
CollectionUtil.mergeArrays(chars, integers);
|
||||
});
|
||||
CollectionUtil.mergeArrays(chars, integers);
|
||||
|
||||
}
|
||||
|
||||
@@ -165,11 +147,9 @@ public class CollectionUtilTest {
|
||||
assertArrayEquals(new int[] {2, 3, 4}, numbers);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testEnumIteratorNull() {
|
||||
assertThrows(IllegalArgumentException.class, () -> {
|
||||
CollectionUtil.iterator((Enumeration<Object>) null);
|
||||
});
|
||||
CollectionUtil.iterator((Enumeration<Object>) null);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -203,11 +183,9 @@ public class CollectionUtilTest {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testArrayIteratorNull() {
|
||||
assertThrows(IllegalArgumentException.class, () -> {
|
||||
CollectionUtil.iterator((Object[]) null);
|
||||
});
|
||||
CollectionUtil.iterator((Object[]) null);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -284,7 +262,7 @@ public class CollectionUtilTest {
|
||||
|
||||
int count = 0;
|
||||
for (Object element : elements) {
|
||||
assertTrue(iterator.hasNext(), "No next element for element '" + element + "' at index: " + count);
|
||||
assertTrue("No next element for element '" + element + "' at index: " + count, iterator.hasNext());
|
||||
assertEquals(count > 0, iterator.hasPrevious());
|
||||
assertEquals(count, iterator.nextIndex());
|
||||
assertEquals(count - 1, iterator.previousIndex());
|
||||
@@ -340,7 +318,7 @@ public class CollectionUtilTest {
|
||||
assertEquals(elements.length, iterator.nextIndex());
|
||||
|
||||
for (int i = count; i > 0; i--) {
|
||||
assertTrue(iterator.hasPrevious(), "No previous element for element '" + elements[i - 1] + "' at index: " + (i - 1));
|
||||
assertTrue("No previous element for element '" + elements[i - 1] + "' at index: " + (i - 1), iterator.hasPrevious());
|
||||
assertEquals(i < elements.length, iterator.hasNext());
|
||||
assertEquals(i - 1, iterator.previousIndex());
|
||||
assertEquals(i, iterator.nextIndex());
|
||||
@@ -361,24 +339,18 @@ public class CollectionUtilTest {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testArrayIteratorRangeNull() {
|
||||
assertThrows(IllegalArgumentException.class, () -> {
|
||||
CollectionUtil.iterator(null, 0, 0);
|
||||
});
|
||||
CollectionUtil.iterator(null, 0, 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testArrayIteratorRangeBadStart() {
|
||||
assertThrows(IllegalArgumentException.class, () -> {
|
||||
CollectionUtil.iterator(stringObjects, stringObjects.length + 1, 2);
|
||||
});
|
||||
CollectionUtil.iterator(stringObjects, stringObjects.length + 1, 2);
|
||||
}
|
||||
@Test
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testArrayIteratorRangeBadLength() {
|
||||
assertThrows(IllegalArgumentException.class, () -> {
|
||||
CollectionUtil.iterator(stringObjects, 1, stringObjects.length);
|
||||
});
|
||||
CollectionUtil.iterator(stringObjects, 1, stringObjects.length);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -407,11 +379,9 @@ public class CollectionUtilTest {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testReverseOrderNull() {
|
||||
assertThrows(IllegalArgumentException.class, () -> {
|
||||
CollectionUtil.reverseOrder(null);
|
||||
});
|
||||
CollectionUtil.reverseOrder(null);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -461,7 +431,7 @@ public class CollectionUtilTest {
|
||||
}
|
||||
}
|
||||
|
||||
@Disabled("For development only")
|
||||
@Ignore("For development only")
|
||||
@Test
|
||||
@SuppressWarnings({"UnusedDeclaration"})
|
||||
public void testGenerify() {
|
||||
|
||||
@@ -45,10 +45,11 @@
|
||||
|
||||
package com.twelvemonkeys.util;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import org.junit.jupiter.api.*;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
/**
|
||||
* Tests LRUMap.
|
||||
@@ -80,8 +81,8 @@ public class LRUMapTest extends LinkedMapTest {
|
||||
map2.put(4,"foo"); // removes 1 since max size exceeded
|
||||
map2.removeLRU(); // should be Integer(2)
|
||||
|
||||
assertTrue(map2.get(new Integer(3)).equals("foo"), "Second to last value should exist");
|
||||
assertTrue(map2.get(new Integer(1)) == null, "First value inserted should not exist");
|
||||
assertTrue("Second to last value should exist",map2.get(new Integer(3)).equals("foo"));
|
||||
assertTrue("First value inserted should not exist", map2.get(new Integer(1)) == null);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -92,8 +93,8 @@ public class LRUMapTest extends LinkedMapTest {
|
||||
map2.put(3,"foo");
|
||||
map2.put(4,"bar");
|
||||
|
||||
assertTrue(map2.get(new Integer(4)).equals("bar"), "last value should exist");
|
||||
assertTrue(map2.get(new Integer(1)) == null, "LRU should not exist");
|
||||
assertTrue("last value should exist",map2.get(new Integer(4)).equals("bar"));
|
||||
assertTrue("LRU should not exist", map2.get(new Integer(1)) == null);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -112,8 +113,10 @@ public class LRUMapTest extends LinkedMapTest {
|
||||
|
||||
map2.putAll(hashMap);
|
||||
|
||||
assertTrue(map2.size() == 3, "max size is 3, but actual size is " + map2.size());
|
||||
assertTrue(map2.containsKey(new Integer(4)), "map should contain the Integer(4) object");
|
||||
assertTrue("max size is 3, but actual size is " + map2.size(),
|
||||
map2.size() == 3);
|
||||
assertTrue("map should contain the Integer(4) object",
|
||||
map2.containsKey(new Integer(4)));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -131,7 +134,8 @@ public class LRUMapTest extends LinkedMapTest {
|
||||
map.put("6","6");
|
||||
map.setMaxSize(3);
|
||||
|
||||
assertTrue(map.size() == 3, "map should have size = 3, but actually = " + map.size());
|
||||
assertTrue("map should have size = 3, but actually = " + map.size(),
|
||||
map.size() == 3);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -156,9 +160,9 @@ public class LRUMapTest extends LinkedMapTest {
|
||||
keys[i] = keyIterator.next();
|
||||
}
|
||||
|
||||
assertTrue(keys[0].equals("3"), "first evicted should be 3, was " + keys[0]);
|
||||
assertTrue(keys[1].equals("1"), "second evicted should be 1, was " + keys[1]);
|
||||
assertTrue(keys[2].equals("4"), "third evicted should be 4, was " + keys[2]);
|
||||
assertTrue("first evicted should be 3, was " + keys[0], keys[0].equals("3"));
|
||||
assertTrue("second evicted should be 1, was " + keys[1], keys[1].equals("1"));
|
||||
assertTrue("third evicted should be 4, was " + keys[2], keys[2].equals("4"));
|
||||
|
||||
}
|
||||
|
||||
@@ -188,12 +192,13 @@ public class LRUMapTest extends LinkedMapTest {
|
||||
// 4 2
|
||||
counter.remove("5");
|
||||
|
||||
assertTrue(counter.size() == 2, "size should be 2, but was " + counter.size());
|
||||
assertTrue(counter.removedCount == 3, "removedCount should be 3 but was " + counter.removedCount);
|
||||
assertTrue("size should be 2, but was " + counter.size(), counter.size() == 2);
|
||||
assertTrue("removedCount should be 3 but was " + counter.removedCount,
|
||||
counter.removedCount == 3);
|
||||
|
||||
assertTrue(counter.list.get(0).equals("2"), "first removed was '2'");
|
||||
assertTrue(counter.list.get(1).equals("3"), "second removed was '3'");
|
||||
assertTrue(counter.list.get(2).equals("1"), "third removed was '1'");
|
||||
assertTrue("first removed was '2'",counter.list.get(0).equals("2"));
|
||||
assertTrue("second removed was '3'",counter.list.get(1).equals("3"));
|
||||
assertTrue("third removed was '1'",counter.list.get(2).equals("1"));
|
||||
|
||||
//assertTrue("oldest key is '4'",counter.get(0).equals("4"));
|
||||
//assertTrue("newest key is '2'",counter.get(1).equals("2"));
|
||||
|
||||
@@ -45,11 +45,15 @@
|
||||
|
||||
package com.twelvemonkeys.util;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.jupiter.api.*;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
/**
|
||||
* Unit tests
|
||||
@@ -70,7 +74,7 @@ public class LinkedMapTest extends MapAbstractTest {
|
||||
*/
|
||||
protected LinkedMap labRat;
|
||||
|
||||
@BeforeEach
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
// use makeMap and cast the result to a SeqHashMap
|
||||
// so that subclasses of SeqHashMap can share these tests
|
||||
@@ -99,21 +103,27 @@ public class LinkedMapTest extends MapAbstractTest {
|
||||
}
|
||||
|
||||
// Test size().
|
||||
assertEquals(expectedSize, labRat.size(), "size() does not match expected size");
|
||||
assertEquals("size() does not match expected size",
|
||||
expectedSize, labRat.size());
|
||||
|
||||
// Test clone(), iterator(), and get(Object).
|
||||
LinkedMap clone = (LinkedMap) labRat.clone();
|
||||
assertEquals(labRat.size(), clone.size(), "Size of clone does not match original");
|
||||
assertEquals("Size of clone does not match original",
|
||||
labRat.size(), clone.size());
|
||||
Iterator origEntries = labRat.entrySet().iterator();
|
||||
Iterator copiedEntries = clone.entrySet().iterator();
|
||||
while (origEntries.hasNext()) {
|
||||
Map.Entry origEntry = (Map.Entry)origEntries.next();
|
||||
Map.Entry copiedEntry = (Map.Entry)copiedEntries.next();
|
||||
assertEquals(origEntry.getKey(), copiedEntry.getKey(), "Cloned key does not match original");
|
||||
assertEquals(origEntry.getValue(), copiedEntry.getValue(), "Cloned value does not match original");
|
||||
assertEquals(origEntry, copiedEntry, "Cloned entry does not match original");
|
||||
assertEquals("Cloned key does not match original",
|
||||
origEntry.getKey(), copiedEntry.getKey());
|
||||
assertEquals("Cloned value does not match original",
|
||||
origEntry.getValue(), copiedEntry.getValue());
|
||||
assertEquals("Cloned entry does not match original",
|
||||
origEntry, copiedEntry);
|
||||
}
|
||||
assertTrue(!copiedEntries.hasNext(), "iterator() returned different number of elements than keys()");
|
||||
assertTrue("iterator() returned different number of elements than keys()",
|
||||
!copiedEntries.hasNext());
|
||||
|
||||
// Test sequence()
|
||||
/*
|
||||
@@ -197,7 +207,7 @@ public class LinkedMapTest extends MapAbstractTest {
|
||||
}
|
||||
*/
|
||||
|
||||
@AfterEach
|
||||
@After
|
||||
public void tearDown() throws Exception {
|
||||
labRat = null;
|
||||
}
|
||||
|
||||
@@ -45,10 +45,12 @@
|
||||
|
||||
package com.twelvemonkeys.util;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import org.junit.jupiter.api.*;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* Abstract test class for {@link java.util.Map} methods and contracts.
|
||||
@@ -388,19 +390,19 @@ public abstract class MapAbstractTest extends ObjectAbstractTest {
|
||||
m.put(keys[i], values[i]);
|
||||
}
|
||||
catch (NullPointerException exception) {
|
||||
assertTrue(keys[i] == null || values[i] == null,
|
||||
"NullPointerException only allowed to be thrown if either the key or value is null.");
|
||||
assertTrue("NullPointerException only allowed to be thrown if either the key or value is null.",
|
||||
keys[i] == null || values[i] == null);
|
||||
|
||||
assertTrue(keys[i] == null || !isAllowNullKey(),
|
||||
"NullPointerException on null key, but isAllowNullKey is not overridden to return false.");
|
||||
assertTrue("NullPointerException on null key, but isAllowNullKey is not overridden to return false.",
|
||||
keys[i] == null || !isAllowNullKey());
|
||||
|
||||
assertTrue(values[i] == null || !isAllowNullValue(),
|
||||
"NullPointerException on null value, but isAllowNullValue is not overridden to return false.");
|
||||
assertTrue("NullPointerException on null value, but isAllowNullValue is not overridden to return false.",
|
||||
values[i] == null || !isAllowNullValue());
|
||||
|
||||
fail("Unknown reason for NullPointer.");
|
||||
assertTrue("Unknown reason for NullPointer.", false);
|
||||
}
|
||||
}
|
||||
assertEquals(keys.length, m.size(), "size must reflect number of mappings added.");
|
||||
assertEquals("size must reflect number of mappings added.", keys.length, m.size());
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
@@ -479,26 +481,27 @@ public abstract class MapAbstractTest extends ObjectAbstractTest {
|
||||
Object[] values = getSampleValues();
|
||||
Object[] newValues = getNewSampleValues();
|
||||
|
||||
assertTrue(keys != null, "failure in test: Must have keys returned from getSampleKeys.");
|
||||
assertTrue(values != null, "failure in test: Must have values returned from getSampleValues.");
|
||||
assertTrue("failure in test: Must have keys returned from getSampleKeys.", keys != null);
|
||||
assertTrue("failure in test: Must have values returned from getSampleValues.", values != null);
|
||||
|
||||
// verify keys and values have equivalent lengths (in case getSampleX are
|
||||
// overridden)
|
||||
assertEquals(keys.length, values.length, "failure in test: not the same number of sample keys and values.");
|
||||
assertEquals(values.length, newValues.length, "failure in test: not the same number of values and new values.");
|
||||
assertEquals("failure in test: not the same number of sample keys and values.", keys.length, values.length);
|
||||
assertEquals("failure in test: not the same number of values and new values.", values.length, newValues.length);
|
||||
|
||||
// verify there aren't duplicate keys, and check values
|
||||
for (int i = 0; i < keys.length - 1; i++) {
|
||||
for (int j = i + 1; j < keys.length; j++) {
|
||||
assertTrue((keys[i] != null || keys[j] != null), "failure in test: duplicate null keys.");
|
||||
assertTrue((keys[i] == null || keys[j] == null || (!keys[i].equals(keys[j]) && !keys[j].equals(keys[i]))),
|
||||
"failure in test: duplicate non-null key.");
|
||||
assertTrue("failure in test: duplicate null keys.", (keys[i] != null || keys[j] != null));
|
||||
assertTrue("failure in test: duplicate non-null key.",
|
||||
(keys[i] == null || keys[j] == null || (!keys[i].equals(keys[j]) && !keys[j].equals(keys[i]))));
|
||||
}
|
||||
|
||||
assertTrue(keys[i] != null || isAllowNullKey(),"failure in test: found null key, but isNullKeySupported is false.");
|
||||
assertTrue(values[i] != null || isAllowNullValue(),"failure in test: found null value, but isNullValueSupported is false.");
|
||||
assertTrue(newValues[i] != null || isAllowNullValue(), "failure in test: found null new value, but isNullValueSupported is false.");
|
||||
assertTrue(values[i] != newValues[i] && (values[i] == null || !values[i].equals(newValues[i])), "failure in test: values should not be the same as new value");
|
||||
assertTrue("failure in test: found null key, but isNullKeySupported is false.", keys[i] != null || isAllowNullKey());
|
||||
assertTrue("failure in test: found null value, but isNullValueSupported is false.", values[i] != null || isAllowNullValue());
|
||||
assertTrue("failure in test: found null new value, but isNullValueSupported is false.", newValues[i] != null || isAllowNullValue());
|
||||
assertTrue("failure in test: values should not be the same as new value",
|
||||
values[i] != newValues[i] && (values[i] == null || !values[i].equals(newValues[i])));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -514,18 +517,18 @@ public abstract class MapAbstractTest extends ObjectAbstractTest {
|
||||
@Test
|
||||
public void testMakeMap() {
|
||||
Map em = makeEmptyMap();
|
||||
assertTrue(em != null, "failure in test: makeEmptyMap must return a non-null map.");
|
||||
assertTrue("failure in test: makeEmptyMap must return a non-null map.", em != null);
|
||||
|
||||
Map em2 = makeEmptyMap();
|
||||
assertTrue(em2 != null, "failure in test: makeEmptyMap must return a non-null map.");
|
||||
assertTrue(em != em2, "failure in test: makeEmptyMap must return a new map with each invocation.");
|
||||
assertTrue("failure in test: makeEmptyMap must return a non-null map.", em2 != null);
|
||||
assertTrue("failure in test: makeEmptyMap must return a new map with each invocation.", em != em2);
|
||||
|
||||
Map fm = makeFullMap();
|
||||
assertTrue(fm != null, "failure in test: makeFullMap must return a non-null map.");
|
||||
assertTrue("failure in test: makeFullMap must return a non-null map.", fm != null);
|
||||
|
||||
Map fm2 = makeFullMap();
|
||||
assertTrue(fm2 != null, "failure in test: makeFullMap must return a non-null map.");
|
||||
assertTrue(fm != fm2, "failure in test: makeFullMap must return a new map with each invocation.");
|
||||
assertTrue("failure in test: makeFullMap must return a non-null map.", fm2 != null);
|
||||
assertTrue("failure in test: makeFullMap must return a new map with each invocation.", fm != fm2);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -534,11 +537,11 @@ public abstract class MapAbstractTest extends ObjectAbstractTest {
|
||||
@Test
|
||||
public void testMapIsEmpty() {
|
||||
resetEmpty();
|
||||
assertEquals(true, map.isEmpty(), "Map.isEmpty() should return true with an empty map");
|
||||
assertEquals("Map.isEmpty() should return true with an empty map", true, map.isEmpty());
|
||||
verifyAll();
|
||||
|
||||
resetFull();
|
||||
assertEquals(false, map.isEmpty(), "Map.isEmpty() should return false with a non-empty map");
|
||||
assertEquals("Map.isEmpty() should return false with a non-empty map", false, map.isEmpty());
|
||||
verifyAll();
|
||||
}
|
||||
|
||||
@@ -548,11 +551,11 @@ public abstract class MapAbstractTest extends ObjectAbstractTest {
|
||||
@Test
|
||||
public void testMapSize() {
|
||||
resetEmpty();
|
||||
assertEquals(0, map.size(), "Map.size() should be 0 with an empty map");
|
||||
assertEquals("Map.size() should be 0 with an empty map", 0, map.size());
|
||||
verifyAll();
|
||||
|
||||
resetFull();
|
||||
assertEquals(getSampleKeys().length, map.size(), "Map.size() should equal the number of entries in the map");
|
||||
assertEquals("Map.size() should equal the number of entries in the map", getSampleKeys().length, map.size());
|
||||
verifyAll();
|
||||
}
|
||||
|
||||
@@ -599,13 +602,13 @@ public abstract class MapAbstractTest extends ObjectAbstractTest {
|
||||
|
||||
resetEmpty();
|
||||
for (Object key : keys) {
|
||||
assertTrue(!map.containsKey(key), "Map must not contain key when map is empty");
|
||||
assertTrue("Map must not contain key when map is empty", !map.containsKey(key));
|
||||
}
|
||||
verifyAll();
|
||||
|
||||
resetFull();
|
||||
for (Object key : keys) {
|
||||
assertTrue(map.containsKey(key), "Map must contain key for a mapping in the map. Missing: " + key);
|
||||
assertTrue("Map must contain key for a mapping in the map. Missing: " + key, map.containsKey(key));
|
||||
}
|
||||
verifyAll();
|
||||
}
|
||||
@@ -621,13 +624,13 @@ public abstract class MapAbstractTest extends ObjectAbstractTest {
|
||||
|
||||
resetEmpty();
|
||||
for (Object value : values) {
|
||||
assertTrue(!map.containsValue(value), "Empty map must not contain value");
|
||||
assertTrue("Empty map must not contain value", !map.containsValue(value));
|
||||
}
|
||||
verifyAll();
|
||||
|
||||
resetFull();
|
||||
for (Object value : values) {
|
||||
assertTrue(map.containsValue(value), "Map must contain value for a mapping in the map.");
|
||||
assertTrue("Map must contain value for a mapping in the map.", map.containsValue(value));
|
||||
}
|
||||
verifyAll();
|
||||
}
|
||||
@@ -638,11 +641,11 @@ public abstract class MapAbstractTest extends ObjectAbstractTest {
|
||||
@Test
|
||||
public void testMapEquals() {
|
||||
resetEmpty();
|
||||
assertTrue(map.equals(confirmed), "Empty maps unequal.");
|
||||
assertTrue("Empty maps unequal.", map.equals(confirmed));
|
||||
verifyAll();
|
||||
|
||||
resetFull();
|
||||
assertTrue(map.equals(confirmed), "Full maps unequal.");
|
||||
assertTrue("Full maps unequal.", map.equals(confirmed));
|
||||
verifyAll();
|
||||
|
||||
resetFull();
|
||||
@@ -651,11 +654,11 @@ public abstract class MapAbstractTest extends ObjectAbstractTest {
|
||||
Iterator iter = confirmed.keySet().iterator();
|
||||
iter.next();
|
||||
iter.remove();
|
||||
assertTrue(!map.equals(confirmed), "Different maps equal.");
|
||||
assertTrue("Different maps equal.", !map.equals(confirmed));
|
||||
|
||||
resetFull();
|
||||
assertTrue(!map.equals(null), "equals(null) returned true.");
|
||||
assertTrue(!map.equals(new Object()), "equals(new Object()) returned true.");
|
||||
assertTrue("equals(null) returned true.", !map.equals(null));
|
||||
assertTrue("equals(new Object()) returned true.", !map.equals(new Object()));
|
||||
verifyAll();
|
||||
}
|
||||
|
||||
@@ -670,14 +673,14 @@ public abstract class MapAbstractTest extends ObjectAbstractTest {
|
||||
Object[] values = getSampleValues();
|
||||
|
||||
for (Object key : keys) {
|
||||
assertTrue(map.get(key) == null, "Empty map.get() should return null.");
|
||||
assertTrue("Empty map.get() should return null.", map.get(key) == null);
|
||||
}
|
||||
|
||||
verifyAll();
|
||||
|
||||
resetFull();
|
||||
for (int i = 0; i < keys.length; i++) {
|
||||
assertEquals(values[i], map.get(keys[i]), "Full map.get() should return value from mapping.");
|
||||
assertEquals("Full map.get() should return value from mapping.", values[i], map.get(keys[i]));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -687,10 +690,10 @@ public abstract class MapAbstractTest extends ObjectAbstractTest {
|
||||
@Test
|
||||
public void testMapHashCode() {
|
||||
resetEmpty();
|
||||
assertTrue(map.hashCode() == confirmed.hashCode(), "Empty maps have different hashCodes.");
|
||||
assertTrue("Empty maps have different hashCodes.", map.hashCode() == confirmed.hashCode());
|
||||
|
||||
resetFull();
|
||||
assertTrue(map.hashCode() == confirmed.hashCode(), "Equal maps have different hashCodes.");
|
||||
assertTrue("Equal maps have different hashCodes.", map.hashCode() == confirmed.hashCode());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -705,11 +708,11 @@ public abstract class MapAbstractTest extends ObjectAbstractTest {
|
||||
@Test
|
||||
public void testMapToString() {
|
||||
resetEmpty();
|
||||
assertTrue(map.toString() != null, "Empty map toString() should not return null");
|
||||
assertTrue("Empty map toString() should not return null", map.toString() != null);
|
||||
verifyAll();
|
||||
|
||||
resetFull();
|
||||
assertTrue(map.toString() != null, "Empty map toString() should not return null");
|
||||
assertTrue("Empty map toString() should not return null", map.toString() != null);
|
||||
verifyAll();
|
||||
}
|
||||
|
||||
@@ -773,23 +776,29 @@ public abstract class MapAbstractTest extends ObjectAbstractTest {
|
||||
Object o = map.put(keys[i], values[i]);
|
||||
confirmed.put(keys[i], values[i]);
|
||||
verifyAll();
|
||||
assertTrue(o == null, "First map.put should return null");
|
||||
assertTrue(map.containsKey(keys[i]), "Map should contain key after put");
|
||||
assertTrue(map.containsValue(values[i]), "Map should contain value after put");
|
||||
assertTrue("First map.put should return null", o == null);
|
||||
assertTrue("Map should contain key after put",
|
||||
map.containsKey(keys[i]));
|
||||
assertTrue("Map should contain value after put",
|
||||
map.containsValue(values[i]));
|
||||
}
|
||||
if (isPutChangeSupported()) {
|
||||
for (int i = 0; i < keys.length; i++) {
|
||||
Object o = map.put(keys[i], newValues[i]);
|
||||
confirmed.put(keys[i], newValues[i]);
|
||||
verifyAll();
|
||||
assertEquals(values[i], o, "Map.put should return previous value when changed");
|
||||
assertTrue(map.containsKey(keys[i]), "Map should still contain key after put when changed");
|
||||
assertTrue(map.containsValue(newValues[i]), "Map should contain new value after put when changed");
|
||||
assertEquals("Map.put should return previous value when changed",
|
||||
values[i], o);
|
||||
assertTrue("Map should still contain key after put when changed",
|
||||
map.containsKey(keys[i]));
|
||||
assertTrue("Map should contain new value after put when changed",
|
||||
map.containsValue(newValues[i]));
|
||||
|
||||
// if duplicates are allowed, we're not guaranteed that the value
|
||||
// no longer exists, so don't try checking that.
|
||||
if (!isAllowDuplicateValues()) {
|
||||
assertTrue(!map.containsValue(values[i]), "Map should not contain old value after put when changed");
|
||||
assertTrue("Map should not contain old value after put when changed",
|
||||
!map.containsValue(values[i]));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -823,14 +832,18 @@ public abstract class MapAbstractTest extends ObjectAbstractTest {
|
||||
Object o = map.put(key, newValues[i]);
|
||||
Object value = confirmed.put(key, newValues[i]);
|
||||
verifyAll();
|
||||
assertEquals(value, o, "Map.put should return previous value when changed");
|
||||
assertTrue(map.containsKey(key), "Map should still contain key after put when changed");
|
||||
assertTrue(map.containsValue(newValues[i]), "Map should contain new value after put when changed");
|
||||
assertEquals("Map.put should return previous value when changed",
|
||||
value, o);
|
||||
assertTrue("Map should still contain key after put when changed",
|
||||
map.containsKey(key));
|
||||
assertTrue("Map should contain new value after put when changed",
|
||||
map.containsValue(newValues[i]));
|
||||
|
||||
// if duplicates are allowed, we're not guaranteed that the value
|
||||
// no longer exists, so don't try checking that.
|
||||
if (!isAllowDuplicateValues()) {
|
||||
assertTrue(!map.containsValue(values[i]), "Map should not contain old value after put when changed");
|
||||
assertTrue("Map should not contain old value after put when changed",
|
||||
!map.containsValue(values[i]));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -957,7 +970,7 @@ public abstract class MapAbstractTest extends ObjectAbstractTest {
|
||||
Object[] values = getSampleValues();
|
||||
for (int i = 0; i < keys.length; i++) {
|
||||
Object o = map.remove(keys[i]);
|
||||
assertTrue(o == null, "First map.remove should return null");
|
||||
assertTrue("First map.remove should return null", o == null);
|
||||
}
|
||||
verifyAll();
|
||||
|
||||
@@ -968,7 +981,8 @@ public abstract class MapAbstractTest extends ObjectAbstractTest {
|
||||
confirmed.remove(keys[i]);
|
||||
verifyAll();
|
||||
|
||||
assertEquals(values[i], o, "map.remove with valid key should return value");
|
||||
assertEquals("map.remove with valid key should return value",
|
||||
values[i], o);
|
||||
}
|
||||
|
||||
Object[] other = getOtherKeys();
|
||||
@@ -977,8 +991,10 @@ public abstract class MapAbstractTest extends ObjectAbstractTest {
|
||||
int size = map.size();
|
||||
for (int i = 0; i < other.length; i++) {
|
||||
Object o = map.remove(other[i]);
|
||||
assertEquals(o, null, "map.remove for nonexistent key should return null");
|
||||
assertEquals(size, map.size(), "map.remove for nonexistent key should not shrink map");
|
||||
assertEquals("map.remove for nonexistent key should return null",
|
||||
o, null);
|
||||
assertEquals("map.remove for nonexistent key should not " +
|
||||
"shrink map", size, map.size());
|
||||
}
|
||||
verifyAll();
|
||||
}
|
||||
@@ -1188,9 +1204,10 @@ public abstract class MapAbstractTest extends ObjectAbstractTest {
|
||||
}
|
||||
j++;
|
||||
}
|
||||
assertTrue(j < 10000, "values().remove(obj) is broken");
|
||||
assertTrue(!map.containsValue(sampleValues[i]),
|
||||
"Value should have been removed from the underlying map.");
|
||||
assertTrue("values().remove(obj) is broken", j < 10000);
|
||||
assertTrue(
|
||||
"Value should have been removed from the underlying map.",
|
||||
!map.containsValue(sampleValues[i]));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1213,8 +1230,9 @@ public abstract class MapAbstractTest extends ObjectAbstractTest {
|
||||
// if key.remove is unsupported, just skip this test
|
||||
return;
|
||||
}
|
||||
assertTrue(!map.containsKey(sampleKeys[i]),
|
||||
"Key should have been removed from the underlying map.");
|
||||
assertTrue(
|
||||
"Key should have been removed from the underlying map.",
|
||||
!map.containsKey(sampleKeys[i]));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1395,7 +1413,7 @@ public abstract class MapAbstractTest extends ObjectAbstractTest {
|
||||
break;
|
||||
}
|
||||
}
|
||||
assertNotNull(entry, "No matching entry in map for key '" + key + "'");
|
||||
assertNotNull("No matching entry in map for key '" + key + "'", entry);
|
||||
return entry;
|
||||
}
|
||||
|
||||
@@ -1620,14 +1638,14 @@ public abstract class MapAbstractTest extends ObjectAbstractTest {
|
||||
public void verifyMap() {
|
||||
int size = confirmed.size();
|
||||
boolean empty = confirmed.isEmpty();
|
||||
assertEquals(size, map.size(), "Map should be same size as HashMap");
|
||||
assertEquals(empty, map.isEmpty(), "Map should be empty if HashMap is");
|
||||
assertEquals(confirmed.hashCode(), map.hashCode(), "hashCodes should be the same");
|
||||
assertEquals("Map should be same size as HashMap", size, map.size());
|
||||
assertEquals("Map should be empty if HashMap is", empty, map.isEmpty());
|
||||
assertEquals("hashCodes should be the same", confirmed.hashCode(), map.hashCode());
|
||||
// this fails for LRUMap because confirmed.equals() somehow modifies
|
||||
// map, causing concurrent modification exceptions.
|
||||
//assertEquals("Map should still equal HashMap", confirmed, map);
|
||||
// this works though and performs the same verification:
|
||||
assertTrue(map.equals(confirmed), "Map should still equal HashMap");
|
||||
assertTrue("Map should still equal HashMap", map.equals(confirmed));
|
||||
// TODO: this should really be reexamined to figure out why LRU map
|
||||
// behaves like it does (the equals shouldn't modify since all accesses
|
||||
// by the confirmed collection should be through an iterator, thus not
|
||||
@@ -1637,29 +1655,29 @@ public abstract class MapAbstractTest extends ObjectAbstractTest {
|
||||
public void verifyEntrySet() {
|
||||
int size = confirmed.size();
|
||||
boolean empty = confirmed.isEmpty();
|
||||
assertEquals(size, entrySet.size(),
|
||||
"entrySet should be same size as HashMap's\nTest: " + entrySet + "\nReal: " + confirmed.entrySet());
|
||||
assertEquals(empty, entrySet.isEmpty(),
|
||||
"entrySet should be empty if HashMap is\nTest: " + entrySet + "\nReal: " + confirmed.entrySet());
|
||||
assertTrue(entrySet.containsAll(confirmed.entrySet()),
|
||||
"entrySet should contain all HashMap's elements\nTest: " + entrySet + "\nReal: " + confirmed.entrySet());
|
||||
assertEquals(confirmed.entrySet().hashCode(), entrySet.hashCode(),
|
||||
"entrySet hashCodes should be the same\nTest: " + entrySet + "\nReal: " + confirmed.entrySet());
|
||||
assertEquals(confirmed.entrySet(), entrySet,"Map's entry set should still equal HashMap's");
|
||||
assertEquals("entrySet should be same size as HashMap's\nTest: " + entrySet + "\nReal: " + confirmed.entrySet(),
|
||||
size, entrySet.size());
|
||||
assertEquals("entrySet should be empty if HashMap is\nTest: " + entrySet + "\nReal: " + confirmed.entrySet(),
|
||||
empty, entrySet.isEmpty());
|
||||
assertTrue("entrySet should contain all HashMap's elements\nTest: " + entrySet + "\nReal: " + confirmed.entrySet(),
|
||||
entrySet.containsAll(confirmed.entrySet()));
|
||||
assertEquals("entrySet hashCodes should be the same\nTest: " + entrySet + "\nReal: " + confirmed.entrySet(),
|
||||
confirmed.entrySet().hashCode(), entrySet.hashCode());
|
||||
assertEquals("Map's entry set should still equal HashMap's", confirmed.entrySet(), entrySet);
|
||||
}
|
||||
|
||||
public void verifyKeySet() {
|
||||
int size = confirmed.size();
|
||||
boolean empty = confirmed.isEmpty();
|
||||
assertEquals(size, keySet.size(),
|
||||
"keySet should be same size as HashMap's\nTest: " + keySet + "\nReal: " + confirmed.keySet());
|
||||
assertEquals(empty, keySet.isEmpty(),
|
||||
"keySet should be empty if HashMap is\nTest: " + keySet + "\nReal: " + confirmed.keySet());
|
||||
assertTrue(keySet.containsAll(confirmed.keySet()),
|
||||
"keySet should contain all HashMap's elements\nTest: " + keySet + "\nReal: " + confirmed.keySet());
|
||||
assertEquals(confirmed.keySet().hashCode(), keySet.hashCode(),
|
||||
"keySet hashCodes should be the same\nTest: " + keySet + "\nReal: " + confirmed.keySet());
|
||||
assertEquals(confirmed.keySet(), keySet, "Map's key set should still equal HashMap's");
|
||||
assertEquals("keySet should be same size as HashMap's\nTest: " + keySet + "\nReal: " + confirmed.keySet(),
|
||||
size, keySet.size());
|
||||
assertEquals("keySet should be empty if HashMap is\nTest: " + keySet + "\nReal: " + confirmed.keySet(),
|
||||
empty, keySet.isEmpty());
|
||||
assertTrue("keySet should contain all HashMap's elements\nTest: " + keySet + "\nReal: " + confirmed.keySet(),
|
||||
keySet.containsAll(confirmed.keySet()));
|
||||
assertEquals("keySet hashCodes should be the same\nTest: " + keySet + "\nReal: " + confirmed.keySet(),
|
||||
confirmed.keySet().hashCode(), keySet.hashCode());
|
||||
assertEquals("Map's key set should still equal HashMap's", confirmed.keySet(), keySet);
|
||||
}
|
||||
|
||||
public void verifyValues() {
|
||||
@@ -1669,23 +1687,23 @@ public abstract class MapAbstractTest extends ObjectAbstractTest {
|
||||
int size = confirmed.size();
|
||||
boolean empty = confirmed.isEmpty();
|
||||
|
||||
assertEquals(size, values.size(), "values should be same size as HashMap's\nTest: " + test + "\nReal: " + known);
|
||||
assertEquals(empty, values.isEmpty(), "values should be empty if HashMap is\nTest: " + test + "\nReal: " + known);
|
||||
assertTrue(test.containsAll(known), "values should contain all HashMap's elements\nTest: " + test + "\nReal: " + known);
|
||||
assertTrue(known.containsAll(test), "values should contain all HashMap's elements\nTest: " + test + "\nReal: " + known);
|
||||
assertEquals("values should be same size as HashMap's\nTest: " + test + "\nReal: " + known, size, values.size());
|
||||
assertEquals("values should be empty if HashMap is\nTest: " + test + "\nReal: " + known, empty, values.isEmpty());
|
||||
assertTrue("values should contain all HashMap's elements\nTest: " + test + "\nReal: " + known, test.containsAll(known));
|
||||
assertTrue("values should contain all HashMap's elements\nTest: " + test + "\nReal: " + known, known.containsAll(test));
|
||||
|
||||
for (Object aKnown : known) {
|
||||
boolean removed = test.remove(aKnown);
|
||||
assertTrue(removed, "Map's values should still equal HashMap's");
|
||||
assertTrue("Map's values should still equal HashMap's", removed);
|
||||
}
|
||||
|
||||
assertTrue(test.isEmpty(), "Map's values should still equal HashMap's");
|
||||
assertTrue("Map's values should still equal HashMap's", test.isEmpty());
|
||||
}
|
||||
|
||||
/**
|
||||
* Erases any leftover instance variables by setting them to null.
|
||||
*/
|
||||
@AfterEach
|
||||
@After
|
||||
public void tearDown() throws Exception {
|
||||
map = null;
|
||||
keySet = null;
|
||||
|
||||
@@ -30,11 +30,13 @@
|
||||
|
||||
package com.twelvemonkeys.util;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.jupiter.api.*;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
/**
|
||||
* NOTE: This TestCase is written especially for NullMap, and is full of dirty
|
||||
@@ -81,12 +83,12 @@ public class NullMapTest extends MapAbstractTest {
|
||||
@Override
|
||||
public void testMapIsEmpty() {
|
||||
resetEmpty();
|
||||
assertEquals(true, map.isEmpty(),
|
||||
"Map.isEmpty() should return true with an empty map");
|
||||
assertEquals("Map.isEmpty() should return true with an empty map",
|
||||
true, map.isEmpty());
|
||||
verifyAll();
|
||||
resetFull();
|
||||
assertEquals(true, map.isEmpty(),
|
||||
"Map.isEmpty() should return true with a full map");
|
||||
assertEquals("Map.isEmpty() should return true with a full map",
|
||||
true, map.isEmpty());
|
||||
}
|
||||
|
||||
// Overriden, as this map is always empty
|
||||
@@ -94,13 +96,13 @@ public class NullMapTest extends MapAbstractTest {
|
||||
@Override
|
||||
public void testMapSize() {
|
||||
resetEmpty();
|
||||
assertEquals(0, map.size(),
|
||||
"Map.size() should be 0 with an empty map");
|
||||
assertEquals("Map.size() should be 0 with an empty map",
|
||||
0, map.size());
|
||||
verifyAll();
|
||||
|
||||
resetFull();
|
||||
assertEquals(0, map.size(),
|
||||
"Map.size() should equal the number of entries in the map");
|
||||
assertEquals("Map.size() should equal the number of entries " +
|
||||
"in the map", 0, map.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -110,7 +112,7 @@ public class NullMapTest extends MapAbstractTest {
|
||||
|
||||
resetEmpty();
|
||||
for (Object key : keys) {
|
||||
assertTrue(!map.containsKey(key),"Map must not contain key when map is empty");
|
||||
assertTrue("Map must not contain key when map is empty", !map.containsKey(key));
|
||||
}
|
||||
verifyAll();
|
||||
}
|
||||
@@ -122,7 +124,7 @@ public class NullMapTest extends MapAbstractTest {
|
||||
|
||||
resetEmpty();
|
||||
for (Object value : values) {
|
||||
assertTrue(!map.containsValue(value), "Empty map must not contain value");
|
||||
assertTrue("Empty map must not contain value", !map.containsValue(value));
|
||||
}
|
||||
verifyAll();
|
||||
}
|
||||
@@ -131,7 +133,7 @@ public class NullMapTest extends MapAbstractTest {
|
||||
@Override
|
||||
public void testMapEquals() {
|
||||
resetEmpty();
|
||||
assertTrue(map.equals(confirmed), "Empty maps unequal.");
|
||||
assertTrue("Empty maps unequal.", map.equals(confirmed));
|
||||
verifyAll();
|
||||
}
|
||||
|
||||
@@ -139,7 +141,8 @@ public class NullMapTest extends MapAbstractTest {
|
||||
@Override
|
||||
public void testMapHashCode() {
|
||||
resetEmpty();
|
||||
assertTrue(map.hashCode() == confirmed.hashCode(), "Empty maps have different hashCodes.");
|
||||
assertTrue("Empty maps have different hashCodes.",
|
||||
map.hashCode() == confirmed.hashCode());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -150,7 +153,7 @@ public class NullMapTest extends MapAbstractTest {
|
||||
Object[] keys = getSampleKeys();
|
||||
|
||||
for (Object key : keys) {
|
||||
assertTrue(map.get(key) == null, "Empty map.get() should return null.");
|
||||
assertTrue("Empty map.get() should return null.", map.get(key) == null);
|
||||
}
|
||||
verifyAll();
|
||||
}
|
||||
@@ -167,7 +170,7 @@ public class NullMapTest extends MapAbstractTest {
|
||||
Object o = map.put(keys[i], values[i]);
|
||||
//confirmed.put(keys[i], values[i]);
|
||||
verifyAll();
|
||||
assertTrue(o == null, "First map.put should return null");
|
||||
assertTrue("First map.put should return null", o == null);
|
||||
}
|
||||
for (int i = 0; i < keys.length; i++) {
|
||||
map.put(keys[i], newValues[i]);
|
||||
@@ -180,8 +183,8 @@ public class NullMapTest extends MapAbstractTest {
|
||||
@Override
|
||||
public void testMapToString() {
|
||||
resetEmpty();
|
||||
assertTrue(map.toString() != null,
|
||||
"Empty map toString() should not return null");
|
||||
assertTrue("Empty map toString() should not return null",
|
||||
map.toString() != null);
|
||||
verifyAll();
|
||||
}
|
||||
|
||||
@@ -199,7 +202,7 @@ public class NullMapTest extends MapAbstractTest {
|
||||
Object[] keys = getSampleKeys();
|
||||
for(int i = 0; i < keys.length; i++) {
|
||||
Object o = map.remove(keys[i]);
|
||||
assertTrue(o == null, "First map.remove should return null");
|
||||
assertTrue("First map.remove should return null", o == null);
|
||||
}
|
||||
verifyAll();
|
||||
}
|
||||
|
||||
@@ -44,10 +44,12 @@
|
||||
*/
|
||||
package com.twelvemonkeys.util;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
import org.junit.jupiter.api.*;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
/**
|
||||
* Abstract test class for {@link Object} methods and contracts.
|
||||
@@ -117,7 +119,7 @@ public abstract class ObjectAbstractTest {
|
||||
@Test
|
||||
public void testObjectEqualsSelf() {
|
||||
Object obj = makeObject();
|
||||
assertEquals(obj, obj, "A Object should equal itself");
|
||||
assertEquals("A Object should equal itself", obj, obj);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -129,24 +131,25 @@ public abstract class ObjectAbstractTest {
|
||||
@Test
|
||||
public void testObjectHashCodeEqualsSelfHashCode() {
|
||||
Object obj = makeObject();
|
||||
assertEquals(obj.hashCode(), obj.hashCode(), "hashCode should be repeatable");
|
||||
assertEquals("hashCode should be repeatable", obj.hashCode(), obj.hashCode());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testObjectHashCodeEqualsContract() {
|
||||
Object obj1 = makeObject();
|
||||
if (obj1.equals(obj1)) {
|
||||
assertEquals(obj1.hashCode(), obj1.hashCode(),
|
||||
"[1] When two objects are equal, their hashCodes should be also.");
|
||||
assertEquals(
|
||||
"[1] When two objects are equal, their hashCodes should be also.",
|
||||
obj1.hashCode(), obj1.hashCode());
|
||||
}
|
||||
Object obj2 = makeObject();
|
||||
if (obj1.equals(obj2)) {
|
||||
assertEquals(
|
||||
obj1.hashCode(), obj2.hashCode(),
|
||||
"[2] When two objects are equal, their hashCodes should be also.");
|
||||
"[2] When two objects are equal, their hashCodes should be also.",
|
||||
obj1.hashCode(), obj2.hashCode());
|
||||
assertTrue(
|
||||
obj2.equals(obj1),
|
||||
"When obj1.equals(obj2) is true, then obj2.equals(obj1) should also be true");
|
||||
"When obj1.equals(obj2) is true, then obj2.equals(obj1) should also be true",
|
||||
obj2.equals(obj1));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -163,7 +166,7 @@ public abstract class ObjectAbstractTest {
|
||||
Object dest = in.readObject();
|
||||
in.close();
|
||||
if (isEqualsCheckable()) {
|
||||
assertEquals(obj, dest, "obj != deserialize(serialize(obj))");
|
||||
assertEquals("obj != deserialize(serialize(obj))", obj, dest);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -196,8 +199,8 @@ public abstract class ObjectAbstractTest {
|
||||
if (object instanceof Serializable) {
|
||||
String name = getCanonicalEmptyCollectionName(object);
|
||||
assertTrue(
|
||||
new File(name).exists(),
|
||||
"Canonical empty collection (" + name + ") is not in CVS");
|
||||
"Canonical empty collection (" + name + ") is not in CVS",
|
||||
new File(name).exists());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -213,8 +216,8 @@ public abstract class ObjectAbstractTest {
|
||||
if (object instanceof Serializable) {
|
||||
String name = getCanonicalFullCollectionName(object);
|
||||
assertTrue(
|
||||
new File(name).exists(),
|
||||
"Canonical full collection (" + name + ") is not in CVS");
|
||||
"Canonical full collection (" + name + ") is not in CVS",
|
||||
new File(name).exists());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,10 +44,12 @@
|
||||
*/
|
||||
package com.twelvemonkeys.util;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import org.junit.jupiter.api.*;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
/**
|
||||
* Abstract test class for {@link Set} methods and contracts.
|
||||
@@ -77,12 +79,14 @@ public abstract class SetAbstractTest extends CollectionAbstractTest {
|
||||
public void verifyAll() {
|
||||
super.verifyAll();
|
||||
|
||||
assertEquals(confirmed, collection, "Sets should be equal");
|
||||
assertEquals(confirmed.hashCode(), collection.hashCode(), "Sets should have equal hashCodes");
|
||||
assertEquals("Sets should be equal", confirmed, collection);
|
||||
assertEquals("Sets should have equal hashCodes",
|
||||
confirmed.hashCode(), collection.hashCode());
|
||||
Collection set = makeConfirmedCollection();
|
||||
Iterator iterator = collection.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
assertTrue(set.add(iterator.next()), "Set.iterator should only return unique elements");
|
||||
assertTrue("Set.iterator should only return unique elements",
|
||||
set.add(iterator.next()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -176,20 +180,23 @@ public abstract class SetAbstractTest extends CollectionAbstractTest {
|
||||
@Test
|
||||
public void testSetEquals() {
|
||||
resetEmpty();
|
||||
assertEquals(getSet(), getConfirmedSet(), "Empty sets should be equal");
|
||||
assertEquals("Empty sets should be equal",
|
||||
getSet(), getConfirmedSet());
|
||||
verifyAll();
|
||||
|
||||
Collection set2 = makeConfirmedCollection();
|
||||
set2.add("foo");
|
||||
assertTrue(!getSet().equals(set2), "Empty set shouldn't equal nonempty set");
|
||||
assertTrue("Empty set shouldn't equal nonempty set",
|
||||
!getSet().equals(set2));
|
||||
|
||||
resetFull();
|
||||
assertEquals(getSet(), getConfirmedSet(), "Full sets should be equal");
|
||||
assertEquals("Full sets should be equal", getSet(), getConfirmedSet());
|
||||
verifyAll();
|
||||
|
||||
set2.clear();
|
||||
set2.addAll(Arrays.asList(getOtherElements()));
|
||||
assertTrue(!getSet().equals(set2), "Sets with different contents shouldn't be equal");
|
||||
assertTrue("Sets with different contents shouldn't be equal",
|
||||
!getSet().equals(set2));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -198,9 +205,11 @@ public abstract class SetAbstractTest extends CollectionAbstractTest {
|
||||
@Test
|
||||
public void testSetHashCode() {
|
||||
resetEmpty();
|
||||
assertEquals(getSet().hashCode(), getConfirmedSet().hashCode(), "Empty sets have equal hashCodes");
|
||||
assertEquals("Empty sets have equal hashCodes",
|
||||
getSet().hashCode(), getConfirmedSet().hashCode());
|
||||
|
||||
resetFull();
|
||||
assertEquals(getSet().hashCode(), getConfirmedSet().hashCode(), "Equal sets have equal hashCodes");
|
||||
assertEquals("Equal sets have equal hashCodes",
|
||||
getSet().hashCode(), getConfirmedSet().hashCode());
|
||||
}
|
||||
}
|
||||
|
||||
+32
-30
@@ -30,10 +30,12 @@
|
||||
|
||||
package com.twelvemonkeys.util;
|
||||
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
import org.junit.jupiter.api.*;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* StringTokenIteratorTestCase
|
||||
@@ -54,88 +56,88 @@ public class StringTokenIteratorTest extends TokenIteratorAbstractTest {
|
||||
@Test
|
||||
public void testEmptyDelimiter() {
|
||||
Iterator iterator = createTokenIterator("", "");
|
||||
assertFalse(iterator.hasNext(), "Empty string has elements");
|
||||
assertFalse("Empty string has elements", iterator.hasNext());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSingleToken() {
|
||||
Iterator iterator = createTokenIterator("A");
|
||||
assertTrue(iterator.hasNext(), "String has no elements");
|
||||
assertTrue("String has no elements", iterator.hasNext());
|
||||
assertEquals("A", iterator.next());
|
||||
assertFalse(iterator.hasNext(), "String has more than one element");
|
||||
assertFalse("String has more than one element", iterator.hasNext());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSingleTokenEmptyDelimiter() {
|
||||
Iterator iterator = createTokenIterator("A", "");
|
||||
assertTrue(iterator.hasNext(), "String has no elements");
|
||||
assertTrue("String has no elements", iterator.hasNext());
|
||||
assertEquals("A", iterator.next());
|
||||
assertFalse(iterator.hasNext(), "String has more than one element");
|
||||
assertFalse("String has more than one element", iterator.hasNext());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSingleTokenSingleDelimiter() {
|
||||
Iterator iterator = createTokenIterator("A", ",");
|
||||
assertTrue(iterator.hasNext(), "String has no elements");
|
||||
assertTrue("String has no elements", iterator.hasNext());
|
||||
assertEquals("A", iterator.next());
|
||||
assertFalse(iterator.hasNext(), "String has more than one element");
|
||||
assertFalse("String has more than one element", iterator.hasNext());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSingleSeparatorDefaultDelimiter() {
|
||||
Iterator iterator = createTokenIterator("A B C D");
|
||||
assertTrue(iterator.hasNext(), "String has no elements");
|
||||
assertTrue("String has no elements", iterator.hasNext());
|
||||
assertEquals("A", iterator.next());
|
||||
assertTrue(iterator.hasNext(), "String has no elements");
|
||||
assertTrue("String has no elements", iterator.hasNext());
|
||||
assertEquals("B", iterator.next());
|
||||
assertTrue(iterator.hasNext(), "String has no elements");
|
||||
assertTrue("String has no elements", iterator.hasNext());
|
||||
assertEquals("C", iterator.next());
|
||||
assertTrue(iterator.hasNext(), "String has no elements");
|
||||
assertTrue("String has no elements", iterator.hasNext());
|
||||
assertEquals("D", iterator.next());
|
||||
assertFalse(iterator.hasNext(), "String has more than one element");
|
||||
assertFalse("String has more than one element", iterator.hasNext());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSingleSeparator() {
|
||||
Iterator iterator = createTokenIterator("A,B,C", ",");
|
||||
assertTrue(iterator.hasNext(), "String has no elements");
|
||||
assertTrue("String has no elements", iterator.hasNext());
|
||||
assertEquals("A", iterator.next());
|
||||
assertTrue(iterator.hasNext(), "String has no elements");
|
||||
assertTrue("String has no elements", iterator.hasNext());
|
||||
assertEquals("B", iterator.next());
|
||||
assertTrue(iterator.hasNext(), "String has no elements");
|
||||
assertTrue("String has no elements", iterator.hasNext());
|
||||
assertEquals("C", iterator.next());
|
||||
assertFalse(iterator.hasNext(), "String has more than one element");
|
||||
assertFalse("String has more than one element", iterator.hasNext());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMultipleSeparatorDefaultDelimiter() {
|
||||
Iterator iterator = createTokenIterator("A B C\nD\t\t \nE");
|
||||
assertTrue(iterator.hasNext(), "String has no elements");
|
||||
assertTrue("String has no elements", iterator.hasNext());
|
||||
assertEquals("A", iterator.next());
|
||||
assertTrue(iterator.hasNext(), "String has no elements");
|
||||
assertTrue("String has no elements", iterator.hasNext());
|
||||
assertEquals("B", iterator.next());
|
||||
assertTrue(iterator.hasNext(), "String has no elements");
|
||||
assertTrue("String has no elements", iterator.hasNext());
|
||||
assertEquals("C", iterator.next());
|
||||
assertTrue(iterator.hasNext(), "String has no elements");
|
||||
assertTrue("String has no elements", iterator.hasNext());
|
||||
assertEquals("D", iterator.next());
|
||||
assertTrue(iterator.hasNext(), "String has no elements");
|
||||
assertTrue("String has no elements", iterator.hasNext());
|
||||
assertEquals("E", iterator.next());
|
||||
assertFalse(iterator.hasNext(), "String has more than one element");
|
||||
assertFalse("String has more than one element", iterator.hasNext());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMultipleSeparator() {
|
||||
Iterator iterator = createTokenIterator("A,B,;,C...D, ., ,E", " ,.;:");
|
||||
assertTrue(iterator.hasNext(), "String has no elements");
|
||||
assertTrue("String has no elements", iterator.hasNext());
|
||||
assertEquals("A", iterator.next());
|
||||
assertTrue(iterator.hasNext(), "String has no elements");
|
||||
assertTrue("String has no elements", iterator.hasNext());
|
||||
assertEquals("B", iterator.next());
|
||||
assertTrue(iterator.hasNext(), "String has no elements");
|
||||
assertTrue("String has no elements", iterator.hasNext());
|
||||
assertEquals("C", iterator.next());
|
||||
assertTrue(iterator.hasNext(), "String has no elements");
|
||||
assertTrue("String has no elements", iterator.hasNext());
|
||||
assertEquals("D", iterator.next());
|
||||
assertTrue(iterator.hasNext(), "String has no elements");
|
||||
assertTrue("String has no elements", iterator.hasNext());
|
||||
assertEquals("E", iterator.next());
|
||||
assertFalse(iterator.hasNext(), "String has more than one element");
|
||||
assertFalse("String has more than one element", iterator.hasNext());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,10 +30,12 @@
|
||||
|
||||
package com.twelvemonkeys.util;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import org.junit.jupiter.api.*;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* TimeoutMapTest
|
||||
* <p/>
|
||||
@@ -539,7 +541,7 @@ public class TimeoutMapTest extends MapAbstractTest {
|
||||
}
|
||||
}
|
||||
|
||||
assertTrue(count > 0, "Elements expired too early, test did not run as expected.");
|
||||
assertTrue("Elements expired too early, test did not run as expected.", count > 0);
|
||||
//assertEquals("Elements did not expire as expected.", 1, count);
|
||||
}
|
||||
|
||||
@@ -571,7 +573,7 @@ public class TimeoutMapTest extends MapAbstractTest {
|
||||
}
|
||||
}
|
||||
|
||||
assertTrue(count > 0, "Elements expired too early, test did not run as expected.");
|
||||
assertTrue("Elements expired too early, test did not run as expected.", count > 0);
|
||||
//assertEquals("Elements did not expire as expected.", 1, count);
|
||||
}
|
||||
|
||||
@@ -611,7 +613,7 @@ public class TimeoutMapTest extends MapAbstractTest {
|
||||
}
|
||||
}
|
||||
|
||||
assertTrue(count > 0, "Elements expired too early, test did not run as expected.");
|
||||
assertTrue("Elements expired too early, test did not run as expected.", count > 0);
|
||||
//assertEquals("Elements did not expire as expected.", 1, count);
|
||||
}
|
||||
|
||||
@@ -628,7 +630,7 @@ public class TimeoutMapTest extends MapAbstractTest {
|
||||
Object removedKey = null;
|
||||
Object otherKey = null;
|
||||
Iterator iterator = map.entrySet().iterator();
|
||||
assertTrue(iterator.hasNext(), "Iterator was empty");
|
||||
assertTrue("Iterator was empty", iterator.hasNext());
|
||||
try {
|
||||
Map.Entry entry = (Map.Entry) iterator.next();
|
||||
assertNotNull(entry);
|
||||
@@ -646,8 +648,8 @@ public class TimeoutMapTest extends MapAbstractTest {
|
||||
fail("Elements expired between Interator.hasNext() and Iterator.remove()");
|
||||
}
|
||||
|
||||
assertTrue(!map.containsKey(removedKey), "Wrong entry removed, keySet().iterator() is broken.");
|
||||
assertTrue(map.containsKey(otherKey), "Wrong entry removed, keySet().iterator() is broken.");
|
||||
assertTrue("Wrong entry removed, keySet().iterator() is broken.", !map.containsKey(removedKey));
|
||||
assertTrue("Wrong entry removed, keySet().iterator() is broken.", map.containsKey(otherKey));
|
||||
}
|
||||
|
||||
|
||||
|
||||
+5
-3
@@ -30,10 +30,12 @@
|
||||
|
||||
package com.twelvemonkeys.util;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
import org.junit.jupiter.api.*;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
/**
|
||||
* TokenIteratorAbstractTestCase
|
||||
@@ -78,7 +80,7 @@ public abstract class TokenIteratorAbstractTest {
|
||||
@Test
|
||||
public void testEmptyString() {
|
||||
Iterator iterator = createTokenIterator("");
|
||||
assertFalse(iterator.hasNext(), "Empty string has elements");
|
||||
assertFalse("Empty string has elements", iterator.hasNext());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -30,8 +30,8 @@
|
||||
|
||||
package com.twelvemonkeys.util.convert;
|
||||
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* ConverterTest
|
||||
@@ -43,7 +43,7 @@ import org.junit.jupiter.api.Test;
|
||||
*/
|
||||
public class ConverterTest {
|
||||
|
||||
@Disabled("Not implemented")
|
||||
@Ignore("Not implemented")
|
||||
@Test
|
||||
public void testMe() {
|
||||
// TODO: Implement tests
|
||||
|
||||
+1
-1
@@ -31,7 +31,7 @@
|
||||
package com.twelvemonkeys.util.convert;
|
||||
|
||||
import com.twelvemonkeys.lang.DateUtil;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.text.DateFormat;
|
||||
import java.util.Date;
|
||||
|
||||
+4
-4
@@ -31,13 +31,13 @@
|
||||
package com.twelvemonkeys.util.convert;
|
||||
|
||||
import com.twelvemonkeys.lang.Validate;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.File;
|
||||
import java.net.URI;
|
||||
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* DefaultConverterTest
|
||||
@@ -138,7 +138,7 @@ public class DefaultConverterTest extends PropertyConverterAbstractTest {
|
||||
assertEquals(-2.3456, (Double) converter.toObject("-2.3456", Double.TYPE, null), 0);
|
||||
}
|
||||
|
||||
@Disabled("Known issue. Why would anyone do something like this?")
|
||||
@Ignore("Known issue. Why would anyone do something like this?")
|
||||
@Test
|
||||
public void testConvertCharPrimitive() {
|
||||
PropertyConverter converter = makePropertyConverter();
|
||||
|
||||
+16
-16
@@ -32,11 +32,11 @@ package com.twelvemonkeys.util.convert;
|
||||
|
||||
import com.twelvemonkeys.lang.ObjectAbstractTest;
|
||||
import com.twelvemonkeys.lang.Validate;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* PropertyConverterAbstractTest
|
||||
@@ -66,26 +66,26 @@ public abstract class PropertyConverterAbstractTest extends ObjectAbstractTest {
|
||||
try {
|
||||
obj = converter.toObject(test.original(), test.type(), test.format());
|
||||
|
||||
assertEquals(test.type(), obj.getClass(), String.format("'%s' converted to incorrect type", test.original()));
|
||||
assertEquals(String.format("'%s' converted to incorrect type", test.original()), test.type(), obj.getClass());
|
||||
if (test.type().isArray()) {
|
||||
assertArrayEquals0(String.format("'%s' not converted", test.original()), test.value(), obj);
|
||||
}
|
||||
else {
|
||||
assertEquals(test.value(), obj, String.format("'%s' not converted", test.original()));
|
||||
assertEquals(String.format("'%s' not converted", test.original()), test.value(), obj);
|
||||
}
|
||||
|
||||
String result = converter.toString(test.value(), test.format());
|
||||
|
||||
assertEquals(test.converted(), result, String.format("'%s' does not match", test.converted()));
|
||||
assertEquals(String.format("'%s' does not match", test.converted()), test.converted(), result);
|
||||
|
||||
obj = converter.toObject(result, test.type(), test.format());
|
||||
assertEquals(test.type(), obj.getClass(), String.format("'%s' converted to incorrect type", test.original()));
|
||||
assertEquals(String.format("'%s' converted to incorrect type", test.original()), test.type(), obj.getClass());
|
||||
|
||||
if (test.type().isArray()) {
|
||||
assertArrayEquals0(String.format("'%s' did not survive round trip conversion", test.original()), test.value(), obj);
|
||||
}
|
||||
else {
|
||||
assertEquals(test.value(), obj, String.format("'%s' did not survive round trip conversion", test.original()));
|
||||
assertEquals(String.format("'%s' did not survive round trip conversion", test.original()), test.value(), obj);
|
||||
}
|
||||
}
|
||||
catch (ConversionException e) {
|
||||
@@ -98,35 +98,35 @@ public abstract class PropertyConverterAbstractTest extends ObjectAbstractTest {
|
||||
Class<?> componentType = left.getClass().getComponentType();
|
||||
if (componentType.isPrimitive()) {
|
||||
if (int.class == componentType) {
|
||||
assertArrayEquals((int[]) left, (int[]) right, message);
|
||||
assertArrayEquals(message, (int[]) left, (int[]) right);
|
||||
}
|
||||
else if (short.class == componentType) {
|
||||
assertArrayEquals((short[]) left, (short[]) right, message);
|
||||
assertArrayEquals(message, (short[]) left, (short[]) right);
|
||||
}
|
||||
else if (long.class == componentType) {
|
||||
assertArrayEquals((long[]) left, (long[]) right, message);
|
||||
assertArrayEquals(message, (long[]) left, (long[]) right);
|
||||
}
|
||||
else if (float.class == componentType) {
|
||||
assertArrayEquals((float[]) left, (float[]) right, 0f, message);
|
||||
assertArrayEquals(message, (float[]) left, (float[]) right, 0f);
|
||||
}
|
||||
else if (double.class == componentType) {
|
||||
assertArrayEquals((double[]) left, (double[]) right, 0d, message);
|
||||
assertArrayEquals(message, (double[]) left, (double[]) right, 0d);
|
||||
}
|
||||
else if (boolean.class == componentType) {
|
||||
assertTrue(Arrays.equals((boolean[]) left, (boolean[]) right), message);
|
||||
assertTrue(message, Arrays.equals((boolean[]) left, (boolean[]) right));
|
||||
}
|
||||
else if (byte.class == componentType) {
|
||||
assertArrayEquals((byte[]) left, (byte[]) right, message);
|
||||
assertArrayEquals(message, (byte[]) left, (byte[]) right);
|
||||
}
|
||||
else if (char.class == componentType) {
|
||||
assertArrayEquals((char[]) left, (char[]) right, message);
|
||||
assertArrayEquals(message, (char[]) left, (char[]) right);
|
||||
}
|
||||
else {
|
||||
fail(String.format("Unknown primitive type: %s", componentType));
|
||||
}
|
||||
}
|
||||
else {
|
||||
assertArrayEquals((Object[]) left, (Object[]) right, message);
|
||||
assertArrayEquals(message, (Object[]) left, (Object[]) right);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+28
-27
@@ -32,11 +32,12 @@ package com.twelvemonkeys.util.regex;
|
||||
|
||||
import com.twelvemonkeys.util.TokenIterator;
|
||||
import com.twelvemonkeys.util.TokenIteratorAbstractTest;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* StringTokenIteratorTestCase
|
||||
* <p/>
|
||||
@@ -67,9 +68,9 @@ public class RegExTokenIteratorTest extends TokenIteratorAbstractTest {
|
||||
@Test
|
||||
public void testSingleToken() {
|
||||
Iterator iterator = createTokenIterator("A");
|
||||
assertTrue(iterator.hasNext(), "String has no elements");
|
||||
assertTrue("String has no elements", iterator.hasNext());
|
||||
assertEquals("A", iterator.next());
|
||||
assertFalse(iterator.hasNext(), "String has more than one element");
|
||||
assertFalse("String has more than one element", iterator.hasNext());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -86,67 +87,67 @@ public class RegExTokenIteratorTest extends TokenIteratorAbstractTest {
|
||||
@Test
|
||||
public void testSingleTokenSingleDelimiter() {
|
||||
Iterator iterator = createTokenIterator("A", "[^,]+");
|
||||
assertTrue(iterator.hasNext(), "String has no elements");
|
||||
assertTrue("String has no elements", iterator.hasNext());
|
||||
assertEquals("A", iterator.next());
|
||||
assertFalse(iterator.hasNext(), "String has more than one element");
|
||||
assertFalse("String has more than one element", iterator.hasNext());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSingleSeparatorDefaultDelimiter() {
|
||||
Iterator iterator = createTokenIterator("A B C D");
|
||||
assertTrue(iterator.hasNext(), "String has no elements");
|
||||
assertTrue("String has no elements", iterator.hasNext());
|
||||
assertEquals("A", iterator.next());
|
||||
assertTrue(iterator.hasNext(), "String has no elements");
|
||||
assertTrue("String has no elements", iterator.hasNext());
|
||||
assertEquals("B", iterator.next());
|
||||
assertTrue(iterator.hasNext(), "String has no elements");
|
||||
assertTrue("String has no elements", iterator.hasNext());
|
||||
assertEquals("C", iterator.next());
|
||||
assertTrue(iterator.hasNext(), "String has no elements");
|
||||
assertTrue("String has no elements", iterator.hasNext());
|
||||
assertEquals("D", iterator.next());
|
||||
assertFalse(iterator.hasNext(), "String has more than one element");
|
||||
assertFalse("String has more than one element", iterator.hasNext());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSingleSeparator() {
|
||||
Iterator iterator = createTokenIterator("A,B,C", "[^,]+");
|
||||
assertTrue(iterator.hasNext(), "String has no elements");
|
||||
assertTrue("String has no elements", iterator.hasNext());
|
||||
assertEquals("A", iterator.next());
|
||||
assertTrue(iterator.hasNext(), "String has no elements");
|
||||
assertTrue("String has no elements", iterator.hasNext());
|
||||
assertEquals("B", iterator.next());
|
||||
assertTrue(iterator.hasNext(), "String has no elements");
|
||||
assertTrue("String has no elements", iterator.hasNext());
|
||||
assertEquals("C", iterator.next());
|
||||
assertFalse(iterator.hasNext(), "String has more than one element");
|
||||
assertFalse("String has more than one element", iterator.hasNext());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMultipleSeparatorDefaultDelimiter() {
|
||||
Iterator iterator = createTokenIterator("A B C\nD\t\t \nE");
|
||||
assertTrue(iterator.hasNext(), "String has no elements");
|
||||
assertTrue("String has no elements", iterator.hasNext());
|
||||
assertEquals("A", iterator.next());
|
||||
assertTrue(iterator.hasNext(), "String has no elements");
|
||||
assertTrue("String has no elements", iterator.hasNext());
|
||||
assertEquals("B", iterator.next());
|
||||
assertTrue(iterator.hasNext(), "String has no elements");
|
||||
assertTrue("String has no elements", iterator.hasNext());
|
||||
assertEquals("C", iterator.next());
|
||||
assertTrue(iterator.hasNext(), "String has no elements");
|
||||
assertTrue("String has no elements", iterator.hasNext());
|
||||
assertEquals("D", iterator.next());
|
||||
assertTrue(iterator.hasNext(), "String has no elements");
|
||||
assertTrue("String has no elements", iterator.hasNext());
|
||||
assertEquals("E", iterator.next());
|
||||
assertFalse(iterator.hasNext(), "String has more than one element");
|
||||
assertFalse("String has more than one element", iterator.hasNext());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMultipleSeparator() {
|
||||
Iterator iterator = createTokenIterator("A,B,;,C...D, ., ,E", "[^ ,.;:]+");
|
||||
assertTrue(iterator.hasNext(), "String has no elements");
|
||||
assertTrue("String has no elements", iterator.hasNext());
|
||||
Object o = iterator.next();
|
||||
assertEquals("A", o);
|
||||
assertTrue(iterator.hasNext(), "String has no elements");
|
||||
assertTrue("String has no elements", iterator.hasNext());
|
||||
assertEquals("B", iterator.next());
|
||||
assertTrue(iterator.hasNext(), "String has no elements");
|
||||
assertTrue("String has no elements", iterator.hasNext());
|
||||
assertEquals("C", iterator.next());
|
||||
assertTrue(iterator.hasNext(), "String has no elements");
|
||||
assertTrue("String has no elements", iterator.hasNext());
|
||||
assertEquals("D", iterator.next());
|
||||
assertTrue(iterator.hasNext(), "String has no elements");
|
||||
assertTrue("String has no elements", iterator.hasNext());
|
||||
assertEquals("E", iterator.next());
|
||||
assertFalse(iterator.hasNext(), "String has more than one element");
|
||||
assertFalse("String has more than one element", iterator.hasNext());
|
||||
}
|
||||
}
|
||||
|
||||
+8
-12
@@ -30,13 +30,12 @@
|
||||
|
||||
package com.twelvemonkeys.util.service;
|
||||
|
||||
import com.twelvemonkeys.lang.Validate;
|
||||
import com.twelvemonkeys.util.CollectionUtil;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* ServiceRegistryTest
|
||||
@@ -49,11 +48,9 @@ public class ServiceRegistryTest {
|
||||
|
||||
private final TestRegistry registry = new TestRegistry();
|
||||
|
||||
@Test
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testCreateNull() {
|
||||
assertThrows(IllegalArgumentException.class, () -> {
|
||||
new ServiceRegistry(null);
|
||||
});
|
||||
new ServiceRegistry(null);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -67,12 +64,11 @@ public class ServiceRegistryTest {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@Test(expected = ServiceConfigurationError.class)
|
||||
public void testCreateBadConfig() {
|
||||
assertThrows(ServiceConfigurationError.class, () -> {
|
||||
ServiceRegistry registry = new ServiceRegistry(Arrays.asList(BadSPI.class).iterator());
|
||||
registry.registerApplicationClasspathSPIs();
|
||||
});
|
||||
@SuppressWarnings("unchecked")
|
||||
ServiceRegistry registry = new ServiceRegistry(Arrays.asList(BadSPI.class).iterator());
|
||||
registry.registerApplicationClasspathSPIs();
|
||||
|
||||
// DONE: Test non-class
|
||||
|
||||
|
||||
+4
-15
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<groupId>com.twelvemonkeys</groupId>
|
||||
<artifactId>twelvemonkeys</artifactId>
|
||||
<version>3.13.0</version>
|
||||
<version>3.8.3</version>
|
||||
</parent>
|
||||
<groupId>com.twelvemonkeys.common</groupId>
|
||||
<artifactId>common</artifactId>
|
||||
@@ -20,10 +20,6 @@
|
||||
<module>common-image</module>
|
||||
</modules>
|
||||
|
||||
<properties>
|
||||
<junit.jupiter.version>5.14.1</junit.jupiter.version>
|
||||
</properties>
|
||||
|
||||
<dependencyManagement>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
@@ -47,18 +43,11 @@
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter-api</artifactId>
|
||||
<version>${junit.jupiter.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter-params</artifactId>
|
||||
<version>${junit.jupiter.version}</version>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>4.13.1</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
+6
-25
@@ -4,20 +4,15 @@
|
||||
<parent>
|
||||
<groupId>com.twelvemonkeys</groupId>
|
||||
<artifactId>twelvemonkeys</artifactId>
|
||||
<version>3.13.0</version>
|
||||
<version>3.8.3</version>
|
||||
</parent>
|
||||
<groupId>com.twelvemonkeys.contrib</groupId>
|
||||
<artifactId>contrib</artifactId>
|
||||
<name>TwelveMonkeys :: Contrib</name>
|
||||
<description>
|
||||
Contributions to TwelveMonkeys and code that doesn't fit anywhere else.
|
||||
Contributions to TwelveMonkeys which are not matching into the ImageIO plug-ins.
|
||||
</description>
|
||||
|
||||
<properties>
|
||||
<junit.jupiter.version>5.14.1</junit.jupiter.version>
|
||||
</properties>
|
||||
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.twelvemonkeys.common</groupId>
|
||||
@@ -66,26 +61,12 @@
|
||||
<type>test-jar</type>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter-engine</artifactId>
|
||||
<version>${junit.jupiter.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter-api</artifactId>
|
||||
<version>${junit.jupiter.version}</version>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>4.13.1</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.felix</groupId>
|
||||
<artifactId>maven-bundle-plugin</artifactId>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
package com.twelvemonkeys.contrib.exif;
|
||||
|
||||
import static com.twelvemonkeys.contrib.exif.Orientation.*;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static com.twelvemonkeys.contrib.exif.Orientation.*;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
/**
|
||||
* OrientationTest.
|
||||
|
||||
@@ -34,6 +34,8 @@ import com.twelvemonkeys.contrib.tiff.TIFFUtilities.TIFFExtension;
|
||||
import com.twelvemonkeys.imageio.plugins.tiff.TIFFImageMetadataFormat;
|
||||
import com.twelvemonkeys.io.FileUtil;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.w3c.dom.Node;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
@@ -52,9 +54,6 @@ import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
/**
|
||||
* TIFFUtilitiesTest
|
||||
*
|
||||
@@ -96,7 +95,7 @@ public class TIFFUtilitiesTest {
|
||||
ImageInputStream iis = ImageIO.createImageInputStream(output);
|
||||
ImageReader reader = ImageIO.getImageReaders(iis).next();
|
||||
reader.setInput(iis);
|
||||
assertEquals(3, reader.getNumImages(true));
|
||||
Assert.assertEquals(3, reader.getNumImages(true));
|
||||
|
||||
iis.close();
|
||||
output.delete();
|
||||
@@ -120,11 +119,11 @@ public class TIFFUtilitiesTest {
|
||||
ImageReader reader = ImageIO.getImageReadersByFormatName("TIF").next();
|
||||
|
||||
File[] outputFiles = outputDirectory.listFiles();
|
||||
assertEquals(3, outputFiles.length);
|
||||
Assert.assertEquals(3, outputFiles.length);
|
||||
for (File outputFile : outputFiles) {
|
||||
ImageInputStream iis = ImageIO.createImageInputStream(outputFile);
|
||||
reader.setInput(iis);
|
||||
assertEquals(1, reader.getNumImages(true));
|
||||
Assert.assertEquals(1, reader.getNumImages(true));
|
||||
iis.close();
|
||||
outputFile.delete();
|
||||
}
|
||||
@@ -158,7 +157,7 @@ public class TIFFUtilitiesTest {
|
||||
Node metaData = reader.getImageMetadata(i)
|
||||
.getAsTree(TIFFImageMetadataFormat.SUN_NATIVE_IMAGE_METADATA_FORMAT_NAME);
|
||||
short orientation = ((Number) expression.evaluate(metaData, XPathConstants.NUMBER)).shortValue();
|
||||
assertEquals(orientation, TIFFExtension.ORIENTATION_RIGHTTOP);
|
||||
Assert.assertEquals(orientation, TIFFExtension.ORIENTATION_RIGHTTOP);
|
||||
}
|
||||
checkTest1.close();
|
||||
|
||||
@@ -175,7 +174,7 @@ public class TIFFUtilitiesTest {
|
||||
Node metaData = reader.getImageMetadata(i)
|
||||
.getAsTree(TIFFImageMetadataFormat.SUN_NATIVE_IMAGE_METADATA_FORMAT_NAME);
|
||||
short orientation = ((Number) expression.evaluate(metaData, XPathConstants.NUMBER)).shortValue();
|
||||
assertEquals(orientation, i == 1
|
||||
Assert.assertEquals(orientation, i == 1
|
||||
? TIFFExtension.ORIENTATION_BOTRIGHT
|
||||
: TIFFExtension.ORIENTATION_RIGHTTOP);
|
||||
}
|
||||
@@ -200,7 +199,7 @@ public class TIFFUtilitiesTest {
|
||||
byte[] original = ((DataBufferByte) image.getData().getDataBuffer()).getData();
|
||||
byte[] rotated = ((DataBufferByte) image360.getData().getDataBuffer()).getData();
|
||||
|
||||
assertArrayEquals(original, rotated);
|
||||
Assert.assertArrayEquals(original, rotated);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<groupId>com.twelvemonkeys.imageio</groupId>
|
||||
<artifactId>imageio</artifactId>
|
||||
<version>3.13.0</version>
|
||||
<version>3.8.3</version>
|
||||
</parent>
|
||||
<artifactId>imageio-batik</artifactId>
|
||||
<name>TwelveMonkeys :: ImageIO :: Batik Plugin</name>
|
||||
@@ -17,7 +17,7 @@
|
||||
|
||||
<properties>
|
||||
<project.jpms.module.name>com.twelvemonkeys.imageio.batik</project.jpms.module.name>
|
||||
<batik.version>1.19</batik.version>
|
||||
<batik.version>1.14</batik.version>
|
||||
</properties>
|
||||
|
||||
<build>
|
||||
@@ -33,18 +33,6 @@
|
||||
</systemPropertyVariables>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.felix</groupId>
|
||||
<artifactId>maven-bundle-plugin</artifactId>
|
||||
<configuration>
|
||||
<instructions>
|
||||
<Provide-Capability>
|
||||
osgi.serviceloader;
|
||||
osgi.serviceloader=javax.imageio.spi.ImageReaderSpi
|
||||
</Provide-Capability>
|
||||
</instructions>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
@@ -63,7 +51,7 @@
|
||||
<dependency>
|
||||
<groupId>commons-io</groupId>
|
||||
<artifactId>commons-io</artifactId>
|
||||
<version>2.21.0</version>
|
||||
<version>2.11.0</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
|
||||
+32
-34
@@ -33,7 +33,6 @@ package com.twelvemonkeys.imageio.plugins.svg;
|
||||
import com.twelvemonkeys.image.ImageUtil;
|
||||
import com.twelvemonkeys.imageio.ImageReaderBase;
|
||||
import com.twelvemonkeys.imageio.util.IIOUtil;
|
||||
import com.twelvemonkeys.imageio.util.ImageTypeSpecifiers;
|
||||
import com.twelvemonkeys.lang.StringUtil;
|
||||
|
||||
import org.apache.batik.anim.dom.SVGDOMImplementation;
|
||||
@@ -92,10 +91,10 @@ public class SVGImageReader extends ImageReaderBase {
|
||||
/**
|
||||
* Creates an {@code SVGImageReader}.
|
||||
*
|
||||
* @param provider the provider
|
||||
* @param pProvider the provider
|
||||
*/
|
||||
public SVGImageReader(final ImageReaderSpi provider) {
|
||||
super(provider);
|
||||
public SVGImageReader(final ImageReaderSpi pProvider) {
|
||||
super(pProvider);
|
||||
}
|
||||
|
||||
protected void resetMembers() {
|
||||
@@ -109,20 +108,20 @@ public class SVGImageReader extends ImageReaderBase {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setInput(Object input, boolean seekForwardOnly, boolean ignoreMetadata) {
|
||||
super.setInput(input, seekForwardOnly, ignoreMetadata);
|
||||
public void setInput(Object pInput, boolean seekForwardOnly, boolean ignoreMetadata) {
|
||||
super.setInput(pInput, seekForwardOnly, ignoreMetadata);
|
||||
|
||||
if (imageInput != null) {
|
||||
TranscoderInput transcoderInput = new TranscoderInput(IIOUtil.createStreamAdapter(imageInput));
|
||||
rasterizer.setInput(transcoderInput);
|
||||
TranscoderInput input = new TranscoderInput(IIOUtil.createStreamAdapter(imageInput));
|
||||
rasterizer.setInput(input);
|
||||
}
|
||||
}
|
||||
|
||||
public BufferedImage read(int imageIndex, ImageReadParam param) throws IOException {
|
||||
checkBounds(imageIndex);
|
||||
public BufferedImage read(int pIndex, ImageReadParam pParam) throws IOException {
|
||||
checkBounds(pIndex);
|
||||
|
||||
if (param instanceof SVGReadParam) {
|
||||
SVGReadParam svgParam = (SVGReadParam) param;
|
||||
if (pParam instanceof SVGReadParam) {
|
||||
SVGReadParam svgParam = (SVGReadParam) pParam;
|
||||
|
||||
// set the external-resource-resolution preference
|
||||
allowExternalResources = svgParam.isAllowExternalResources();
|
||||
@@ -140,17 +139,17 @@ public class SVGImageReader extends ImageReaderBase {
|
||||
}
|
||||
|
||||
Dimension size = null;
|
||||
if (param != null) {
|
||||
size = param.getSourceRenderSize();
|
||||
if (pParam != null) {
|
||||
size = pParam.getSourceRenderSize();
|
||||
}
|
||||
if (size == null) {
|
||||
size = new Dimension(getWidth(imageIndex), getHeight(imageIndex));
|
||||
size = new Dimension(getWidth(pIndex), getHeight(pIndex));
|
||||
}
|
||||
|
||||
BufferedImage destination = getDestination(param, getImageTypes(imageIndex), size.width, size.height);
|
||||
BufferedImage destination = getDestination(pParam, getImageTypes(pIndex), size.width, size.height);
|
||||
|
||||
// Read in the image, using the Batik Transcoder
|
||||
processImageStarted(imageIndex);
|
||||
processImageStarted(pIndex);
|
||||
|
||||
BufferedImage image = rasterizer.getImage();
|
||||
|
||||
@@ -174,18 +173,18 @@ public class SVGImageReader extends ImageReaderBase {
|
||||
return ex.getException() != null ? ex.getException() : ex;
|
||||
}
|
||||
|
||||
private TranscodingHints paramsToHints(SVGReadParam param) throws IOException {
|
||||
private TranscodingHints paramsToHints(SVGReadParam pParam) throws IOException {
|
||||
TranscodingHints hints = new TranscodingHints();
|
||||
// Note: We must allow generic ImageReadParams, so converting to
|
||||
// TanscodingHints should be done outside the SVGReadParam class.
|
||||
|
||||
// Set dimensions
|
||||
Dimension size = param.getSourceRenderSize();
|
||||
Dimension size = pParam.getSourceRenderSize();
|
||||
Rectangle viewBox = rasterizer.getViewBox();
|
||||
if (size == null) {
|
||||
// SVG is not a pixel based format, but we'll scale it, according to
|
||||
// the subsampling for compatibility
|
||||
size = getSourceRenderSizeFromSubsamping(param, viewBox.getSize());
|
||||
size = getSourceRenderSizeFromSubsamping(pParam, viewBox.getSize());
|
||||
}
|
||||
|
||||
if (size != null) {
|
||||
@@ -194,7 +193,7 @@ public class SVGImageReader extends ImageReaderBase {
|
||||
}
|
||||
|
||||
// Set area of interest
|
||||
Rectangle region = param.getSourceRegion();
|
||||
Rectangle region = pParam.getSourceRegion();
|
||||
if (region != null) {
|
||||
hints.put(ImageTranscoder.KEY_AOI, region);
|
||||
|
||||
@@ -218,7 +217,7 @@ public class SVGImageReader extends ImageReaderBase {
|
||||
}
|
||||
|
||||
// Background color
|
||||
Paint bg = param.getBackgroundColor();
|
||||
Paint bg = pParam.getBackgroundColor();
|
||||
if (bg != null) {
|
||||
hints.put(ImageTranscoder.KEY_BACKGROUND_COLOR, bg);
|
||||
}
|
||||
@@ -226,10 +225,10 @@ public class SVGImageReader extends ImageReaderBase {
|
||||
return hints;
|
||||
}
|
||||
|
||||
private Dimension getSourceRenderSizeFromSubsamping(ImageReadParam param, Dimension origSize) {
|
||||
if (param.getSourceXSubsampling() > 1 || param.getSourceYSubsampling() > 1) {
|
||||
return new Dimension((int) (origSize.width / (float) param.getSourceXSubsampling()),
|
||||
(int) (origSize.height / (float) param.getSourceYSubsampling()));
|
||||
private Dimension getSourceRenderSizeFromSubsamping(ImageReadParam pParam, Dimension pOrigSize) {
|
||||
if (pParam.getSourceXSubsampling() > 1 || pParam.getSourceYSubsampling() > 1) {
|
||||
return new Dimension((int) (pOrigSize.width / (float) pParam.getSourceXSubsampling()),
|
||||
(int) (pOrigSize.height / (float) pParam.getSourceYSubsampling()));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@@ -238,19 +237,19 @@ public class SVGImageReader extends ImageReaderBase {
|
||||
return new SVGReadParam();
|
||||
}
|
||||
|
||||
public int getWidth(int imageIndex) throws IOException {
|
||||
checkBounds(imageIndex);
|
||||
public int getWidth(int pIndex) throws IOException {
|
||||
checkBounds(pIndex);
|
||||
|
||||
return rasterizer.getDefaultWidth();
|
||||
}
|
||||
|
||||
public int getHeight(int imageIndex) throws IOException {
|
||||
checkBounds(imageIndex);
|
||||
public int getHeight(int pIndex) throws IOException {
|
||||
checkBounds(pIndex);
|
||||
return rasterizer.getDefaultHeight();
|
||||
}
|
||||
|
||||
public Iterator<ImageTypeSpecifier> getImageTypes(int imageIndex) {
|
||||
return Collections.singleton(ImageTypeSpecifiers.createFromRenderedImage(rasterizer.createImage(1, 1))).iterator();
|
||||
return Collections.singleton(ImageTypeSpecifier.createFromRenderedImage(rasterizer.createImage(1, 1))).iterator();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -602,7 +601,6 @@ public class SVGImageReader extends ImageReaderBase {
|
||||
initialized = true;
|
||||
|
||||
try {
|
||||
super.addTranscodingHint(SVGAbstractTranscoder.KEY_ALLOW_EXTERNAL_RESOURCES, allowExternalResources);
|
||||
super.transcode(transcoderInput, null);
|
||||
}
|
||||
catch (TranscoderException e) {
|
||||
@@ -635,8 +633,8 @@ public class SVGImageReader extends ImageReaderBase {
|
||||
return viewBox.getBounds();
|
||||
}
|
||||
|
||||
void setInput(final TranscoderInput input) {
|
||||
transcoderInput = input;
|
||||
void setInput(final TranscoderInput pInput) {
|
||||
transcoderInput = pInput;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+15
-60
@@ -36,11 +36,9 @@ import com.twelvemonkeys.lang.SystemUtil;
|
||||
import javax.imageio.ImageReader;
|
||||
import javax.imageio.spi.ServiceRegistry;
|
||||
import javax.imageio.stream.ImageInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.EOFException;
|
||||
import java.io.IOException;
|
||||
import java.util.Locale;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import static com.twelvemonkeys.imageio.util.IIOUtil.deregisterProvider;
|
||||
|
||||
@@ -62,22 +60,22 @@ public final class SVGImageReaderSpi extends ImageReaderSpiBase {
|
||||
super(new SVGProviderInfo());
|
||||
}
|
||||
|
||||
public boolean canDecodeInput(final Object source) throws IOException {
|
||||
return source instanceof ImageInputStream && canDecode((ImageInputStream) source);
|
||||
public boolean canDecodeInput(final Object pSource) throws IOException {
|
||||
return pSource instanceof ImageInputStream && canDecode((ImageInputStream) pSource);
|
||||
}
|
||||
|
||||
@SuppressWarnings("StatementWithEmptyBody")
|
||||
private static boolean canDecode(final ImageInputStream input) throws IOException {
|
||||
private static boolean canDecode(final ImageInputStream pInput) throws IOException {
|
||||
// NOTE: This test is quite quick as it does not involve any parsing,
|
||||
// however it may not recognize all kinds of SVG documents.
|
||||
try {
|
||||
input.mark();
|
||||
pInput.mark();
|
||||
|
||||
// TODO: This is not ok for UTF-16 and other wide encodings
|
||||
// TODO: Use an XML (encoding) aware Reader instance instead
|
||||
// Need to figure out pretty fast if this is XML or not
|
||||
int b;
|
||||
while (Character.isWhitespace((char) (b = input.read()))) {
|
||||
while (Character.isWhitespace((char) (b = pInput.read()))) {
|
||||
// Skip over leading WS
|
||||
}
|
||||
|
||||
@@ -97,30 +95,30 @@ public final class SVGImageReaderSpi extends ImageReaderSpiBase {
|
||||
|
||||
byte[] buffer = new byte[4];
|
||||
while (true) {
|
||||
input.readFully(buffer);
|
||||
pInput.readFully(buffer);
|
||||
|
||||
if (buffer[0] == '?') {
|
||||
// This is the XML declaration or a processing instruction
|
||||
while (!((input.readByte() & 0xFF) == '?' && input.read() == '>')) {
|
||||
while (!((pInput.readByte() & 0xFF) == '?' && pInput.read() == '>')) {
|
||||
// Skip until end of XML declaration or processing instruction or EOF
|
||||
}
|
||||
}
|
||||
else if (buffer[0] == '!') {
|
||||
if (buffer[1] == '-' && buffer[2] == '-') {
|
||||
// This is a comment
|
||||
while (!((input.readByte() & 0xFF) == '-' && input.read() == '-' && input.read() == '>')) {
|
||||
while (!((pInput.readByte() & 0xFF) == '-' && pInput.read() == '-' && pInput.read() == '>')) {
|
||||
// Skip until end of comment or EOF
|
||||
}
|
||||
}
|
||||
else if (buffer[1] == 'D' && buffer[2] == 'O' && buffer[3] == 'C'
|
||||
&& input.read() == 'T' && input.read() == 'Y'
|
||||
&& input.read() == 'P' && input.read() == 'E') {
|
||||
&& pInput.read() == 'T' && pInput.read() == 'Y'
|
||||
&& pInput.read() == 'P' && pInput.read() == 'E') {
|
||||
// This is the DOCTYPE declaration
|
||||
while (Character.isWhitespace((char) (b = input.read()))) {
|
||||
while (Character.isWhitespace((char) (b = pInput.read()))) {
|
||||
// Skip over WS
|
||||
}
|
||||
|
||||
if (b == 's' && input.read() == 'v' && input.read() == 'g') {
|
||||
if (b == 's' && pInput.read() == 'v' && pInput.read() == 'g') {
|
||||
// It's SVG, identified by DOCTYPE
|
||||
return true;
|
||||
}
|
||||
@@ -136,47 +134,15 @@ public final class SVGImageReaderSpi extends ImageReaderSpiBase {
|
||||
if (buffer[0] == 's' && buffer[1] == 'v' && buffer[2] == 'g'
|
||||
&& (Character.isWhitespace((char) buffer[3]) || buffer[3] == ':')) {
|
||||
// It's SVG, identified by root tag
|
||||
// TODO: Support svg with prefix + recognize namespace (http://www.w3.org/2000/svg)!
|
||||
return true;
|
||||
}
|
||||
|
||||
// Read the full tag name (may contain a prefix of any length)
|
||||
final int MAX_TAG_NAME = 256;
|
||||
ByteArrayOutputStream nameBuf = new ByteArrayOutputStream(MAX_TAG_NAME);
|
||||
|
||||
// We already have 4 bytes in 'buffer' (from input.readFully(buffer))
|
||||
int consumedFromBuffer = 0;
|
||||
for (; consumedFromBuffer < buffer.length; consumedFromBuffer++) {
|
||||
byte bb = buffer[consumedFromBuffer];
|
||||
if (bb == '>' || Character.isWhitespace((char) bb) || bb == '/') {
|
||||
break;
|
||||
}
|
||||
nameBuf.write(bb);
|
||||
}
|
||||
|
||||
// If tag name not terminated yet, keep reading bytes (within limit)
|
||||
final boolean incompleteTagName = consumedFromBuffer == buffer.length;
|
||||
readBuffer(input, nameBuf, output -> incompleteTagName && output.size() < MAX_TAG_NAME,
|
||||
bb -> bb == '>' || Character.isWhitespace(bb) || bb == '/');
|
||||
|
||||
final String name = nameBuf.toString("US-ASCII");
|
||||
if (name.toLowerCase(Locale.ENGLISH).endsWith(":svg")) {
|
||||
// Scan the rest of the tag attributes until '>' to find the SVG namespace URI
|
||||
ByteArrayOutputStream attrBuf = new ByteArrayOutputStream();
|
||||
final int MAX_ATTR_SCAN = 1024; // safe upper bound to keep it fast
|
||||
readBuffer(input, attrBuf, output -> output.size() < MAX_ATTR_SCAN, bb -> bb == '>');
|
||||
|
||||
// If the tag contains the SVG namespace, it's SVG.
|
||||
if (attrBuf.toString("US-ASCII").matches(
|
||||
".*xmlns:" + name.split(":")[0] + "\\s*=\\s*\"http://www.w3.org/2000/svg\".*")) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// If the tag is not "svg", this isn't SVG
|
||||
return false;
|
||||
}
|
||||
|
||||
while ((input.readByte() & 0xFF) != '<') {
|
||||
while ((pInput.readByte() & 0xFF) != '<') {
|
||||
// Skip over, until next begin tag or EOF
|
||||
}
|
||||
}
|
||||
@@ -187,18 +153,7 @@ public final class SVGImageReaderSpi extends ImageReaderSpiBase {
|
||||
}
|
||||
finally {
|
||||
//noinspection ThrowFromFinallyBlock
|
||||
input.reset();
|
||||
}
|
||||
}
|
||||
|
||||
private static void readBuffer(final ImageInputStream input, final ByteArrayOutputStream buffer,
|
||||
final Predicate<ByteArrayOutputStream> loopCondition, Predicate<Byte> breakCondition) throws IOException {
|
||||
while (loopCondition.test(buffer)) {
|
||||
byte bb = input.readByte();
|
||||
if (breakCondition.test(bb)) {
|
||||
break;
|
||||
}
|
||||
buffer.write(bb);
|
||||
pInput.reset();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+4
-4
@@ -51,16 +51,16 @@ public class SVGReadParam extends ImageReadParam {
|
||||
return background;
|
||||
}
|
||||
|
||||
public void setBackgroundColor(Paint color) {
|
||||
background = color;
|
||||
public void setBackgroundColor(Paint pColor) {
|
||||
background = pColor;
|
||||
}
|
||||
|
||||
public String getBaseURI() {
|
||||
return baseURI;
|
||||
}
|
||||
|
||||
public void setBaseURI(String baseURI) {
|
||||
this.baseURI = baseURI;
|
||||
public void setBaseURI(String pBaseURI) {
|
||||
baseURI = pBaseURI;
|
||||
}
|
||||
|
||||
public void setAllowExternalResources(boolean allow) {
|
||||
|
||||
+10
-15
@@ -32,16 +32,16 @@ package com.twelvemonkeys.imageio.plugins.svg;
|
||||
|
||||
import com.twelvemonkeys.imageio.stream.ByteArrayImageInputStream;
|
||||
import com.twelvemonkeys.imageio.stream.URLImageInputStreamSpi;
|
||||
import org.junit.Test;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import javax.imageio.spi.IIORegistry;
|
||||
import javax.imageio.spi.ImageReaderSpi;
|
||||
import javax.imageio.stream.ImageInputStream;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.time.Duration;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
/**
|
||||
* SVGImageReaderSpiTest.
|
||||
@@ -56,7 +56,7 @@ public class SVGImageReaderSpiTest {
|
||||
"/svg/Android_robot.svg", // Minimal, no xml dec, no namespace
|
||||
"/svg/batikLogo.svg", // xml dec, comments, namespace
|
||||
"/svg/blue-square.svg", // xml dec, namespace
|
||||
"/svg/red-square.svg", // prefixed namespace
|
||||
"/svg/red-square.svg",
|
||||
};
|
||||
|
||||
private static final String[] INVALID_INPUTS = {
|
||||
@@ -70,9 +70,6 @@ public class SVGImageReaderSpiTest {
|
||||
"<!-- ", // #275 Infinite loop issue
|
||||
"<?123?>", // #275 Infinite loop issue
|
||||
"<svg",
|
||||
"<ns0:svg>", // namespace prefix undefined
|
||||
"<ns0:svg xmlns:ns0=\"foo\">", // not the official svg namespace
|
||||
"<ns0:svg xmlns:ns1=\"http://www.w3.org/2000/svg\">", // mismatching prefix
|
||||
};
|
||||
|
||||
static {
|
||||
@@ -86,20 +83,18 @@ public class SVGImageReaderSpiTest {
|
||||
public void canDecodeInput() throws Exception {
|
||||
for (String validInput : VALID_INPUTS) {
|
||||
try (ImageInputStream input = ImageIO.createImageInputStream(getClass().getResource(validInput))) {
|
||||
assertTrue(provider.canDecodeInput(input), "Can't read valid input: " + validInput);
|
||||
assertTrue("Can't read valid input: " + validInput, provider.canDecodeInput(input));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Test will time out, if EOFs are not properly detected, see #275
|
||||
@Test
|
||||
@Test(timeout = 5000)
|
||||
public void canDecodeInputInvalid() throws Exception {
|
||||
assertTimeoutPreemptively(Duration.ofMillis(5000), () -> {
|
||||
for (String invalidInput : INVALID_INPUTS) {
|
||||
try (ImageInputStream input = new ByteArrayImageInputStream(invalidInput.getBytes(StandardCharsets.UTF_8))) {
|
||||
assertFalse(provider.canDecodeInput(input), "Claims to read invalid input:" + invalidInput);
|
||||
}
|
||||
for (String invalidInput : INVALID_INPUTS) {
|
||||
try (ImageInputStream input = new ByteArrayImageInputStream(invalidInput.getBytes(StandardCharsets.UTF_8))) {
|
||||
assertFalse("Claims to read invalid input:" + invalidInput, provider.canDecodeInput(input));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
+15
-13
@@ -32,6 +32,9 @@ package com.twelvemonkeys.imageio.plugins.svg;
|
||||
|
||||
import com.twelvemonkeys.imageio.util.ImageReaderAbstractTest;
|
||||
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
|
||||
import javax.imageio.IIOException;
|
||||
import javax.imageio.ImageIO;
|
||||
import javax.imageio.ImageReadParam;
|
||||
@@ -49,9 +52,10 @@ import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
/**
|
||||
@@ -124,18 +128,18 @@ public class SVGImageReaderTest extends ImageReaderAbstractTest<SVGImageReader>
|
||||
int current = image.getRGB(x, y);
|
||||
if (x < quadPoint) {
|
||||
if (y < quadPoint) {
|
||||
assertEquals( 0xFF0000FF, current, "x=" + x + " y=" + y + " q=" + quadPoint);
|
||||
assertEquals("x=" + x + " y=" + y + " q=" + quadPoint, 0xFF0000FF, current);
|
||||
}
|
||||
else {
|
||||
assertEquals(0xFFFF0000, current, "x=" + x + " y=" + y + " q=" + quadPoint);
|
||||
assertEquals("x=" + x + " y=" + y + " q=" + quadPoint, 0xFFFF0000, current);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (y < quadPoint) {
|
||||
assertEquals(0xFF00FF00, current, "x=" + x + " y=" + y + " q=" + quadPoint);
|
||||
assertEquals("x=" + x + " y=" + y + " q=" + quadPoint, 0xFF00FF00, current);
|
||||
}
|
||||
else {
|
||||
assertEquals(0xFF000000, current, "x=" + x + " y=" + y + " q=" + quadPoint);
|
||||
assertEquals("x=" + x + " y=" + y + " q=" + quadPoint, 0xFF000000, current);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -167,14 +171,14 @@ public class SVGImageReaderTest extends ImageReaderAbstractTest<SVGImageReader>
|
||||
}
|
||||
|
||||
@Test
|
||||
@Disabled("Known issue: Source region reading not supported")
|
||||
@Ignore("Known issue: Source region reading not supported")
|
||||
@Override
|
||||
public void testReadWithSourceRegionParamEqualImage() throws IOException {
|
||||
super.testReadWithSourceRegionParamEqualImage();
|
||||
}
|
||||
|
||||
@Test
|
||||
@Disabled("Known issue: Subsampled reading not supported")
|
||||
@Ignore("Known issue: Subsampled reading not supported")
|
||||
@Override
|
||||
public void testReadWithSubsampleParamPixels() throws IOException {
|
||||
super.testReadWithSubsampleParamPixels();
|
||||
@@ -312,7 +316,7 @@ public class SVGImageReaderTest extends ImageReaderAbstractTest<SVGImageReader>
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@Test(expected = SecurityException.class)
|
||||
public void testDisallowedExternalResources() throws URISyntaxException, IOException {
|
||||
// system-property set to true in surefire-plugin-settings in the pom
|
||||
URL resource = getClassLoaderResource("/svg/barChart.svg");
|
||||
@@ -329,9 +333,7 @@ public class SVGImageReaderTest extends ImageReaderAbstractTest<SVGImageReader>
|
||||
// `reader.read` for `/svg/barChart.svg` should raise
|
||||
// a SecurityException when External Resources are blocked
|
||||
// because the API invocation gets preference
|
||||
assertThrows(SecurityException.class, () -> {
|
||||
reader.read(0, param);
|
||||
});
|
||||
reader.read(0, param);
|
||||
}
|
||||
finally {
|
||||
reader.dispose();
|
||||
|
||||
+5
-4
@@ -32,6 +32,9 @@ package com.twelvemonkeys.imageio.plugins.wmf;
|
||||
|
||||
import com.twelvemonkeys.imageio.util.ImageReaderAbstractTest;
|
||||
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
|
||||
import javax.imageio.spi.ImageReaderSpi;
|
||||
import java.awt.*;
|
||||
import java.io.IOException;
|
||||
@@ -39,8 +42,6 @@ import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.Test;
|
||||
/**
|
||||
* WMFImageReaderTest
|
||||
*
|
||||
@@ -76,14 +77,14 @@ public class WMFImageReaderTest extends ImageReaderAbstractTest<WMFImageReader>
|
||||
}
|
||||
|
||||
@Test
|
||||
@Disabled("Known issue: Source region reading not supported")
|
||||
@Ignore("Known issue: Source region reading not supported")
|
||||
@Override
|
||||
public void testReadWithSourceRegionParamEqualImage() throws IOException {
|
||||
super.testReadWithSourceRegionParamEqualImage();
|
||||
}
|
||||
|
||||
@Test
|
||||
@Disabled("Known issue: Subsampled reading not supported")
|
||||
@Ignore("Known issue: Subsampled reading not supported")
|
||||
@Override
|
||||
public void testReadWithSubsampleParamPixels() throws IOException {
|
||||
super.testReadWithSubsampleParamPixels();
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<ns0:svg xmlns:ns0="http://www.w3.org/2000/svg" width="100" height="100" id="red-square" version="1.1">
|
||||
<ns0:g id="layer1">
|
||||
<ns0:rect id="rect2985" width="100" height="100" x="0" y="0"
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100" id="red-square" version="1.1">
|
||||
<g id="layer1">
|
||||
<rect id="rect2985" width="100" height="100" x="0" y="0"
|
||||
style="color:#000000;fill:#ff0000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
|
||||
</ns0:g>
|
||||
</ns0:svg>
|
||||
</g>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 465 B After Width: | Height: | Size: 441 B |
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<groupId>com.twelvemonkeys.imageio</groupId>
|
||||
<artifactId>imageio</artifactId>
|
||||
<version>3.13.0</version>
|
||||
<version>3.8.3</version>
|
||||
</parent>
|
||||
<artifactId>imageio-bmp</artifactId>
|
||||
<name>TwelveMonkeys :: ImageIO :: BMP plugin</name>
|
||||
@@ -26,23 +26,4 @@
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.felix</groupId>
|
||||
<artifactId>maven-bundle-plugin</artifactId>
|
||||
<configuration>
|
||||
<instructions>
|
||||
<Provide-Capability>
|
||||
osgi.serviceloader;
|
||||
osgi.serviceloader=javax.imageio.spi.ImageReaderSpi,
|
||||
osgi.serviceloader;
|
||||
osgi.serviceloader=javax.imageio.spi.ImageWriterSpi
|
||||
</Provide-Capability>
|
||||
</instructions>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
|
||||
+13
-14
@@ -81,8 +81,8 @@ public final class BMPImageReader extends ImageReaderBase {
|
||||
super(new BMPImageReaderSpi());
|
||||
}
|
||||
|
||||
BMPImageReader(final ImageReaderSpi provider) {
|
||||
super(provider);
|
||||
BMPImageReader(final ImageReaderSpi pProvider) {
|
||||
super(pProvider);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -129,7 +129,6 @@ public final class BMPImageReader extends ImageReaderBase {
|
||||
|
||||
// Read DIB header
|
||||
header = DIBHeader.read(imageInput);
|
||||
// System.out.println("header = " + header);
|
||||
|
||||
if (pixelOffset < header.size + DIB.BMP_FILE_HEADER_SIZE) {
|
||||
throw new IIOException("Invalid pixel offset: " + pixelOffset);
|
||||
@@ -187,30 +186,30 @@ public final class BMPImageReader extends ImageReaderBase {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getWidth(int imageIndex) throws IOException {
|
||||
checkBounds(imageIndex);
|
||||
public int getWidth(int pImageIndex) throws IOException {
|
||||
checkBounds(pImageIndex);
|
||||
|
||||
return header.getWidth();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getHeight(int imageIndex) throws IOException {
|
||||
checkBounds(imageIndex);
|
||||
public int getHeight(int pImageIndex) throws IOException {
|
||||
checkBounds(pImageIndex);
|
||||
|
||||
return header.getHeight();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<ImageTypeSpecifier> getImageTypes(int imageIndex) throws IOException {
|
||||
checkBounds(imageIndex);
|
||||
public Iterator<ImageTypeSpecifier> getImageTypes(int pImageIndex) throws IOException {
|
||||
checkBounds(pImageIndex);
|
||||
|
||||
// TODO: Better implementation, include INT_RGB types for 3BYTE_BGR and 4BYTE_ABGR for INT_ARGB
|
||||
return Collections.singletonList(getRawImageType(imageIndex)).iterator();
|
||||
return Collections.singletonList(getRawImageType(pImageIndex)).iterator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ImageTypeSpecifier getRawImageType(int imageIndex) throws IOException {
|
||||
checkBounds(imageIndex);
|
||||
public ImageTypeSpecifier getRawImageType(int pImageIndex) throws IOException {
|
||||
checkBounds(pImageIndex);
|
||||
|
||||
if (header.getPlanes() != 1) {
|
||||
throw new IIOException("Multiple planes not supported");
|
||||
@@ -686,8 +685,8 @@ public final class BMPImageReader extends ImageReaderBase {
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "unchecked", "UnusedDeclaration", "SameParameterValue" })
|
||||
static <T extends Throwable> void throwAs(final Class<T> type, final Throwable throwable) throws T {
|
||||
throw (T) throwable;
|
||||
static <T extends Throwable> void throwAs(final Class<T> pType, final Throwable pThrowable) throws T {
|
||||
throw (T) pThrowable;
|
||||
}
|
||||
|
||||
private class ListenerDelegator extends ProgressListenerBase implements IIOReadUpdateListener, IIOReadWarningListener {
|
||||
|
||||
+8
-8
@@ -65,16 +65,16 @@ public final class BMPImageReaderSpi extends ImageReaderSpiBase {
|
||||
}
|
||||
}
|
||||
|
||||
public boolean canDecodeInput(final Object source) throws IOException {
|
||||
return source instanceof ImageInputStream && canDecode((ImageInputStream) source);
|
||||
public boolean canDecodeInput(final Object pSource) throws IOException {
|
||||
return pSource instanceof ImageInputStream && canDecode((ImageInputStream) pSource);
|
||||
}
|
||||
|
||||
private static boolean canDecode(final ImageInputStream input) throws IOException {
|
||||
private static boolean canDecode(final ImageInputStream pInput) throws IOException {
|
||||
byte[] fileHeader = new byte[18]; // Strictly: file header (14 bytes) + BMP header size field (4 bytes)
|
||||
|
||||
try {
|
||||
input.mark();
|
||||
input.readFully(fileHeader);
|
||||
pInput.mark();
|
||||
pInput.readFully(fileHeader);
|
||||
|
||||
// Magic: BM
|
||||
if (fileHeader[0] != 'B' || fileHeader[1] != 'M') {
|
||||
@@ -112,15 +112,15 @@ public final class BMPImageReaderSpi extends ImageReaderSpiBase {
|
||||
}
|
||||
}
|
||||
finally {
|
||||
input.reset();
|
||||
pInput.reset();
|
||||
}
|
||||
}
|
||||
|
||||
public ImageReader createReaderInstance(final Object extension) {
|
||||
public ImageReader createReaderInstance(final Object pExtension) {
|
||||
return new BMPImageReader(this);
|
||||
}
|
||||
|
||||
public String getDescription(final Locale locale) {
|
||||
public String getDescription(final Locale pLocale) {
|
||||
return "Windows Device Independent Bitmap Format (BMP) Reader";
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -47,7 +47,7 @@ import java.nio.ByteOrder;
|
||||
* BMPImageWriter
|
||||
*/
|
||||
public final class BMPImageWriter extends DIBImageWriter {
|
||||
BMPImageWriter(ImageWriterSpi provider) {
|
||||
protected BMPImageWriter(ImageWriterSpi provider) {
|
||||
super(provider);
|
||||
}
|
||||
|
||||
|
||||
+1
-2
@@ -32,7 +32,6 @@ package com.twelvemonkeys.imageio.plugins.bmp;
|
||||
|
||||
import com.twelvemonkeys.imageio.AbstractMetadata;
|
||||
import com.twelvemonkeys.lang.Validate;
|
||||
|
||||
import org.w3c.dom.Node;
|
||||
|
||||
import javax.imageio.metadata.IIOMetadataNode;
|
||||
@@ -142,7 +141,7 @@ final class BMPMetadata extends AbstractMetadata {
|
||||
@Override
|
||||
protected IIOMetadataNode getStandardChromaNode() {
|
||||
// NOTE: BMP files may contain a color map, even if true color...
|
||||
// Not sure if this is a good idea to expose to the metadata,
|
||||
// Not sure if this is a good idea to expose to the meta data,
|
||||
// as it might be unexpected... Then again...
|
||||
if (colorMap != null) {
|
||||
IIOMetadataNode chroma = new IIOMetadataNode("Chroma");
|
||||
|
||||
+7
-7
@@ -29,11 +29,11 @@
|
||||
*/
|
||||
package com.twelvemonkeys.imageio.plugins.bmp;
|
||||
|
||||
import java.awt.image.*;
|
||||
import java.io.IOException;
|
||||
|
||||
import static com.twelvemonkeys.lang.Validate.notNull;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Describes a bitmap structure.
|
||||
*
|
||||
@@ -47,9 +47,9 @@ abstract class BitmapDescriptor {
|
||||
protected BufferedImage image;
|
||||
protected BitmapMask mask;
|
||||
|
||||
public BitmapDescriptor(final DirectoryEntry entry, final DIBHeader header) {
|
||||
this.entry = notNull(entry, "entry");
|
||||
this.header = notNull(header, "header");
|
||||
public BitmapDescriptor(final DirectoryEntry pEntry, final DIBHeader pHeader) {
|
||||
entry = notNull(pEntry, "entry");;
|
||||
header = notNull(pHeader, "header");
|
||||
}
|
||||
|
||||
abstract public BufferedImage getImage() throws IOException;
|
||||
@@ -75,7 +75,7 @@ abstract class BitmapDescriptor {
|
||||
return getClass().getSimpleName() + "[" + entry + ", " + header + "]";
|
||||
}
|
||||
|
||||
final void setMask(final BitmapMask mask) {
|
||||
public final void setMask(final BitmapMask mask) {
|
||||
this.mask = mask;
|
||||
}
|
||||
|
||||
|
||||
+22
-14
@@ -29,7 +29,10 @@
|
||||
*/
|
||||
package com.twelvemonkeys.imageio.plugins.bmp;
|
||||
|
||||
import java.awt.image.*;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.awt.image.DataBuffer;
|
||||
import java.awt.image.IndexColorModel;
|
||||
import java.awt.image.WritableRaster;
|
||||
import java.util.Hashtable;
|
||||
|
||||
/**
|
||||
@@ -38,13 +41,12 @@ import java.util.Hashtable;
|
||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||
* @version $Id: BitmapIndexed.java,v 1.0 25.feb.2006 00:29:44 haku Exp$
|
||||
*/
|
||||
final class BitmapIndexed extends BitmapDescriptor {
|
||||
final int[] bits;
|
||||
final int[] colors;
|
||||
|
||||
public BitmapIndexed(final DirectoryEntry entry, final DIBHeader header) {
|
||||
super(entry, header);
|
||||
class BitmapIndexed extends BitmapDescriptor {
|
||||
protected final int[] bits;
|
||||
protected final int[] colors;
|
||||
|
||||
public BitmapIndexed(final DirectoryEntry pEntry, final DIBHeader pHeader) {
|
||||
super(pEntry, pHeader);
|
||||
bits = new int[getWidth() * getHeight()];
|
||||
|
||||
// NOTE: We're adding space for one extra color, for transparency
|
||||
@@ -57,16 +59,20 @@ final class BitmapIndexed extends BitmapDescriptor {
|
||||
|
||||
IndexColorModel icm = createColorModel();
|
||||
|
||||
// We add cursor hotspot as a property to images created from CUR format.
|
||||
// This is slightly obscure, and should probably be moved...
|
||||
// This is slightly obscure, and should probably be moved..
|
||||
Hashtable<String, Object> properties = null;
|
||||
if (entry instanceof DirectoryEntry.CUREntry) {
|
||||
properties = new Hashtable<>(1);
|
||||
properties.put("cursor_hotspot", ((DirectoryEntry.CUREntry) this.entry).getHotspot());
|
||||
}
|
||||
|
||||
WritableRaster raster = icm.createCompatibleWritableRaster(getWidth(), getHeight());
|
||||
BufferedImage image = new BufferedImage(icm, raster, icm.isAlphaPremultiplied(), properties);
|
||||
BufferedImage image = new BufferedImage(
|
||||
icm,
|
||||
icm.createCompatibleWritableRaster(getWidth(), getHeight()),
|
||||
icm.isAlphaPremultiplied(), properties
|
||||
);
|
||||
|
||||
WritableRaster raster = image.getRaster();
|
||||
|
||||
// Make pixels transparent according to mask
|
||||
final int trans = icm.getTransparentPixel();
|
||||
@@ -99,7 +105,7 @@ final class BitmapIndexed extends BitmapDescriptor {
|
||||
int index = findTransparentIndexMaybeRemap(this.colors, this.bits);
|
||||
|
||||
if (index == -1) {
|
||||
// No duplicate found, increase bit count
|
||||
// No duplicate found, increase bitcount
|
||||
bits++;
|
||||
transparent = this.colors.length - 1;
|
||||
}
|
||||
@@ -111,8 +117,10 @@ final class BitmapIndexed extends BitmapDescriptor {
|
||||
}
|
||||
|
||||
// NOTE: Setting hasAlpha to true, makes things work on 1.2
|
||||
return new IndexColorModel(bits, colors, this.colors, 0, true, transparent,
|
||||
bits <= 8 ? DataBuffer.TYPE_BYTE : DataBuffer.TYPE_USHORT);
|
||||
return new IndexColorModel(
|
||||
bits, colors, this.colors, 0, true, transparent,
|
||||
bits <= 8 ? DataBuffer.TYPE_BYTE : DataBuffer.TYPE_USHORT
|
||||
);
|
||||
}
|
||||
|
||||
private static int findTransparentIndexMaybeRemap(final int[] colors, final int[] bits) {
|
||||
|
||||
+8
-8
@@ -30,7 +30,7 @@
|
||||
|
||||
package com.twelvemonkeys.imageio.plugins.bmp;
|
||||
|
||||
import java.awt.image.*;
|
||||
import java.awt.image.BufferedImage;
|
||||
|
||||
|
||||
/**
|
||||
@@ -39,17 +39,17 @@ import java.awt.image.*;
|
||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||
* @version $Id: BitmapMask.java,v 1.0 25.feb.2006 00:29:44 haku Exp$
|
||||
*/
|
||||
final class BitmapMask extends BitmapDescriptor {
|
||||
final BitmapIndexed bitMask;
|
||||
class BitmapMask extends BitmapDescriptor {
|
||||
protected final BitmapIndexed bitMask;
|
||||
|
||||
public BitmapMask(final DirectoryEntry parent, final DIBHeader header) {
|
||||
super(parent, header);
|
||||
bitMask = new BitmapIndexed(parent, header);
|
||||
public BitmapMask(final DirectoryEntry pParent, final DIBHeader pHeader) {
|
||||
super(pParent, pHeader);
|
||||
bitMask = new BitmapIndexed(pParent, pHeader);
|
||||
}
|
||||
|
||||
boolean isTransparent(final int x, final int y) {
|
||||
boolean isTransparent(final int pX, final int pY) {
|
||||
// NOTE: 1: Fully transparent, 0: Opaque...
|
||||
return bitMask.bits[x + y * getWidth()] != 0;
|
||||
return bitMask.bits[pX + pY * getWidth()] != 0;
|
||||
}
|
||||
|
||||
public BufferedImage getImage() {
|
||||
|
||||
+6
-5
@@ -31,7 +31,8 @@
|
||||
package com.twelvemonkeys.imageio.plugins.bmp;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.image.*;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.awt.image.WritableRaster;
|
||||
|
||||
/**
|
||||
* Describes an RGB/true color bitmap structure (16, 24 and 32 bits per pixel).
|
||||
@@ -39,10 +40,10 @@ import java.awt.image.*;
|
||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||
* @version $Id: BitmapRGB.java,v 1.0 25.feb.2006 00:29:44 haku Exp$
|
||||
*/
|
||||
final class BitmapRGB extends BitmapDescriptor {
|
||||
class BitmapRGB extends BitmapDescriptor {
|
||||
|
||||
public BitmapRGB(final DirectoryEntry entry, final DIBHeader header) {
|
||||
super(entry, header);
|
||||
public BitmapRGB(final DirectoryEntry pEntry, final DIBHeader pHeader) {
|
||||
super(pEntry, pHeader);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -70,7 +71,7 @@ final class BitmapRGB extends BitmapDescriptor {
|
||||
|
||||
WritableRaster alphaRaster = masked.getAlphaRaster();
|
||||
|
||||
byte[] trans = {0x00};
|
||||
byte[] trans = {0x0};
|
||||
for (int y = 0; y < getHeight(); y++) {
|
||||
for (int x = 0; x < getWidth(); x++) {
|
||||
if (mask.isTransparent(x, y)) {
|
||||
|
||||
+8
-7
@@ -30,10 +30,11 @@
|
||||
|
||||
package com.twelvemonkeys.imageio.plugins.bmp;
|
||||
|
||||
import javax.imageio.IIOException;
|
||||
import java.awt.image.*;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.imageio.IIOException;
|
||||
|
||||
/**
|
||||
* Represents bitmap structures we can't read.
|
||||
* Allows for deferred exception handling, and allowing clients to read all images that can be read.
|
||||
@@ -41,13 +42,13 @@ import java.io.IOException;
|
||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||
* @version $Id: BitmapUnsupported.java,v 1.0 25.feb.2006 00:29:44 haku Exp$
|
||||
*/
|
||||
final class BitmapUnsupported extends BitmapDescriptor {
|
||||
private final String message;
|
||||
class BitmapUnsupported extends BitmapDescriptor {
|
||||
private String message;
|
||||
|
||||
public BitmapUnsupported(final DirectoryEntry entry, DIBHeader header, final String message) {
|
||||
super(entry, header);
|
||||
public BitmapUnsupported(final DirectoryEntry pEntry, DIBHeader header, final String pMessage) {
|
||||
super(pEntry, header);
|
||||
|
||||
this.message = message;
|
||||
message = pMessage;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+5
-5
@@ -48,22 +48,22 @@ public final class CURImageReader extends DIBImageReader {
|
||||
super(new CURImageReaderSpi());
|
||||
}
|
||||
|
||||
CURImageReader(final ImageReaderSpi provider) {
|
||||
super(provider);
|
||||
protected CURImageReader(final ImageReaderSpi pProvider) {
|
||||
super(pProvider);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the hot spot location for the cursor.
|
||||
*
|
||||
* @param imageIndex the index of the cursor in the current input.
|
||||
* @param pImageIndex the index of the cursor in the current input.
|
||||
* @return the hot spot location for the cursor
|
||||
*
|
||||
* @throws java.io.IOException if an I/O exception occurs during reading of image meta data
|
||||
* @throws IndexOutOfBoundsException if {@code pImageIndex} is less than {@code 0} or greater than/equal to
|
||||
* the number of cursors in the file
|
||||
*/
|
||||
public Point getHotSpot(final int imageIndex) throws IOException {
|
||||
DirectoryEntry.CUREntry entry = (DirectoryEntry.CUREntry) getEntry(imageIndex);
|
||||
public final Point getHotSpot(final int pImageIndex) throws IOException {
|
||||
DirectoryEntry.CUREntry entry = (DirectoryEntry.CUREntry) getEntry(pImageIndex);
|
||||
return entry.getHotspot();
|
||||
}
|
||||
}
|
||||
|
||||
+5
-4
@@ -32,6 +32,7 @@ package com.twelvemonkeys.imageio.plugins.bmp;
|
||||
|
||||
import com.twelvemonkeys.imageio.spi.ImageReaderSpiBase;
|
||||
|
||||
import javax.imageio.ImageReader;
|
||||
import javax.imageio.stream.ImageInputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.Locale;
|
||||
@@ -48,15 +49,15 @@ public final class CURImageReaderSpi extends ImageReaderSpiBase {
|
||||
super(new CURProviderInfo());
|
||||
}
|
||||
|
||||
public boolean canDecodeInput(final Object source) throws IOException {
|
||||
return source instanceof ImageInputStream && ICOImageReaderSpi.canDecode((ImageInputStream) source, DIB.TYPE_CUR);
|
||||
public boolean canDecodeInput(final Object pSource) throws IOException {
|
||||
return pSource instanceof ImageInputStream && ICOImageReaderSpi.canDecode((ImageInputStream) pSource, DIB.TYPE_CUR);
|
||||
}
|
||||
|
||||
public CURImageReader createReaderInstance(final Object extension) {
|
||||
public ImageReader createReaderInstance(final Object pExtension) throws IOException {
|
||||
return new CURImageReader(this);
|
||||
}
|
||||
|
||||
public String getDescription(final Locale locale) {
|
||||
public String getDescription(final Locale pLocale) {
|
||||
return "Windows Cursor Format (CUR) Reader";
|
||||
}
|
||||
}
|
||||
|
||||
+103
-171
@@ -30,11 +30,12 @@
|
||||
|
||||
package com.twelvemonkeys.imageio.plugins.bmp;
|
||||
|
||||
import javax.imageio.IIOException;
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.imageio.IIOException;
|
||||
|
||||
/**
|
||||
* Represents the DIB (Device Independent Bitmap) Information header structure.
|
||||
*
|
||||
@@ -90,17 +91,17 @@ abstract class DIBHeader {
|
||||
protected DIBHeader() {
|
||||
}
|
||||
|
||||
public static DIBHeader read(final DataInput stream) throws IOException {
|
||||
int size = stream.readInt();
|
||||
public static DIBHeader read(final DataInput pStream) throws IOException {
|
||||
int size = pStream.readInt();
|
||||
|
||||
DIBHeader header = createHeader(size);
|
||||
header.read(size, stream);
|
||||
header.read(size, pStream);
|
||||
|
||||
return header;
|
||||
}
|
||||
|
||||
private static DIBHeader createHeader(final int size) throws IOException {
|
||||
switch (size) {
|
||||
private static DIBHeader createHeader(final int pSize) throws IOException {
|
||||
switch (pSize) {
|
||||
case DIB.BITMAP_CORE_HEADER_SIZE:
|
||||
return new BitmapCoreHeader();
|
||||
case DIB.OS2_V2_HEADER_16_SIZE:
|
||||
@@ -117,12 +118,11 @@ abstract class DIBHeader {
|
||||
case DIB.BITMAP_V5_INFO_HEADER_SIZE:
|
||||
return new BitmapV5InfoHeader();
|
||||
default:
|
||||
throw new IIOException(String.format("Unknown Bitmap Information Header (size: %s)", size));
|
||||
throw new IIOException(String.format("Unknown Bitmap Information Header (size: %s)", pSize));
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract void read(int size, DataInput stream) throws IOException;
|
||||
protected abstract void write(final DataOutput stream) throws IOException;
|
||||
protected abstract void read(int pSize, DataInput pStream) throws IOException;
|
||||
|
||||
public final int getSize() {
|
||||
return size;
|
||||
@@ -189,12 +189,12 @@ abstract class DIBHeader {
|
||||
);
|
||||
}
|
||||
|
||||
private static int[] readMasks(final DataInput stream, final boolean hasAlphaMask) throws IOException {
|
||||
private static int[] readMasks(final DataInput pStream, final boolean hasAlphaMask) throws IOException {
|
||||
int maskCount = hasAlphaMask ? 4 : 3;
|
||||
int[] masks = new int[4];
|
||||
|
||||
for (int i = 0; i < maskCount; i++) {
|
||||
masks[i] = stream.readInt();
|
||||
masks[i] = pStream.readInt();
|
||||
}
|
||||
|
||||
return masks;
|
||||
@@ -205,30 +205,24 @@ abstract class DIBHeader {
|
||||
// TODO: Get rid of code duplication below...
|
||||
|
||||
static final class BitmapCoreHeader extends DIBHeader {
|
||||
@Override
|
||||
protected void read(final int size, final DataInput stream) throws IOException {
|
||||
if (size != DIB.BITMAP_CORE_HEADER_SIZE) {
|
||||
throw new IIOException(String.format("Size: %s !=: %s", size, DIB.BITMAP_CORE_HEADER_SIZE));
|
||||
protected void read(final int pSize, final DataInput pStream) throws IOException {
|
||||
if (pSize != DIB.BITMAP_CORE_HEADER_SIZE) {
|
||||
throw new IIOException(String.format("Size: %s !=: %s", pSize, DIB.BITMAP_CORE_HEADER_SIZE));
|
||||
}
|
||||
|
||||
this.size = size;
|
||||
size = pSize;
|
||||
|
||||
// NOTE: Unlike all other headers, width and height are unsigned SHORT values (16 bit)!
|
||||
width = stream.readUnsignedShort();
|
||||
height = stream.readShort();
|
||||
width = pStream.readUnsignedShort();
|
||||
height = pStream.readShort();
|
||||
|
||||
if (height < 0) {
|
||||
height = -height;
|
||||
topDown = true;
|
||||
}
|
||||
|
||||
planes = stream.readUnsignedShort();
|
||||
bitCount = stream.readUnsignedShort();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void write(DataOutput stream) {
|
||||
throw new UnsupportedOperationException();
|
||||
planes = pStream.readUnsignedShort();
|
||||
bitCount = pStream.readUnsignedShort();
|
||||
}
|
||||
|
||||
public String getBMPVersion() {
|
||||
@@ -248,51 +242,45 @@ abstract class DIBHeader {
|
||||
*/
|
||||
static final class BitmapCoreHeaderV2 extends DIBHeader {
|
||||
@SuppressWarnings("unused")
|
||||
@Override
|
||||
protected void read(final int size, final DataInput stream) throws IOException {
|
||||
if (size != DIB.OS2_V2_HEADER_SIZE && size != DIB.OS2_V2_HEADER_16_SIZE) {
|
||||
throw new IIOException(String.format("Size: %s !=: %s", size, DIB.OS2_V2_HEADER_SIZE));
|
||||
protected void read(final int pSize, final DataInput pStream) throws IOException {
|
||||
if (pSize != DIB.OS2_V2_HEADER_SIZE && pSize != DIB.OS2_V2_HEADER_16_SIZE) {
|
||||
throw new IIOException(String.format("Size: %s !=: %s", pSize, DIB.OS2_V2_HEADER_SIZE));
|
||||
}
|
||||
|
||||
this.size = size;
|
||||
size = pSize;
|
||||
|
||||
width = stream.readInt();
|
||||
height = stream.readInt();
|
||||
width = pStream.readInt();
|
||||
height = pStream.readInt();
|
||||
|
||||
if (height < 0) {
|
||||
height = -height;
|
||||
topDown = true;
|
||||
}
|
||||
|
||||
planes = stream.readUnsignedShort();
|
||||
bitCount = stream.readUnsignedShort();
|
||||
planes = pStream.readUnsignedShort();
|
||||
bitCount = pStream.readUnsignedShort();
|
||||
|
||||
if (size != DIB.OS2_V2_HEADER_16_SIZE) {
|
||||
compression = stream.readInt();
|
||||
if (pSize != DIB.OS2_V2_HEADER_16_SIZE) {
|
||||
compression = pStream.readInt();
|
||||
|
||||
imageSize = stream.readInt();
|
||||
imageSize = pStream.readInt();
|
||||
|
||||
xPixelsPerMeter = stream.readInt();
|
||||
yPixelsPerMeter = stream.readInt();
|
||||
xPixelsPerMeter = pStream.readInt();
|
||||
yPixelsPerMeter = pStream.readInt();
|
||||
|
||||
colorsUsed = stream.readInt();
|
||||
colorsImportant = stream.readInt();
|
||||
colorsUsed = pStream.readInt();
|
||||
colorsImportant = pStream.readInt();
|
||||
}
|
||||
|
||||
// TODO: Use? These fields are not reflected in metadata as per now...
|
||||
int units = stream.readShort();
|
||||
int reserved = stream.readShort();
|
||||
int recording = stream.readShort(); // Recording algorithm
|
||||
int rendering = stream.readShort(); // Halftoning algorithm
|
||||
int size1 = stream.readInt(); // Reserved for halftoning use
|
||||
int size2 = stream.readInt(); // Reserved for halftoning use
|
||||
int colorEncoding = stream.readInt(); // Color model used in bitmap
|
||||
int identifier = stream.readInt(); // Reserved for application use
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void write(DataOutput stream) {
|
||||
throw new UnsupportedOperationException();
|
||||
int units = pStream.readShort();
|
||||
int reserved = pStream.readShort();
|
||||
int recording = pStream.readShort(); // Recording algorithm
|
||||
int rendering = pStream.readShort(); // Halftoning algorithm
|
||||
int size1 = pStream.readInt(); // Reserved for halftoning use
|
||||
int size2 = pStream.readInt(); // Reserved for halftoning use
|
||||
int colorEncoding = pStream.readInt(); // Color model used in bitmap
|
||||
int identifier = pStream.readInt(); // Reserved for application use
|
||||
}
|
||||
|
||||
public String getBMPVersion() {
|
||||
@@ -300,6 +288,7 @@ abstract class DIBHeader {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Represents the DIB (Device Independent Bitmap) Windows 3.0 Bitmap Information header structure.
|
||||
* This is the common format for persistent DIB structures, even if Windows
|
||||
@@ -315,46 +304,44 @@ abstract class DIBHeader {
|
||||
* @see <a href="https://forums.adobe.com/message/3272950#3272950">BITMAPV3INFOHEADER</a>.
|
||||
*/
|
||||
static final class BitmapInfoHeader extends DIBHeader {
|
||||
@Override
|
||||
protected void read(final int size, final DataInput stream) throws IOException {
|
||||
if (!(size == DIB.BITMAP_INFO_HEADER_SIZE || size == DIB.BITMAP_V2_INFO_HEADER_SIZE || size == DIB.BITMAP_V3_INFO_HEADER_SIZE)) {
|
||||
throw new IIOException(String.format("Size: %s !=: %s", size, DIB.BITMAP_INFO_HEADER_SIZE));
|
||||
protected void read(final int pSize, final DataInput pStream) throws IOException {
|
||||
if (!(pSize == DIB.BITMAP_INFO_HEADER_SIZE || pSize == DIB.BITMAP_V2_INFO_HEADER_SIZE || pSize == DIB.BITMAP_V3_INFO_HEADER_SIZE)) {
|
||||
throw new IIOException(String.format("Size: %s !=: %s", pSize, DIB.BITMAP_INFO_HEADER_SIZE));
|
||||
}
|
||||
|
||||
this.size = size;
|
||||
size = pSize;
|
||||
|
||||
width = stream.readInt();
|
||||
height = stream.readInt();
|
||||
width = pStream.readInt();
|
||||
height = pStream.readInt();
|
||||
|
||||
if (height < 0) {
|
||||
height = -height;
|
||||
topDown = true;
|
||||
}
|
||||
|
||||
planes = stream.readUnsignedShort();
|
||||
bitCount = stream.readUnsignedShort();
|
||||
compression = stream.readInt();
|
||||
planes = pStream.readUnsignedShort();
|
||||
bitCount = pStream.readUnsignedShort();
|
||||
compression = pStream.readInt();
|
||||
|
||||
imageSize = stream.readInt();
|
||||
imageSize = pStream.readInt();
|
||||
|
||||
xPixelsPerMeter = stream.readInt();
|
||||
yPixelsPerMeter = stream.readInt();
|
||||
xPixelsPerMeter = pStream.readInt();
|
||||
yPixelsPerMeter = pStream.readInt();
|
||||
|
||||
colorsUsed = stream.readInt();
|
||||
colorsImportant = stream.readInt();
|
||||
colorsUsed = pStream.readInt();
|
||||
colorsImportant = pStream.readInt();
|
||||
|
||||
// Read masks if we have V2 or V3
|
||||
// or if we have compression BITFIELDS or ALPHA_BITFIELDS
|
||||
if (this.size == DIB.BITMAP_V2_INFO_HEADER_SIZE || compression == DIB.COMPRESSION_BITFIELDS) {
|
||||
masks = readMasks(stream, false);
|
||||
if (size == DIB.BITMAP_V2_INFO_HEADER_SIZE || compression == DIB.COMPRESSION_BITFIELDS) {
|
||||
masks = readMasks(pStream, false);
|
||||
}
|
||||
else if (this.size == DIB.BITMAP_V3_INFO_HEADER_SIZE || compression == DIB.COMPRESSION_ALPHA_BITFIELDS) {
|
||||
masks = readMasks(stream, true);
|
||||
else if (size == DIB.BITMAP_V3_INFO_HEADER_SIZE || compression == DIB.COMPRESSION_ALPHA_BITFIELDS) {
|
||||
masks = readMasks(pStream, true);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void write(final DataOutput stream) throws IOException {
|
||||
void write(final DataOutput stream) throws IOException {
|
||||
stream.writeInt(DIB.BITMAP_INFO_HEADER_SIZE);
|
||||
|
||||
stream.writeInt(width);
|
||||
@@ -372,7 +359,7 @@ abstract class DIBHeader {
|
||||
stream.writeInt(colorsUsed);
|
||||
stream.writeInt(colorsImportant);
|
||||
|
||||
// TODO: Write masks, if COMPRESSION_BITFIELDS/COMPRESSION_ALPHA_BITFIELDS
|
||||
// TODO: Write masks, if bitfields
|
||||
}
|
||||
|
||||
public String getBMPVersion() {
|
||||
@@ -389,160 +376,105 @@ abstract class DIBHeader {
|
||||
* Represents the BITMAPV4INFOHEADER structure.
|
||||
*/
|
||||
static final class BitmapV4InfoHeader extends DIBHeader {
|
||||
@Override
|
||||
protected void read(final int size, final DataInput stream) throws IOException {
|
||||
if (size != DIB.BITMAP_V4_INFO_HEADER_SIZE) {
|
||||
throw new IIOException(String.format("Size: %s !=: %s", size, DIB.BITMAP_V4_INFO_HEADER_SIZE));
|
||||
protected void read(final int pSize, final DataInput pStream) throws IOException {
|
||||
if (pSize != DIB.BITMAP_V4_INFO_HEADER_SIZE) {
|
||||
throw new IIOException(String.format("Size: %s !=: %s", pSize, DIB.BITMAP_V4_INFO_HEADER_SIZE));
|
||||
}
|
||||
|
||||
this.size = size;
|
||||
size = pSize;
|
||||
|
||||
width = stream.readInt();
|
||||
height = stream.readInt();
|
||||
width = pStream.readInt();
|
||||
height = pStream.readInt();
|
||||
|
||||
if (height < 0) {
|
||||
height = -height;
|
||||
topDown = true;
|
||||
}
|
||||
|
||||
planes = stream.readUnsignedShort();
|
||||
bitCount = stream.readUnsignedShort();
|
||||
compression = stream.readInt();
|
||||
planes = pStream.readUnsignedShort();
|
||||
bitCount = pStream.readUnsignedShort();
|
||||
compression = pStream.readInt();
|
||||
|
||||
imageSize = stream.readInt();
|
||||
imageSize = pStream.readInt();
|
||||
|
||||
xPixelsPerMeter = stream.readInt();
|
||||
yPixelsPerMeter = stream.readInt();
|
||||
xPixelsPerMeter = pStream.readInt();
|
||||
yPixelsPerMeter = pStream.readInt();
|
||||
|
||||
colorsUsed = stream.readInt();
|
||||
colorsImportant = stream.readInt();
|
||||
colorsUsed = pStream.readInt();
|
||||
colorsImportant = pStream.readInt();
|
||||
|
||||
masks = readMasks(stream, true);
|
||||
masks = readMasks(pStream, true);
|
||||
|
||||
colorSpaceType = stream.readInt(); // Should be 0 for V4
|
||||
colorSpaceType = pStream.readInt(); // Should be 0 for V4
|
||||
cieXYZEndpoints = new double[9];
|
||||
|
||||
for (int i = 0; i < cieXYZEndpoints.length; i++) {
|
||||
cieXYZEndpoints[i] = stream.readInt(); // TODO: Hmmm...?
|
||||
cieXYZEndpoints[i] = pStream.readInt(); // TODO: Hmmm...?
|
||||
}
|
||||
|
||||
gamma = new int[3];
|
||||
|
||||
for (int i = 0; i < gamma.length; i++) {
|
||||
gamma[i] = stream.readInt();
|
||||
gamma[i] = pStream.readInt();
|
||||
}
|
||||
}
|
||||
|
||||
public String getBMPVersion() {
|
||||
return "BMP v. 4.x";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void write(DataOutput stream) throws IOException {
|
||||
stream.writeInt(DIB.BITMAP_V4_INFO_HEADER_SIZE);
|
||||
|
||||
stream.writeInt(width);
|
||||
stream.writeInt(topDown ? -height : height);
|
||||
|
||||
stream.writeShort(planes);
|
||||
stream.writeShort(bitCount);
|
||||
stream.writeInt(compression);
|
||||
|
||||
stream.writeInt(imageSize);
|
||||
|
||||
stream.writeInt(xPixelsPerMeter);
|
||||
stream.writeInt(yPixelsPerMeter);
|
||||
|
||||
stream.writeInt(colorsUsed);
|
||||
stream.writeInt(colorsImportant);
|
||||
|
||||
// Red, Green, Blue, Alpha masks
|
||||
stream.writeInt(masks[0]);
|
||||
stream.writeInt(masks[1]);
|
||||
stream.writeInt(masks[2]);
|
||||
stream.writeInt(masks[3]);
|
||||
|
||||
// color space ("sRGB" LITTLE endian)
|
||||
stream.writeInt(DIB.LCS_sRGB);
|
||||
|
||||
// 36 bytes CIE XYZ triples, unused for sRGB
|
||||
stream.writeInt(0);
|
||||
stream.writeInt(0);
|
||||
stream.writeInt(0);
|
||||
|
||||
stream.writeInt(0);
|
||||
stream.writeInt(0);
|
||||
stream.writeInt(0);
|
||||
|
||||
stream.writeInt(0);
|
||||
stream.writeInt(0);
|
||||
stream.writeInt(0);
|
||||
|
||||
// Red gamma, unused for sRGB
|
||||
// Green gamma, unused for sRGB
|
||||
// Blue gamma, unused for sRGB
|
||||
stream.writeInt(0);
|
||||
stream.writeInt(0);
|
||||
stream.writeInt(0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents the BITMAPV5INFOHEADER structure.
|
||||
*/
|
||||
static final class BitmapV5InfoHeader extends DIBHeader {
|
||||
protected void read(final int size, final DataInput stream) throws IOException {
|
||||
if (size != DIB.BITMAP_V5_INFO_HEADER_SIZE) {
|
||||
throw new IIOException(String.format("Size: %s !=: %s", size, DIB.BITMAP_V5_INFO_HEADER_SIZE));
|
||||
protected void read(final int pSize, final DataInput pStream) throws IOException {
|
||||
if (pSize != DIB.BITMAP_V5_INFO_HEADER_SIZE) {
|
||||
throw new IIOException(String.format("Size: %s !=: %s", pSize, DIB.BITMAP_V5_INFO_HEADER_SIZE));
|
||||
}
|
||||
|
||||
this.size = size;
|
||||
size = pSize;
|
||||
|
||||
width = stream.readInt();
|
||||
height = stream.readInt();
|
||||
width = pStream.readInt();
|
||||
height = pStream.readInt();
|
||||
|
||||
if (height < 0) {
|
||||
height = -height;
|
||||
topDown = true;
|
||||
}
|
||||
|
||||
planes = stream.readUnsignedShort();
|
||||
bitCount = stream.readUnsignedShort();
|
||||
compression = stream.readInt();
|
||||
planes = pStream.readUnsignedShort();
|
||||
bitCount = pStream.readUnsignedShort();
|
||||
compression = pStream.readInt();
|
||||
|
||||
imageSize = stream.readInt();
|
||||
imageSize = pStream.readInt();
|
||||
|
||||
xPixelsPerMeter = stream.readInt();
|
||||
yPixelsPerMeter = stream.readInt();
|
||||
xPixelsPerMeter = pStream.readInt();
|
||||
yPixelsPerMeter = pStream.readInt();
|
||||
|
||||
colorsUsed = stream.readInt();
|
||||
colorsImportant = stream.readInt();
|
||||
colorsUsed = pStream.readInt();
|
||||
colorsImportant = pStream.readInt();
|
||||
|
||||
masks = readMasks(stream, true);
|
||||
masks = readMasks(pStream, true);
|
||||
|
||||
colorSpaceType = stream.readInt();
|
||||
colorSpaceType = pStream.readInt();
|
||||
|
||||
cieXYZEndpoints = new double[9];
|
||||
|
||||
for (int i = 0; i < cieXYZEndpoints.length; i++) {
|
||||
cieXYZEndpoints[i] = stream.readInt(); // TODO: Hmmm...?
|
||||
cieXYZEndpoints[i] = pStream.readInt(); // TODO: Hmmm...?
|
||||
}
|
||||
|
||||
gamma = new int[3];
|
||||
|
||||
for (int i = 0; i < gamma.length; i++) {
|
||||
gamma[i] = stream.readInt();
|
||||
gamma[i] = pStream.readInt();
|
||||
}
|
||||
|
||||
intent = stream.readInt(); // TODO: Verify if this is same as ICC intent
|
||||
profileData = stream.readInt() & 0xffffffffL;
|
||||
profileSize = stream.readInt() & 0xffffffffL;
|
||||
stream.readInt(); // Reserved
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void write(DataOutput stream) {
|
||||
throw new UnsupportedOperationException();
|
||||
intent = pStream.readInt(); // TODO: Verify if this is same as ICC intent
|
||||
profileData = pStream.readInt() & 0xffffffffL;
|
||||
profileSize = pStream.readInt() & 0xffffffffL;
|
||||
pStream.readInt(); // Reserved
|
||||
}
|
||||
|
||||
public String getBMPVersion() {
|
||||
|
||||
+155
-152
@@ -30,23 +30,10 @@
|
||||
|
||||
package com.twelvemonkeys.imageio.plugins.bmp;
|
||||
|
||||
import com.twelvemonkeys.image.ImageUtil;
|
||||
import com.twelvemonkeys.imageio.ImageReaderBase;
|
||||
import com.twelvemonkeys.imageio.stream.SubImageInputStream;
|
||||
import com.twelvemonkeys.imageio.util.ImageTypeSpecifiers;
|
||||
import com.twelvemonkeys.util.WeakWeakMap;
|
||||
|
||||
import javax.imageio.IIOException;
|
||||
import javax.imageio.ImageIO;
|
||||
import javax.imageio.ImageReadParam;
|
||||
import javax.imageio.ImageReader;
|
||||
import javax.imageio.ImageTypeSpecifier;
|
||||
import javax.imageio.spi.ImageReaderSpi;
|
||||
import javax.imageio.stream.ImageInputStream;
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.awt.color.*;
|
||||
import java.awt.event.*;
|
||||
import java.awt.color.ColorSpace;
|
||||
import java.awt.event.WindowAdapter;
|
||||
import java.awt.event.WindowEvent;
|
||||
import java.awt.image.*;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
@@ -57,6 +44,21 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.WeakHashMap;
|
||||
|
||||
import javax.imageio.IIOException;
|
||||
import javax.imageio.ImageIO;
|
||||
import javax.imageio.ImageReadParam;
|
||||
import javax.imageio.ImageReader;
|
||||
import javax.imageio.ImageTypeSpecifier;
|
||||
import javax.imageio.spi.ImageReaderSpi;
|
||||
import javax.imageio.stream.ImageInputStream;
|
||||
import javax.swing.*;
|
||||
|
||||
import com.twelvemonkeys.image.ImageUtil;
|
||||
import com.twelvemonkeys.imageio.ImageReaderBase;
|
||||
import com.twelvemonkeys.imageio.stream.SubImageInputStream;
|
||||
import com.twelvemonkeys.imageio.util.ImageTypeSpecifiers;
|
||||
import com.twelvemonkeys.util.WeakWeakMap;
|
||||
|
||||
/**
|
||||
* ImageReader for Microsoft Windows ICO (icon) format.
|
||||
* 1, 4, 8 bit palette support with bitmask transparency, and 16, 24 and 32 bit
|
||||
@@ -79,13 +81,13 @@ abstract class DIBImageReader extends ImageReaderBase {
|
||||
private Directory directory;
|
||||
|
||||
// TODO: Review these, make sure we don't have a memory leak
|
||||
private final Map<DirectoryEntry, DIBHeader> headers = new WeakHashMap<>();
|
||||
private final Map<DirectoryEntry, BitmapDescriptor> descriptors = new WeakWeakMap<>();
|
||||
private Map<DirectoryEntry, DIBHeader> headers = new WeakHashMap<>();
|
||||
private Map<DirectoryEntry, BitmapDescriptor> descriptors = new WeakWeakMap<>();
|
||||
|
||||
private ImageReader pngImageReader;
|
||||
|
||||
protected DIBImageReader(final ImageReaderSpi provider) {
|
||||
super(provider);
|
||||
protected DIBImageReader(final ImageReaderSpi pProvider) {
|
||||
super(pProvider);
|
||||
}
|
||||
|
||||
protected void resetMembers() {
|
||||
@@ -100,8 +102,8 @@ abstract class DIBImageReader extends ImageReaderBase {
|
||||
}
|
||||
}
|
||||
|
||||
public Iterator<ImageTypeSpecifier> getImageTypes(final int imageIndex) throws IOException {
|
||||
DirectoryEntry entry = getEntry(imageIndex);
|
||||
public Iterator<ImageTypeSpecifier> getImageTypes(final int pImageIndex) throws IOException {
|
||||
DirectoryEntry entry = getEntry(pImageIndex);
|
||||
|
||||
// NOTE: Delegate to PNG reader
|
||||
if (isPNG(entry)) {
|
||||
@@ -153,39 +155,39 @@ abstract class DIBImageReader extends ImageReaderBase {
|
||||
return getDirectory().count();
|
||||
}
|
||||
|
||||
public int getWidth(final int imageIndex) throws IOException {
|
||||
return getEntry(imageIndex).getWidth();
|
||||
public int getWidth(final int pImageIndex) throws IOException {
|
||||
return getEntry(pImageIndex).getWidth();
|
||||
}
|
||||
|
||||
public int getHeight(final int imageIndex) throws IOException {
|
||||
return getEntry(imageIndex).getHeight();
|
||||
public int getHeight(final int pImageIndex) throws IOException {
|
||||
return getEntry(pImageIndex).getHeight();
|
||||
}
|
||||
|
||||
public BufferedImage read(final int imageIndex, final ImageReadParam param) throws IOException {
|
||||
checkBounds(imageIndex);
|
||||
public BufferedImage read(final int pImageIndex, final ImageReadParam pParam) throws IOException {
|
||||
checkBounds(pImageIndex);
|
||||
|
||||
processImageStarted(imageIndex);
|
||||
processImageStarted(pImageIndex);
|
||||
|
||||
DirectoryEntry entry = getEntry(imageIndex);
|
||||
DirectoryEntry entry = getEntry(pImageIndex);
|
||||
|
||||
BufferedImage destination;
|
||||
|
||||
if (isPNG(entry)) {
|
||||
// NOTE: Special case for Windows Vista, 256x256 PNG encoded images, with no DIB header...
|
||||
destination = readPNG(entry, param);
|
||||
destination = readPNG(entry, pParam);
|
||||
}
|
||||
else {
|
||||
// NOTE: If param does not have explicit destination, we'll try to create a BufferedImage later,
|
||||
// to allow for storing the cursor hotspot for CUR images
|
||||
destination = hasExplicitDestination(param) ?
|
||||
getDestination(param, getImageTypes(imageIndex), getWidth(imageIndex), getHeight(imageIndex)) : null;
|
||||
destination = hasExplicitDestination(pParam) ?
|
||||
getDestination(pParam, getImageTypes(pImageIndex), getWidth(pImageIndex), getHeight(pImageIndex)) : null;
|
||||
|
||||
BufferedImage image = readBitmap(entry);
|
||||
|
||||
// TODO: Handle AOI and subsampling inline, probably not of big importance...
|
||||
if (param != null) {
|
||||
image = fakeAOI(image, param);
|
||||
image = ImageUtil.toBuffered(fakeSubsampling(image, param));
|
||||
if (pParam != null) {
|
||||
image = fakeAOI(image, pParam);
|
||||
image = ImageUtil.toBuffered(fakeSubsampling(image, pParam));
|
||||
}
|
||||
|
||||
if (destination == null) {
|
||||
@@ -211,10 +213,10 @@ abstract class DIBImageReader extends ImageReaderBase {
|
||||
return destination;
|
||||
}
|
||||
|
||||
private boolean isPNG(final DirectoryEntry entry) throws IOException {
|
||||
private boolean isPNG(final DirectoryEntry pEntry) throws IOException {
|
||||
long magic;
|
||||
|
||||
imageInput.seek(entry.getOffset());
|
||||
imageInput.seek(pEntry.getOffset());
|
||||
imageInput.setByteOrder(ByteOrder.BIG_ENDIAN);
|
||||
|
||||
try {
|
||||
@@ -227,20 +229,22 @@ abstract class DIBImageReader extends ImageReaderBase {
|
||||
return magic == DIB.PNG_MAGIC;
|
||||
}
|
||||
|
||||
private BufferedImage readPNG(final DirectoryEntry entry, final ImageReadParam param) throws IOException {
|
||||
private BufferedImage readPNG(final DirectoryEntry pEntry, final ImageReadParam pParam) throws IOException {
|
||||
// TODO: Consider delegating listener calls
|
||||
return initPNGReader(entry).read(0, param);
|
||||
return initPNGReader(pEntry).read(0, pParam);
|
||||
}
|
||||
|
||||
private Iterator<ImageTypeSpecifier> getImageTypesPNG(final DirectoryEntry entry) throws IOException {
|
||||
return initPNGReader(entry).getImageTypes(0);
|
||||
private Iterator<ImageTypeSpecifier> getImageTypesPNG(final DirectoryEntry pEntry) throws IOException {
|
||||
return initPNGReader(pEntry).getImageTypes(0);
|
||||
}
|
||||
|
||||
private ImageReader initPNGReader(final DirectoryEntry entry) throws IOException {
|
||||
private ImageReader initPNGReader(final DirectoryEntry pEntry) throws IOException {
|
||||
ImageReader pngReader = getPNGReader();
|
||||
|
||||
imageInput.seek(entry.getOffset());
|
||||
ImageInputStream stream = new SubImageInputStream(imageInput, entry.getSize());
|
||||
imageInput.seek(pEntry.getOffset());
|
||||
// InputStream inputStream = IIOUtil.createStreamAdapter(imageInput, pEntry.getSize());
|
||||
// ImageInputStream stream = ImageIO.createImageInputStream(inputStream);
|
||||
ImageInputStream stream = new SubImageInputStream(imageInput, pEntry.getSize());
|
||||
|
||||
// NOTE: Will throw IOException on later reads if input is not PNG
|
||||
pngReader.setInput(stream);
|
||||
@@ -267,31 +271,31 @@ abstract class DIBImageReader extends ImageReaderBase {
|
||||
return pngImageReader;
|
||||
}
|
||||
|
||||
private DIBHeader getHeader(final DirectoryEntry entry) throws IOException {
|
||||
if (!headers.containsKey(entry)) {
|
||||
imageInput.seek(entry.getOffset());
|
||||
private DIBHeader getHeader(final DirectoryEntry pEntry) throws IOException {
|
||||
if (!headers.containsKey(pEntry)) {
|
||||
imageInput.seek(pEntry.getOffset());
|
||||
DIBHeader header = DIBHeader.read(imageInput);
|
||||
headers.put(entry, header);
|
||||
headers.put(pEntry, header);
|
||||
}
|
||||
|
||||
return headers.get(entry);
|
||||
return headers.get(pEntry);
|
||||
}
|
||||
|
||||
private BufferedImage readBitmap(final DirectoryEntry entry) throws IOException {
|
||||
private BufferedImage readBitmap(final DirectoryEntry pEntry) throws IOException {
|
||||
// TODO: Get rid of the caching, as the images are mutable
|
||||
BitmapDescriptor descriptor = descriptors.get(entry);
|
||||
BitmapDescriptor descriptor = descriptors.get(pEntry);
|
||||
|
||||
if (descriptor == null || !descriptors.containsKey(entry)) {
|
||||
DIBHeader header = getHeader(entry);
|
||||
if (descriptor == null || !descriptors.containsKey(pEntry)) {
|
||||
DIBHeader header = getHeader(pEntry);
|
||||
|
||||
int offset = entry.getOffset() + header.getSize();
|
||||
int offset = pEntry.getOffset() + header.getSize();
|
||||
if (offset != imageInput.getStreamPosition()) {
|
||||
imageInput.seek(offset);
|
||||
}
|
||||
|
||||
// TODO: Support this, it's already in the BMP reader, spec allows RLE4 and RLE8
|
||||
if (header.getCompression() != DIB.COMPRESSION_RGB) {
|
||||
descriptor = new BitmapUnsupported(entry, header, String.format("Unsupported compression: %d", header.getCompression()));
|
||||
descriptor = new BitmapUnsupported(pEntry, header, String.format("Unsupported compression: %d", header.getCompression()));
|
||||
}
|
||||
else {
|
||||
int bitCount = header.getBitCount();
|
||||
@@ -301,75 +305,75 @@ abstract class DIBImageReader extends ImageReaderBase {
|
||||
case 1:
|
||||
case 4:
|
||||
case 8: // TODO: Gray!
|
||||
descriptor = new BitmapIndexed(entry, header);
|
||||
descriptor = new BitmapIndexed(pEntry, header);
|
||||
readBitmapIndexed((BitmapIndexed) descriptor);
|
||||
break;
|
||||
// RGB style
|
||||
case 16:
|
||||
descriptor = new BitmapRGB(entry, header);
|
||||
descriptor = new BitmapRGB(pEntry, header);
|
||||
readBitmap16(descriptor);
|
||||
break;
|
||||
case 24:
|
||||
descriptor = new BitmapRGB(entry, header);
|
||||
descriptor = new BitmapRGB(pEntry, header);
|
||||
readBitmap24(descriptor);
|
||||
break;
|
||||
case 32:
|
||||
descriptor = new BitmapRGB(entry, header);
|
||||
descriptor = new BitmapRGB(pEntry, header);
|
||||
readBitmap32(descriptor);
|
||||
break;
|
||||
|
||||
default:
|
||||
descriptor = new BitmapUnsupported(entry, header, String.format("Unsupported bit count %d", bitCount));
|
||||
descriptor = new BitmapUnsupported(pEntry, header, String.format("Unsupported bit count %d", bitCount));
|
||||
}
|
||||
}
|
||||
|
||||
descriptors.put(entry, descriptor);
|
||||
descriptors.put(pEntry, descriptor);
|
||||
}
|
||||
|
||||
return descriptor.getImage();
|
||||
}
|
||||
|
||||
private void readBitmapIndexed(final BitmapIndexed bitmap) throws IOException {
|
||||
readColorMap(bitmap);
|
||||
private void readBitmapIndexed(final BitmapIndexed pBitmap) throws IOException {
|
||||
readColorMap(pBitmap);
|
||||
|
||||
switch (bitmap.getBitCount()) {
|
||||
switch (pBitmap.getBitCount()) {
|
||||
case 1:
|
||||
readBitmapIndexed1(bitmap, false);
|
||||
readBitmapIndexed1(pBitmap, false);
|
||||
break;
|
||||
case 4:
|
||||
readBitmapIndexed4(bitmap);
|
||||
readBitmapIndexed4(pBitmap);
|
||||
break;
|
||||
case 8:
|
||||
readBitmapIndexed8(bitmap);
|
||||
readBitmapIndexed8(pBitmap);
|
||||
break;
|
||||
}
|
||||
|
||||
BitmapMask mask = new BitmapMask(bitmap.entry, bitmap.header);
|
||||
BitmapMask mask = new BitmapMask(pBitmap.entry, pBitmap.header);
|
||||
readBitmapIndexed1(mask.bitMask, true);
|
||||
bitmap.setMask(mask);
|
||||
pBitmap.setMask(mask);
|
||||
}
|
||||
|
||||
private void readColorMap(final BitmapIndexed bitmap) throws IOException {
|
||||
int colorCount = bitmap.getColorCount();
|
||||
private void readColorMap(final BitmapIndexed pBitmap) throws IOException {
|
||||
int colorCount = pBitmap.getColorCount();
|
||||
|
||||
for (int i = 0; i < colorCount; i++) {
|
||||
// aRGB (a is "Reserved")
|
||||
bitmap.colors[i] = (imageInput.readInt() & 0xffffff) | 0xff000000;
|
||||
pBitmap.colors[i] = (imageInput.readInt() & 0xffffff) | 0xff000000;
|
||||
}
|
||||
}
|
||||
|
||||
private void readBitmapIndexed1(final BitmapIndexed bitmap, final boolean asMask) throws IOException {
|
||||
int width = adjustToPadding((bitmap.getWidth() + 7) >> 3);
|
||||
private void readBitmapIndexed1(final BitmapIndexed pBitmap, final boolean pAsMask) throws IOException {
|
||||
int width = adjustToPadding((pBitmap.getWidth() + 7) >> 3);
|
||||
byte[] row = new byte[width];
|
||||
|
||||
for (int y = 0; y < bitmap.getHeight(); y++) {
|
||||
for (int y = 0; y < pBitmap.getHeight(); y++) {
|
||||
imageInput.readFully(row, 0, width);
|
||||
int rowPos = 0;
|
||||
int xOrVal = 0x80;
|
||||
int pos = (bitmap.getHeight() - y - 1) * bitmap.getWidth();
|
||||
int pos = (pBitmap.getHeight() - y - 1) * pBitmap.getWidth();
|
||||
|
||||
for (int x = 0; x < bitmap.getWidth(); x++) {
|
||||
bitmap.bits[pos++] = ((row[rowPos] & xOrVal) / xOrVal) & 0xFF;
|
||||
for (int x = 0; x < pBitmap.getWidth(); x++) {
|
||||
pBitmap.bits[pos++] = ((row[rowPos] & xOrVal) / xOrVal) & 0xFF;
|
||||
|
||||
if (xOrVal == 1) {
|
||||
xOrVal = 0x80;
|
||||
@@ -380,29 +384,29 @@ abstract class DIBImageReader extends ImageReaderBase {
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE: If we are reading the mask, we can't abort or report progress
|
||||
if (!asMask) {
|
||||
// NOTE: If we are reading the mask, we don't abort or report progress
|
||||
if (!pAsMask) {
|
||||
if (abortRequested()) {
|
||||
processReadAborted();
|
||||
break;
|
||||
}
|
||||
|
||||
processImageProgress(100 * y / (float) bitmap.getHeight());
|
||||
processImageProgress(100 * y / (float) pBitmap.getHeight());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void readBitmapIndexed4(final BitmapIndexed bitmap) throws IOException {
|
||||
int width = adjustToPadding((bitmap.getWidth() + 1) >> 1);
|
||||
private void readBitmapIndexed4(final BitmapIndexed pBitmap) throws IOException {
|
||||
int width = adjustToPadding((pBitmap.getWidth() + 1) >> 1);
|
||||
byte[] row = new byte[width];
|
||||
|
||||
for (int y = 0; y < bitmap.getHeight(); y++) {
|
||||
for (int y = 0; y < pBitmap.getHeight(); y++) {
|
||||
imageInput.readFully(row, 0, width);
|
||||
int rowPos = 0;
|
||||
boolean high4 = true;
|
||||
int pos = (bitmap.getHeight() - y - 1) * bitmap.getWidth();
|
||||
int pos = (pBitmap.getHeight() - y - 1) * pBitmap.getWidth();
|
||||
|
||||
for (int x = 0; x < bitmap.getWidth(); x++) {
|
||||
for (int x = 0; x < pBitmap.getWidth(); x++) {
|
||||
int value;
|
||||
|
||||
if (high4) {
|
||||
@@ -413,7 +417,7 @@ abstract class DIBImageReader extends ImageReaderBase {
|
||||
rowPos++;
|
||||
}
|
||||
|
||||
bitmap.bits[pos++] = value & 0xFF;
|
||||
pBitmap.bits[pos++] = value & 0xFF;
|
||||
high4 = !high4;
|
||||
}
|
||||
|
||||
@@ -422,22 +426,22 @@ abstract class DIBImageReader extends ImageReaderBase {
|
||||
break;
|
||||
}
|
||||
|
||||
processImageProgress(100 * y / (float) bitmap.getHeight());
|
||||
processImageProgress(100 * y / (float) pBitmap.getHeight());
|
||||
}
|
||||
}
|
||||
|
||||
private void readBitmapIndexed8(final BitmapIndexed bitmap) throws IOException {
|
||||
int width = adjustToPadding(bitmap.getWidth());
|
||||
private void readBitmapIndexed8(final BitmapIndexed pBitmap) throws IOException {
|
||||
int width = adjustToPadding(pBitmap.getWidth());
|
||||
|
||||
byte[] row = new byte[width];
|
||||
|
||||
for (int y = 0; y < bitmap.getHeight(); y++) {
|
||||
for (int y = 0; y < pBitmap.getHeight(); y++) {
|
||||
imageInput.readFully(row, 0, width);
|
||||
int rowPos = 0;
|
||||
int pos = (bitmap.getHeight() - y - 1) * bitmap.getWidth();
|
||||
int pos = (pBitmap.getHeight() - y - 1) * pBitmap.getWidth();
|
||||
|
||||
for (int x = 0; x < bitmap.getWidth(); x++) {
|
||||
bitmap.bits[pos++] = row[rowPos++] & 0xFF;
|
||||
for (int x = 0; x < pBitmap.getWidth(); x++) {
|
||||
pBitmap.bits[pos++] = row[rowPos++] & 0xFF;
|
||||
}
|
||||
|
||||
if (abortRequested()) {
|
||||
@@ -445,41 +449,40 @@ abstract class DIBImageReader extends ImageReaderBase {
|
||||
break;
|
||||
}
|
||||
|
||||
processImageProgress(100 * y / (float) bitmap.getHeight());
|
||||
processImageProgress(100 * y / (float) pBitmap.getHeight());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param width Bytes per scan line (i.e., 1BPP, width = 9 -> bytes = 2)
|
||||
* @param pWidth Bytes per scan line (i.e., 1BPP, width = 9 -> bytes = 1)
|
||||
* @return padded width
|
||||
*/
|
||||
private static int adjustToPadding(final int width) {
|
||||
if ((width & 0x03) != 0) {
|
||||
return (width & ~0x03) + 4;
|
||||
private static int adjustToPadding(final int pWidth) {
|
||||
if ((pWidth & 0x03) != 0) {
|
||||
return (pWidth & ~0x03) + 4;
|
||||
}
|
||||
|
||||
return width;
|
||||
return pWidth;
|
||||
}
|
||||
|
||||
private void readBitmap16(final BitmapDescriptor bitmap) throws IOException {
|
||||
short[] pixels = new short[bitmap.getWidth() * bitmap.getHeight()];
|
||||
private void readBitmap16(final BitmapDescriptor pBitmap) throws IOException {
|
||||
short[] pixels = new short[pBitmap.getWidth() * pBitmap.getHeight()];
|
||||
|
||||
// TODO: Support TYPE_USHORT_565 and the RGB 444/ARGB 4444 layouts
|
||||
// Will create TYPE_USHORT_555
|
||||
DirectColorModel cm = new DirectColorModel(16, 0x7C00, 0x03E0, 0x001F);
|
||||
DataBuffer buffer = new DataBufferUShort(pixels, pixels.length);
|
||||
WritableRaster raster = Raster.createPackedRaster(
|
||||
buffer, bitmap.getWidth(), bitmap.getHeight(), bitmap.getWidth(), cm.getMasks(), null
|
||||
buffer, pBitmap.getWidth(), pBitmap.getHeight(), pBitmap.getWidth(), cm.getMasks(), null
|
||||
);
|
||||
bitmap.image = new BufferedImage(cm, raster, cm.isAlphaPremultiplied(), null);
|
||||
pBitmap.image = new BufferedImage(cm, raster, cm.isAlphaPremultiplied(), null);
|
||||
|
||||
for (int y = 0; y < bitmap.getHeight(); y++) {
|
||||
int offset = (bitmap.getHeight() - y - 1) * bitmap.getWidth();
|
||||
imageInput.readFully(pixels, offset, bitmap.getWidth());
|
||||
for (int y = 0; y < pBitmap.getHeight(); y++) {
|
||||
int offset = (pBitmap.getHeight() - y - 1) * pBitmap.getWidth();
|
||||
imageInput.readFully(pixels, offset, pBitmap.getWidth());
|
||||
|
||||
|
||||
// Skip to 32 bit boundary
|
||||
if (bitmap.getWidth() % 2 != 0) {
|
||||
if (pBitmap.getWidth() % 2 != 0) {
|
||||
imageInput.readShort();
|
||||
}
|
||||
|
||||
@@ -488,14 +491,14 @@ abstract class DIBImageReader extends ImageReaderBase {
|
||||
break;
|
||||
}
|
||||
|
||||
processImageProgress(100 * y / (float) bitmap.getHeight());
|
||||
processImageProgress(100 * y / (float) pBitmap.getHeight());
|
||||
}
|
||||
|
||||
// TODO: Might be mask!?
|
||||
}
|
||||
|
||||
private void readBitmap24(final BitmapDescriptor bitmap) throws IOException {
|
||||
byte[] pixels = new byte[bitmap.getWidth() * bitmap.getHeight() * 3];
|
||||
private void readBitmap24(final BitmapDescriptor pBitmap) throws IOException {
|
||||
byte[] pixels = new byte[pBitmap.getWidth() * pBitmap.getHeight() * 3];
|
||||
|
||||
// Create TYPE_3BYTE_BGR
|
||||
DataBuffer buffer = new DataBufferByte(pixels, pixels.length);
|
||||
@@ -506,17 +509,17 @@ abstract class DIBImageReader extends ImageReaderBase {
|
||||
cs, nBits, false, false, Transparency.OPAQUE, DataBuffer.TYPE_BYTE
|
||||
);
|
||||
|
||||
int scanlineStride = bitmap.getWidth() * 3;
|
||||
int scanlineStride = pBitmap.getWidth() * 3;
|
||||
// BMP rows are padded to 4 byte boundary
|
||||
int rowSizeBytes = ((8 * scanlineStride + 31) / 32) * 4;
|
||||
|
||||
WritableRaster raster = Raster.createInterleavedRaster(
|
||||
buffer, bitmap.getWidth(), bitmap.getHeight(), scanlineStride, 3, bOffs, null
|
||||
buffer, pBitmap.getWidth(), pBitmap.getHeight(), scanlineStride, 3, bOffs, null
|
||||
);
|
||||
bitmap.image = new BufferedImage(cm, raster, cm.isAlphaPremultiplied(), null);
|
||||
pBitmap.image = new BufferedImage(cm, raster, cm.isAlphaPremultiplied(), null);
|
||||
|
||||
for (int y = 0; y < bitmap.getHeight(); y++) {
|
||||
int offset = (bitmap.getHeight() - y - 1) * scanlineStride;
|
||||
for (int y = 0; y < pBitmap.getHeight(); y++) {
|
||||
int offset = (pBitmap.getHeight() - y - 1) * scanlineStride;
|
||||
imageInput.readFully(pixels, offset, scanlineStride);
|
||||
imageInput.skipBytes(rowSizeBytes - scanlineStride);
|
||||
|
||||
@@ -525,38 +528,38 @@ abstract class DIBImageReader extends ImageReaderBase {
|
||||
break;
|
||||
}
|
||||
|
||||
processImageProgress(100 * y / (float) bitmap.getHeight());
|
||||
processImageProgress(100 * y / (float) pBitmap.getHeight());
|
||||
}
|
||||
|
||||
// 24 bit icons usually have a bit mask
|
||||
if (bitmap.hasMask()) {
|
||||
BitmapMask mask = new BitmapMask(bitmap.entry, bitmap.header);
|
||||
if (pBitmap.hasMask()) {
|
||||
BitmapMask mask = new BitmapMask(pBitmap.entry, pBitmap.header);
|
||||
readBitmapIndexed1(mask.bitMask, true);
|
||||
|
||||
bitmap.setMask(mask);
|
||||
pBitmap.setMask(mask);
|
||||
}
|
||||
}
|
||||
|
||||
private void readBitmap32(final BitmapDescriptor bitmap) throws IOException {
|
||||
int[] pixels = new int[bitmap.getWidth() * bitmap.getHeight()];
|
||||
private void readBitmap32(final BitmapDescriptor pBitmap) throws IOException {
|
||||
int[] pixels = new int[pBitmap.getWidth() * pBitmap.getHeight()];
|
||||
|
||||
// Will create TYPE_INT_ARGB
|
||||
DirectColorModel cm = (DirectColorModel) ColorModel.getRGBdefault();
|
||||
DataBuffer buffer = new DataBufferInt(pixels, pixels.length);
|
||||
WritableRaster raster = Raster.createPackedRaster(
|
||||
buffer, bitmap.getWidth(), bitmap.getHeight(), bitmap.getWidth(), cm.getMasks(), null
|
||||
buffer, pBitmap.getWidth(), pBitmap.getHeight(), pBitmap.getWidth(), cm.getMasks(), null
|
||||
);
|
||||
bitmap.image = new BufferedImage(cm, raster, cm.isAlphaPremultiplied(), null);
|
||||
pBitmap.image = new BufferedImage(cm, raster, cm.isAlphaPremultiplied(), null);
|
||||
|
||||
for (int y = 0; y < bitmap.getHeight(); y++) {
|
||||
int offset = (bitmap.getHeight() - y - 1) * bitmap.getWidth();
|
||||
imageInput.readFully(pixels, offset, bitmap.getWidth());
|
||||
for (int y = 0; y < pBitmap.getHeight(); y++) {
|
||||
int offset = (pBitmap.getHeight() - y - 1) * pBitmap.getWidth();
|
||||
imageInput.readFully(pixels, offset, pBitmap.getWidth());
|
||||
|
||||
if (abortRequested()) {
|
||||
processReadAborted();
|
||||
break;
|
||||
}
|
||||
processImageProgress(100 * y / (float) bitmap.getHeight());
|
||||
processImageProgress(100 * y / (float) pBitmap.getHeight());
|
||||
}
|
||||
|
||||
// There might be a mask here as well, but we'll ignore it,
|
||||
@@ -587,18 +590,18 @@ abstract class DIBImageReader extends ImageReaderBase {
|
||||
directory = Directory.read(type, imageCount, imageInput);
|
||||
}
|
||||
|
||||
final DirectoryEntry getEntry(final int imageIndex) throws IOException {
|
||||
final DirectoryEntry getEntry(final int pImageIndex) throws IOException {
|
||||
Directory directory = getDirectory();
|
||||
if (imageIndex < 0 || imageIndex >= directory.count()) {
|
||||
throw new IndexOutOfBoundsException(String.format("Index: %d, ImageCount: %d", imageIndex, directory.count()));
|
||||
if (pImageIndex < 0 || pImageIndex >= directory.count()) {
|
||||
throw new IndexOutOfBoundsException(String.format("Index: %d, ImageCount: %d", pImageIndex, directory.count()));
|
||||
}
|
||||
|
||||
return directory.getEntry(imageIndex);
|
||||
return directory.getEntry(pImageIndex);
|
||||
}
|
||||
|
||||
/// Test code below, ignore.. :-)
|
||||
public static void main(final String[] args) throws IOException {
|
||||
if (args.length == 0) {
|
||||
public static void main(final String[] pArgs) throws IOException {
|
||||
if (pArgs.length == 0) {
|
||||
System.err.println("Please specify the icon file name");
|
||||
System.exit(1);
|
||||
}
|
||||
@@ -610,7 +613,7 @@ abstract class DIBImageReader extends ImageReaderBase {
|
||||
// Ignore
|
||||
}
|
||||
|
||||
String title = new File(args[0]).getName();
|
||||
String title = new File(pArgs[0]).getName();
|
||||
JFrame frame = createWindow(title);
|
||||
JPanel root = new JPanel(new FlowLayout());
|
||||
JScrollPane scroll =
|
||||
@@ -626,7 +629,7 @@ abstract class DIBImageReader extends ImageReaderBase {
|
||||
|
||||
ImageReader reader = readers.next();
|
||||
|
||||
for (String arg : args) {
|
||||
for (String arg : pArgs) {
|
||||
JPanel panel = new JPanel(null);
|
||||
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
|
||||
readImagesInFile(arg, reader, panel);
|
||||
@@ -637,28 +640,28 @@ abstract class DIBImageReader extends ImageReaderBase {
|
||||
frame.setVisible(true);
|
||||
}
|
||||
|
||||
private static void readImagesInFile(String fileName, ImageReader reader, final Container container) throws IOException {
|
||||
File file = new File(fileName);
|
||||
private static void readImagesInFile(String pFileName, ImageReader pReader, final Container pContainer) throws IOException {
|
||||
File file = new File(pFileName);
|
||||
if (!file.isFile()) {
|
||||
System.err.println(fileName + " not found, or is no file");
|
||||
System.err.println(pFileName + " not found, or is no file");
|
||||
}
|
||||
|
||||
reader.setInput(ImageIO.createImageInputStream(file));
|
||||
int imageCount = reader.getNumImages(true);
|
||||
pReader.setInput(ImageIO.createImageInputStream(file));
|
||||
int imageCount = pReader.getNumImages(true);
|
||||
for (int i = 0; i < imageCount; i++) {
|
||||
try {
|
||||
addImage(container, reader, i);
|
||||
addImage(pContainer, pReader, i);
|
||||
}
|
||||
catch (Exception e) {
|
||||
System.err.println("FileName: " + fileName);
|
||||
System.err.println("FileName: " + pFileName);
|
||||
System.err.println("Icon: " + i);
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static JFrame createWindow(final String title) {
|
||||
JFrame frame = new JFrame(title);
|
||||
private static JFrame createWindow(final String pTitle) {
|
||||
JFrame frame = new JFrame(pTitle);
|
||||
frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
|
||||
frame.addWindowListener(new WindowAdapter() {
|
||||
public void windowClosed(WindowEvent e) {
|
||||
@@ -668,15 +671,15 @@ abstract class DIBImageReader extends ImageReaderBase {
|
||||
return frame;
|
||||
}
|
||||
|
||||
private static void addImage(final Container parent, final ImageReader reader, final int imageNo) throws IOException {
|
||||
private static void addImage(final Container pParent, final ImageReader pReader, final int pImageNo) throws IOException {
|
||||
final JButton button = new JButton();
|
||||
|
||||
BufferedImage image = reader.read(imageNo);
|
||||
BufferedImage image = pReader.read(pImageNo);
|
||||
button.setIcon(new ImageIcon(image) {
|
||||
TexturePaint texture;
|
||||
|
||||
private void createTexture(final GraphicsConfiguration graphicsConfiguration) {
|
||||
BufferedImage pattern = graphicsConfiguration.createCompatibleImage(20, 20);
|
||||
private void createTexture(final GraphicsConfiguration pGraphicsConfiguration) {
|
||||
BufferedImage pattern = pGraphicsConfiguration.createCompatibleImage(20, 20);
|
||||
Graphics2D g = pattern.createGraphics();
|
||||
try {
|
||||
g.setColor(Color.LIGHT_GRAY);
|
||||
@@ -711,6 +714,6 @@ abstract class DIBImageReader extends ImageReaderBase {
|
||||
String.valueOf(((IndexColorModel) image.getColorModel()).getMapSize()) :
|
||||
"TrueColor"));
|
||||
|
||||
parent.add(button);
|
||||
pParent.add(button);
|
||||
}
|
||||
}
|
||||
|
||||
+9
-10
@@ -44,25 +44,24 @@ import java.util.List;
|
||||
class Directory {
|
||||
private final List<DirectoryEntry> entries;
|
||||
|
||||
private Directory(int imageCount) {
|
||||
entries = Arrays.asList(new DirectoryEntry[imageCount]);
|
||||
private Directory(int pImageCount) {
|
||||
entries = Arrays.asList(new DirectoryEntry[pImageCount]);
|
||||
}
|
||||
|
||||
public static Directory read(final int type, final int imageCount, final DataInput stream) throws IOException {
|
||||
Directory directory = new Directory(imageCount);
|
||||
directory.readEntries(type, stream);
|
||||
|
||||
public static Directory read(final int pType, final int pImageCount, final DataInput pStream) throws IOException {
|
||||
Directory directory = new Directory(pImageCount);
|
||||
directory.readEntries(pType, pStream);
|
||||
return directory;
|
||||
}
|
||||
|
||||
private void readEntries(final int type, final DataInput stream) throws IOException {
|
||||
private void readEntries(final int pType, final DataInput pStream) throws IOException {
|
||||
for (int i = 0; i < entries.size(); i++) {
|
||||
entries.set(i, DirectoryEntry.read(type, stream));
|
||||
entries.set(i, DirectoryEntry.read(pType, pStream));
|
||||
}
|
||||
}
|
||||
|
||||
public DirectoryEntry getEntry(final int entryIndex) {
|
||||
return entries.get(entryIndex);
|
||||
public DirectoryEntry getEntry(final int pEntryIndex) {
|
||||
return entries.get(pEntryIndex);
|
||||
}
|
||||
|
||||
public int count() {
|
||||
|
||||
+24
-19
@@ -32,7 +32,8 @@ package com.twelvemonkeys.imageio.plugins.bmp;
|
||||
|
||||
import javax.imageio.IIOException;
|
||||
import java.awt.*;
|
||||
import java.awt.image.*;
|
||||
import java.awt.image.ColorModel;
|
||||
import java.awt.image.IndexColorModel;
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
import java.io.IOException;
|
||||
@@ -57,43 +58,47 @@ abstract class DirectoryEntry {
|
||||
DirectoryEntry() {
|
||||
}
|
||||
|
||||
public static DirectoryEntry read(final int type, final DataInput stream) throws IOException {
|
||||
DirectoryEntry entry = createEntry(type);
|
||||
entry.read(stream);
|
||||
|
||||
public static DirectoryEntry read(final int pType, final DataInput pStream) throws IOException {
|
||||
DirectoryEntry entry = createEntry(pType);
|
||||
entry.read(pStream);
|
||||
return entry;
|
||||
}
|
||||
|
||||
private static DirectoryEntry createEntry(int type) throws IIOException {
|
||||
switch (type) {
|
||||
private static DirectoryEntry createEntry(int pType) throws IIOException {
|
||||
switch (pType) {
|
||||
case DIB.TYPE_ICO:
|
||||
return new ICOEntry();
|
||||
case DIB.TYPE_CUR:
|
||||
return new CUREntry();
|
||||
default:
|
||||
throw new IIOException(String.format("Unknown DIB type: %s, expected: %s (ICO) or %s (CUR)", type, DIB.TYPE_ICO, DIB.TYPE_CUR));
|
||||
throw new IIOException(
|
||||
String.format(
|
||||
"Unknown DIB type: %s, expected: %s (ICO) or %s (CUR)",
|
||||
pType, DIB.TYPE_ICO, DIB.TYPE_CUR
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
protected void read(final DataInput stream) throws IOException {
|
||||
protected void read(final DataInput pStream) throws IOException {
|
||||
// Width/height = 0, means 256
|
||||
int w = stream.readUnsignedByte();
|
||||
int w = pStream.readUnsignedByte();
|
||||
width = w == 0 ? 256 : w;
|
||||
int h = stream.readUnsignedByte();
|
||||
int h = pStream.readUnsignedByte();
|
||||
height = h == 0 ? 256 : h;
|
||||
|
||||
// Color count = 0, means 256 or more colors
|
||||
colorCount = stream.readUnsignedByte();
|
||||
colorCount = pStream.readUnsignedByte();
|
||||
|
||||
// Ignore. Should be 0, but .NET (System.Drawing.Icon.Save) sets this value to 255, according to Wikipedia
|
||||
stream.readUnsignedByte();
|
||||
pStream.readUnsignedByte();
|
||||
|
||||
planes = stream.readUnsignedShort(); // Should be 0 or 1 for ICO, x hotspot for CUR
|
||||
bitCount = stream.readUnsignedShort(); // bit count for ICO, y hotspot for CUR
|
||||
planes = pStream.readUnsignedShort(); // Should be 0 or 1 for ICO, x hotspot for CUR
|
||||
bitCount = pStream.readUnsignedShort(); // bit count for ICO, y hotspot for CUR
|
||||
|
||||
// Size of bitmap in bytes
|
||||
size = stream.readInt();
|
||||
offset = stream.readInt();
|
||||
size = pStream.readInt();
|
||||
offset = pStream.readInt();
|
||||
}
|
||||
|
||||
void write(final DataOutput output) throws IOException {
|
||||
@@ -152,8 +157,8 @@ abstract class DirectoryEntry {
|
||||
private int yHotspot;
|
||||
|
||||
@Override
|
||||
protected void read(final DataInput stream) throws IOException {
|
||||
super.read(stream);
|
||||
protected void read(final DataInput pStream) throws IOException {
|
||||
super.read(pStream);
|
||||
|
||||
// NOTE: This is a hack...
|
||||
xHotspot = planes;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user