mirror of
https://github.com/haraldk/TwelveMonkeys.git
synced 2026-05-18 00:00:03 -04:00
Compare commits
55 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 1d47d2ef90 | |||
| 94554b0660 | |||
| a39bca4d2f | |||
| fdbbcc54a8 | |||
| 00cd9471dd | |||
| eb6a3bde39 | |||
| d3dd4c29d5 | |||
| 3355acfa03 | |||
| b70e52561a | |||
| 49ddbfa85e | |||
| 215db21569 | |||
| 0ac8011053 | |||
| abbbca9be3 | |||
| bc5473aec6 | |||
| aca8b1256a | |||
| 18c1edf0e5 | |||
| 6a01466ebb | |||
| b19df1640b | |||
| e8e3e0f1d6 | |||
| c249a21c8c | |||
| 182b2fdfa9 | |||
| df068e350d | |||
| b55c623b87 | |||
| 09573b52ac | |||
| ff7edbd223 | |||
| d8f0cd97a2 | |||
| f6971a9bce | |||
| 821965df0d | |||
| ed46305d31 | |||
| ca3adb7c45 | |||
| 59f76209bc | |||
| 2076235313 | |||
| 88bebf31f8 | |||
| 37beb21c29 | |||
| 88c0d27516 | |||
| dcd4ffccf4 | |||
| f35f5c6b24 | |||
| 9dcf53d985 | |||
| 44a2066b79 | |||
| 382c51db7c | |||
| 660f3f7e86 | |||
| b4c30872c4 | |||
| 402d4d466d | |||
| 7860bf7e17 | |||
| d52522fb80 | |||
| 8a8c6b1931 | |||
| 2930708a54 | |||
| 5661e7459c | |||
| 4d45ea4966 | |||
| 34852f7be5 | |||
| abc929a531 | |||
| 247a09ca61 | |||
| c2880fe793 | |||
| c9e522475b | |||
| 1da16e4d7a |
@@ -1,53 +0,0 @@
|
|||||||
---
|
|
||||||
name: Bug report
|
|
||||||
about: Create a report to help us improve
|
|
||||||
title: ''
|
|
||||||
labels: Reported bug
|
|
||||||
assignees: ''
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
**Describe the bug**
|
|
||||||
A clear and concise description of what the bug is.
|
|
||||||
|
|
||||||
**Version information**
|
|
||||||
1. The version of the TwelveMonkeys ImageIO library in use.
|
|
||||||
For example: 4.0.0
|
|
||||||
|
|
||||||
2. The *exact* output of `java --version` (or `java -version` for older Java releases).
|
|
||||||
For example:
|
|
||||||
|
|
||||||
java version "1.8.0_271"
|
|
||||||
Java(TM) SE Runtime Environment (build 1.8.0_271-b09)
|
|
||||||
Java HotSpot(TM) 64-Bit Server VM (build 25.271-b09, mixed mode)
|
|
||||||
|
|
||||||
3. Extra information about OS version, server version, standalone program or web application packaging, executable wrapper, etc. Please state exact version numbers where applicable.
|
|
||||||
|
|
||||||
**To Reproduce**
|
|
||||||
Steps to reproduce the behavior:
|
|
||||||
|
|
||||||
1. Compile the below sample code
|
|
||||||
2. Download the sample image file
|
|
||||||
3. Run the code with the sample file
|
|
||||||
4. See error
|
|
||||||
|
|
||||||
**Expected behavior**
|
|
||||||
A clear and concise description of what you expected to happen.
|
|
||||||
|
|
||||||
**Example code**
|
|
||||||
Preferably as a failing JUnit test, or a standalone program with a `main` method that showcases the problem.
|
|
||||||
|
|
||||||
Less is more. Don't add your entire project, only the code required to reproduce the problem. 😀
|
|
||||||
|
|
||||||
**Sample file(s)**
|
|
||||||
Attach any sample files needed to reproduce the problem. Use a ZIP-file if the format is not directly supported by GitHub.
|
|
||||||
|
|
||||||
**Stak trace**
|
|
||||||
Always include the stack trace you experience.
|
|
||||||
|
|
||||||
**Screenshots**
|
|
||||||
If applicable, add screenshots to help explain your problem.
|
|
||||||
Do not add screenshots of code or stack traces. 😀
|
|
||||||
|
|
||||||
**Additional context**
|
|
||||||
Add any other context about the problem here.
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
---
|
|
||||||
name: Feature request
|
|
||||||
about: Suggest an idea for this project
|
|
||||||
title: ''
|
|
||||||
labels: New feature
|
|
||||||
assignees: ''
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
**Is your feature request related to a use case or a problem you are working on? Please describe.**
|
|
||||||
A clear and concise description of what the problem or use case is. Understanding the rationale is key, to be able to implemeent the right solution.
|
|
||||||
|
|
||||||
**Describe the solution you'd like**
|
|
||||||
A clear and concise description of what you want to happen.
|
|
||||||
|
|
||||||
**Describe alternatives you've considered**
|
|
||||||
A clear and concise description of any alternative solutions or features you've already considered, and why they won't work.
|
|
||||||
|
|
||||||
**Additional context**
|
|
||||||
Add any other context or screenshots about the feature request here, like links to specifications or sample files.
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
---
|
|
||||||
name: Trouble shooting and programming help
|
|
||||||
about: "General programming issues will reach a wider audience at StackOverflow. Tag
|
|
||||||
questions with javax-imageio and/or twelvemonkeys \U0001F600 "
|
|
||||||
title: ''
|
|
||||||
labels: Trouble-shooting
|
|
||||||
assignees: ''
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
General programming issues and problems will reach a much wider audience at StackOverflow, we suggest you ask them there. This will offload our work with maintaining the library, and make sure you get better help sooner.
|
|
||||||
|
|
||||||
Tag the question with `javax-imageio` and/or `twelvemonkeys` and we'll find them there.
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
**What is fixed** Add link to the issue this PR fixes.
|
|
||||||
|
|
||||||
Example: Fixes #42.
|
|
||||||
|
|
||||||
**Why is this change proposed** If this change does *not* fix an open issue, briefly describe the rationale for this PR.
|
|
||||||
|
|
||||||
**What is changed** Briefly describe the changes proposed in this pull request:
|
|
||||||
|
|
||||||
* Fixed rare exception happening in `x >= 42` case
|
|
||||||
* Small optimization of `decompress()` method
|
|
||||||
* Corrected API doc for `compress()` method to reflect current implementation
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
version: 2
|
|
||||||
updates:
|
|
||||||
# Maven/Java library updates
|
|
||||||
- package-ecosystem: "maven"
|
|
||||||
directory: "/"
|
|
||||||
schedule:
|
|
||||||
interval: "daily"
|
|
||||||
open-pull-requests-limit: 10
|
|
||||||
# GitHub actions updates
|
|
||||||
- package-ecosystem: "github-actions"
|
|
||||||
directory: "/.github/workflows"
|
|
||||||
schedule:
|
|
||||||
interval: "daily"
|
|
||||||
@@ -1,127 +0,0 @@
|
|||||||
name: CI
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- '**'
|
|
||||||
- '!dependabot/**'
|
|
||||||
pull_request:
|
|
||||||
branches: [ 'master' ]
|
|
||||||
|
|
||||||
permissions: read-all
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
test:
|
|
||||||
name: Test OpenJDK ${{ matrix.java }} on ${{ matrix.os }}
|
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
os: [ ubuntu-latest, windows-latest, macos-latest ]
|
|
||||||
java: [ 11, 17, 21, 23 ]
|
|
||||||
runs-on: ${{ matrix.os }}
|
|
||||||
permissions:
|
|
||||||
checks: write
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
|
||||||
- uses: actions/setup-java@c5195efecf7bdfc987ee8bae7a71cb8b11521c00 # v4.7.1
|
|
||||||
with:
|
|
||||||
distribution: 'temurin'
|
|
||||||
java-version: ${{ matrix.java }}
|
|
||||||
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@65fe03598d8d251738592a497a9e8547a5c48eaa # v5
|
|
||||||
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 ${{ matrix.java }} on ${{ matrix.os }}
|
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
os: [ ubuntu-latest, windows-latest, macos-13 ]
|
|
||||||
runs-on: ${{ matrix.os }}
|
|
||||||
permissions:
|
|
||||||
checks: write
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
|
||||||
- uses: actions/setup-java@c5195efecf7bdfc987ee8bae7a71cb8b11521c00 # v4.7.1
|
|
||||||
with:
|
|
||||||
distribution: 'temurin'
|
|
||||||
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@65fe03598d8d251738592a497a9e8547a5c48eaa # 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:
|
|
||||||
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@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
|
||||||
- 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@c5195efecf7bdfc987ee8bae7a71cb8b11521c00 # v4.7.1
|
|
||||||
with:
|
|
||||||
distribution: 'jdkfile'
|
|
||||||
jdkFile: ${{ runner.temp }}/java_package.tar.gz
|
|
||||||
java-version: '8'
|
|
||||||
cache: 'maven'
|
|
||||||
- name: Set MAVEN_OPTS
|
|
||||||
if: ${{ matrix.kcms }}
|
|
||||||
run: |
|
|
||||||
echo "MAVEN_OPTS=-Dsun.java2d.cmm=sun.java2d.cmm.kcms.KcmsServiceProvider" >> $GITHUB_ENV
|
|
||||||
- name: Display Java version
|
|
||||||
run: java -version
|
|
||||||
- name: Run Tests
|
|
||||||
run: mvn --batch-mode --no-transfer-progress test
|
|
||||||
- name: Publish Test Report
|
|
||||||
uses: mikepenz/action-junit-report@65fe03598d8d251738592a497a9e8547a5c48eaa # v5
|
|
||||||
if: ${{ !cancelled() }}
|
|
||||||
with:
|
|
||||||
report_paths: "**/target/surefire-reports/TEST*.xml"
|
|
||||||
check_name: Unit Test Results for Oracle JDK 8 with KCMS=${{ matrix.kcms }}
|
|
||||||
|
|
||||||
release:
|
|
||||||
name: Deploy
|
|
||||||
needs: [ test, test-jdk8, test-oracle ]
|
|
||||||
if: github.ref == 'refs/heads/master' # only perform on latest master
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
|
||||||
- name: Set up Maven Central
|
|
||||||
uses: actions/setup-java@c5195efecf7bdfc987ee8bae7a71cb8b11521c00 # v4.7.1
|
|
||||||
with: # running setup-java again overwrites the settings.xml
|
|
||||||
distribution: 'temurin'
|
|
||||||
java-version: '8'
|
|
||||||
java-package: jdk
|
|
||||||
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)
|
|
||||||
- name: Get Project Version
|
|
||||||
run: |
|
|
||||||
echo "PROJECT_VERSION=$(mvn --batch-mode 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
|
|
||||||
env:
|
|
||||||
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_GPG_KEY: ${{ secrets.GPG_KEY }} # Value of the GPG private key to import
|
|
||||||
MAVEN_GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }}
|
|
||||||
@@ -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@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
|
||||||
|
|
||||||
# Initializes the CodeQL tools for scanning.
|
|
||||||
- name: Initialize CodeQL
|
|
||||||
uses: github/codeql-action/init@fca7ace96b7d713c7035871441bd52efbe39e27e # v3.28.19
|
|
||||||
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@fca7ace96b7d713c7035871441bd52efbe39e27e # v3.28.19
|
|
||||||
|
|
||||||
# ℹ️ 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@fca7ace96b7d713c7035871441bd52efbe39e27e # v3.28.19
|
|
||||||
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@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
|
||||||
with:
|
|
||||||
persist-credentials: false
|
|
||||||
|
|
||||||
- name: "Run analysis"
|
|
||||||
uses: ossf/scorecard-action@05b42c624433fc40578a4040d5cf5e36ddca8cde # v2.4.2
|
|
||||||
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@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
|
|
||||||
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@fca7ace96b7d713c7035871441bd52efbe39e27e # v3.28.19
|
|
||||||
with:
|
|
||||||
sarif_file: results.sarif
|
|
||||||
@@ -15,4 +15,3 @@ private
|
|||||||
profiles.xml
|
profiles.xml
|
||||||
Thumbs.db
|
Thumbs.db
|
||||||
.DS_Store
|
.DS_Store
|
||||||
/.metadata/
|
|
||||||
|
|||||||
+16
@@ -0,0 +1,16 @@
|
|||||||
|
dist: trusty
|
||||||
|
language: java
|
||||||
|
jdk:
|
||||||
|
- oraclejdk8 # LTS until Mar 2022
|
||||||
|
- oraclejdk11 # LTS until Sep 2023
|
||||||
|
- oraclejdk15 # out of support
|
||||||
|
- oraclejdk16 # out of support
|
||||||
|
- oraclejdk17 # LTS until Sep 2026
|
||||||
|
jobs:
|
||||||
|
include:
|
||||||
|
# Extra job, testing legacy CMM option
|
||||||
|
- jdk: oraclejdk8
|
||||||
|
env: MAVEN_OPTS=-Dsun.java2d.cmm=sun.java2d.cmm.kcms.KcmsServiceProvider
|
||||||
|
cache:
|
||||||
|
directories:
|
||||||
|
- $HOME/.m2
|
||||||
@@ -1,20 +1,13 @@
|
|||||||
[](https://github.com/haraldk/TwelveMonkeys/actions/workflows/ci.yml)
|
[](https://travis-ci.com/github/haraldk/TwelveMonkeys)
|
||||||
[](https://github.com/haraldk/TwelveMonkeys/actions/workflows/codeql.yml)
|
[](https://maven-badges.herokuapp.com/maven-central/com.twelvemonkeys.imageio/imageio)
|
||||||
[](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://stackoverflow.com/questions/tagged/twelvemonkeys)
|
||||||
[](https://paypal.me/haraldk76/100)
|
[](https://paypal.me/haraldk76/100)
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
## About
|
## About
|
||||||
|
|
||||||
TwelveMonkeys ImageIO provides extended image file format support for the Java platform, through plugins for the `javax.imageio.*` package.
|
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
|
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.
|
"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.
|
As there is lots of legacy data out there, we see the need for open implementations of readers for popular formats.
|
||||||
@@ -23,41 +16,40 @@ As there is lots of legacy data out there, we see the need for open implementati
|
|||||||
|
|
||||||
## File formats supported
|
## File formats supported
|
||||||
|
|
||||||
| Plugin | Format | Description | R | W | Metadata | Notes |
|
| Plugin | Format | Description | Read | Write | Metadata | Notes |
|
||||||
| ------ | -------- |---------------------------------------------------------|:---:|:---:| -------- | ----- |
|
| ------ | -------- | ----------- |:----:|:-----:| -------- | ----- |
|
||||||
| Batik | **SVG** | Scalable Vector Graphics | ✔ | - | - | Requires [Batik](https://xmlgraphics.apache.org/batik/) |
|
| Batik | **SVG** | Scalable Vector Graphics | ✔ | - | - | Requires [Batik](https://xmlgraphics.apache.org/batik/)
|
||||||
| | WMF | MS Windows Metafile | ✔ | - | - | Requires [Batik](https://xmlgraphics.apache.org/batik/) |
|
| | WMF | MS Windows Metafile | ✔ | - | - | Requires [Batik](https://xmlgraphics.apache.org/batik/)
|
||||||
| [BMP](https://github.com/haraldk/TwelveMonkeys/wiki/BMP-Plugin) | **BMP** | MS Windows and IBM OS/2 Device Independent Bitmap | ✔ | ✔ | [Native](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) |
|
| [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 | ✔ | - | - |
|
| | CUR | MS Windows Cursor Format | ✔ | - | - |
|
||||||
| | ICO | MS Windows Icon 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) |
|
| [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) |
|
||||||
| [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 | ✔ | ✔ | - |
|
||||||
| [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) |
|
||||||
| [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) |
|
| [JPEG](https://github.com/haraldk/TwelveMonkeys/wiki/JPEG-Plugin) | **JPEG** | Joint Photographers Expert Group | ✔ | ✔ | [Native](https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/javax/imageio/metadata/doc-files/jpeg_metadata.html#image) & [Standard](https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/javax/imageio/metadata/doc-files/standard_metadata.html) |
|
||||||
| [JPEG](https://github.com/haraldk/TwelveMonkeys/wiki/JPEG-Plugin) | **JPEG** | Joint Photographers Expert Group | ✔ | ✔ | [Native](https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/javax/imageio/metadata/doc-files/jpeg_metadata.html#image), [Standard](https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/javax/imageio/metadata/doc-files/standard_metadata.html) |
|
| | JPEG Lossless | | ✔ | - | [Native](https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/javax/imageio/metadata/doc-files/jpeg_metadata.html#image) & [Standard](https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/javax/imageio/metadata/doc-files/standard_metadata.html) |
|
||||||
| | JPEG Lossless | | ✔ | - | [Native](https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/javax/imageio/metadata/doc-files/jpeg_metadata.html#image), [Standard](https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/javax/imageio/metadata/doc-files/standard_metadata.html) |
|
| [PCX](https://github.com/haraldk/TwelveMonkeys/wiki/PCX-Plugin) | PCX | ZSoft Paintbrush Format | ✔ | - | [Standard](https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/javax/imageio/metadata/doc-files/standard_metadata.html) |
|
||||||
| [PCX](https://github.com/haraldk/TwelveMonkeys/wiki/PCX-Plugin) | PCX | ZSoft Paintbrush Format | ✔ | - | [Standard](https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/javax/imageio/metadata/doc-files/standard_metadata.html) |
|
| | DCX | Multi-page PCX fax document | ✔ | - | [Standard](https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/javax/imageio/metadata/doc-files/standard_metadata.html) |
|
||||||
| | DCX | Multi-page PCX fax document | ✔ | - | [Standard](https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/javax/imageio/metadata/doc-files/standard_metadata.html) |
|
| [PICT](https://github.com/haraldk/TwelveMonkeys/wiki/PICT-Plugin) | PICT | Apple QuickTime Picture Format | ✔ | ✔ | [Standard](https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/javax/imageio/metadata/doc-files/standard_metadata.html) |
|
||||||
| [PICT](https://github.com/haraldk/TwelveMonkeys/wiki/PICT-Plugin) | PICT | Apple QuickTime Picture Format | ✔ | ✔ | [Standard](https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/javax/imageio/metadata/doc-files/standard_metadata.html) |
|
| | PNTG | Apple MacPaint Picture Format | ✔ | | [Standard](https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/javax/imageio/metadata/doc-files/standard_metadata.html) |
|
||||||
| | PNTG | Apple MacPaint Picture Format | ✔ | - | [Standard](https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/javax/imageio/metadata/doc-files/standard_metadata.html) |
|
| [PNM](https://github.com/haraldk/TwelveMonkeys/wiki/PNM-Plugin) | PAM | NetPBM Portable Any Map | ✔ | ✔ | [Standard](https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/javax/imageio/metadata/doc-files/standard_metadata.html) |
|
||||||
| [PNM](https://github.com/haraldk/TwelveMonkeys/wiki/PNM-Plugin) | PAM | NetPBM Portable Any Map | ✔ | ✔ | [Standard](https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/javax/imageio/metadata/doc-files/standard_metadata.html) |
|
| | PBM | NetPBM Portable Bit Map | ✔ | - | [Standard](https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/javax/imageio/metadata/doc-files/standard_metadata.html) |
|
||||||
| | PBM | NetPBM Portable Bit Map | ✔ | - | [Standard](https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/javax/imageio/metadata/doc-files/standard_metadata.html) |
|
| | PGM | NetPBM Portable Grey Map | ✔ | - | [Standard](https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/javax/imageio/metadata/doc-files/standard_metadata.html) |
|
||||||
| | PGM | NetPBM Portable Grey Map | ✔ | - | [Standard](https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/javax/imageio/metadata/doc-files/standard_metadata.html) |
|
| | PPM | NetPBM Portable Pix Map | ✔ | ✔ | [Standard](https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/javax/imageio/metadata/doc-files/standard_metadata.html) |
|
||||||
| | PPM | NetPBM Portable Pix Map | ✔ | ✔ | [Standard](https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/javax/imageio/metadata/doc-files/standard_metadata.html) |
|
| | PFM | Portable Float Map | ✔ | - | [Standard](https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/javax/imageio/metadata/doc-files/standard_metadata.html) |
|
||||||
| | PFM | Portable Float Map | ✔ | - | [Standard](https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/javax/imageio/metadata/doc-files/standard_metadata.html) |
|
| [PSD](https://github.com/haraldk/TwelveMonkeys/wiki/PSD-Plugin) | **PSD** | Adobe Photoshop Document | ✔ | - | Native & [Standard](https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/javax/imageio/metadata/doc-files/standard_metadata.html) |
|
||||||
| [PSD](https://github.com/haraldk/TwelveMonkeys/wiki/PSD-Plugin) | **PSD** | Adobe Photoshop Document | ✔ | (✔) | Native, [Standard](https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/javax/imageio/metadata/doc-files/standard_metadata.html) |
|
| | PSB | Adobe Photoshop Large Document | ✔ | - | Native & [Standard](https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/javax/imageio/metadata/doc-files/standard_metadata.html) |
|
||||||
| | PSB | Adobe Photoshop Large Document | ✔ | - | Native, [Standard](https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/javax/imageio/metadata/doc-files/standard_metadata.html) |
|
| [SGI](https://github.com/haraldk/TwelveMonkeys/wiki/SGI-Plugin) | SGI | Silicon Graphics Image Format | ✔ | - | [Standard](https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/javax/imageio/metadata/doc-files/standard_metadata.html) |
|
||||||
| [SGI](https://github.com/haraldk/TwelveMonkeys/wiki/SGI-Plugin) | SGI | Silicon Graphics Image Format | ✔ | - | [Standard](https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/javax/imageio/metadata/doc-files/standard_metadata.html) |
|
| [TGA](https://github.com/haraldk/TwelveMonkeys/wiki/TGA-Plugin) | TGA | Truevision TGA Image Format | ✔ | ✔ | [Standard](https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/javax/imageio/metadata/doc-files/standard_metadata.html) |
|
||||||
| [TGA](https://github.com/haraldk/TwelveMonkeys/wiki/TGA-Plugin) | TGA | Truevision TGA Image Format | ✔ | ✔ | [Standard](https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/javax/imageio/metadata/doc-files/standard_metadata.html) |
|
|ThumbsDB| Thumbs.db| MS Windows Thumbs DB | ✔ | - | - | OLE2 Compound Document based format only
|
||||||
|ThumbsDB| Thumbs.db| MS Windows Thumbs DB | ✔ | - | - | OLE2 Compound Document based format only |
|
| [TIFF](https://github.com/haraldk/TwelveMonkeys/wiki/TIFF-Plugin) | **TIFF** | Aldus/Adobe Tagged Image File Format | ✔ | ✔ | [Native](https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/javax/imageio/metadata/doc-files/tiff_metadata.html#ImageMetadata) & [Standard](https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/javax/imageio/metadata/doc-files/standard_metadata.html) |
|
||||||
| [TIFF](https://github.com/haraldk/TwelveMonkeys/wiki/TIFF-Plugin) | **TIFF** | Aldus/Adobe Tagged Image File Format | ✔ | ✔ | [Native](https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/javax/imageio/metadata/doc-files/tiff_metadata.html#ImageMetadata), [Standard](https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/javax/imageio/metadata/doc-files/standard_metadata.html) |
|
| | BigTIFF | | ✔ | - | [Native](https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/javax/imageio/metadata/doc-files/tiff_metadata.html#ImageMetadata) & [Standard](https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/javax/imageio/metadata/doc-files/standard_metadata.html) |
|
||||||
| | BigTIFF | | ✔ | ✔ | [Native](https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/javax/imageio/metadata/doc-files/tiff_metadata.html#ImageMetadata), [Standard](https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/javax/imageio/metadata/doc-files/standard_metadata.html) |
|
| [WebP](https://github.com/haraldk/TwelveMonkeys/wiki/WebP-Plugin) | **WebP** | Google WebP Format | ✔ | - | [Standard](https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/javax/imageio/metadata/doc-files/standard_metadata.html) |
|
||||||
| [WebP](https://github.com/haraldk/TwelveMonkeys/wiki/WebP-Plugin) | **WebP** | Google WebP Format | ✔ | - | [Standard](https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/javax/imageio/metadata/doc-files/standard_metadata.html) |
|
| XWD | XWD | X11 Window Dump Format | ✔ | - | [Standard](https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/javax/imageio/metadata/doc-files/standard_metadata.html) |
|
||||||
| XWD | XWD | X11 Window Dump Format | ✔ | - | [Standard](https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/javax/imageio/metadata/doc-files/standard_metadata.html) |
|
|
||||||
|
|
||||||
|
|
||||||
**Important note on using Batik:** *Please read [The Apache™ XML Graphics Project - Security](https://xmlgraphics.apache.org/security.html),
|
**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
|
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).
|
[JDK standard plugins](https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/javax/imageio/package-summary.html).
|
||||||
@@ -223,43 +215,6 @@ BufferedImageOp ditherer = new DiffusionDither();
|
|||||||
BufferedImage output = ditherer.filter(input, null);
|
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
|
## Building
|
||||||
|
|
||||||
Download the project (using [Git](https://git-scm.com/downloads)):
|
Download the project (using [Git](https://git-scm.com/downloads)):
|
||||||
@@ -316,12 +271,12 @@ To depend on the JPEG and TIFF plugin using Maven, add the following to your POM
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.twelvemonkeys.imageio</groupId>
|
<groupId>com.twelvemonkeys.imageio</groupId>
|
||||||
<artifactId>imageio-jpeg</artifactId>
|
<artifactId>imageio-jpeg</artifactId>
|
||||||
<version>3.12.0</version>
|
<version>3.7.0</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.twelvemonkeys.imageio</groupId>
|
<groupId>com.twelvemonkeys.imageio</groupId>
|
||||||
<artifactId>imageio-tiff</artifactId>
|
<artifactId>imageio-tiff</artifactId>
|
||||||
<version>3.12.0</version>
|
<version>3.7.0</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
@@ -331,17 +286,7 @@ To depend on the JPEG and TIFF plugin using Maven, add the following to your POM
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.twelvemonkeys.servlet</groupId>
|
<groupId>com.twelvemonkeys.servlet</groupId>
|
||||||
<artifactId>servlet</artifactId>
|
<artifactId>servlet</artifactId>
|
||||||
<version>3.12.0</version>
|
<version>3.7.0</version>
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<!--
|
|
||||||
Or Jakarta version, for Servlet API 5.0
|
|
||||||
-->
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.twelvemonkeys.servlet</groupId>
|
|
||||||
<artifactId>servlet</artifactId>
|
|
||||||
<version>3.12.0</version>
|
|
||||||
<classifier>jakarta</classifier>
|
|
||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
```
|
```
|
||||||
@@ -350,18 +295,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:
|
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-lang-3.7.0.jar
|
||||||
twelvemonkeys-common-io-3.12.0.jar
|
twelvemonkeys-common-io-3.7.0.jar
|
||||||
twelvemonkeys-common-image-3.12.0.jar
|
twelvemonkeys-common-image-3.7.0.jar
|
||||||
twelvemonkeys-imageio-core-3.12.0.jar
|
twelvemonkeys-imageio-core-3.7.0.jar
|
||||||
twelvemonkeys-imageio-metadata-3.12.0.jar
|
twelvemonkeys-imageio-metadata-3.7.0.jar
|
||||||
twelvemonkeys-imageio-jpeg-3.12.0.jar
|
twelvemonkeys-imageio-jpeg-3.7.0.jar
|
||||||
twelvemonkeys-imageio-tiff-3.12.0.jar
|
twelvemonkeys-imageio-tiff-3.7.0.jar
|
||||||
|
|
||||||
#### Deploying the plugins in a web app
|
#### Deploying the plugins in a web app
|
||||||
|
|
||||||
Because the `ImageIO` plugin registry (the `IIORegistry`) is "VM global", it does not work well with
|
Because the `ImageIO` plugin registry (the `IIORegistry`) is "VM global", it doesn't by default work well with
|
||||||
servlet contexts as-is. This is especially evident if you load plugins from the `WEB-INF/lib` or `classes` folder.
|
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.
|
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).
|
In addition, servlet contexts dynamically loads and unloads classes (using a new class loader per context).
|
||||||
@@ -397,16 +342,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.
|
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
|
#### 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.
|
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 +367,81 @@ Other "fat" JAR bundlers will probably have similar mechanisms to merge entries
|
|||||||
|
|
||||||
### Links to prebuilt binaries
|
### Links to prebuilt binaries
|
||||||
|
|
||||||
##### Latest version (3.12.0)
|
##### Latest version (3.7.0)
|
||||||
|
|
||||||
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 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-lang-3.7.0.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/common/common-lang/3.7.0/common-lang-3.7.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-io-3.7.0.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/common/common-io/3.7.0/common-io-3.7.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-image-3.7.0.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/common/common-image/3.7.0/common-image-3.7.0.jar)
|
||||||
|
|
||||||
ImageIO dependencies
|
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-core-3.7.0.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-core/3.7.0/imageio-core-3.7.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-metadata-3.7.0.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-metadata/3.7.0/imageio-metadata-3.7.0.jar)
|
||||||
|
|
||||||
ImageIO plugins
|
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-bmp-3.7.0.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-bmp/3.7.0/imageio-bmp-3.7.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.7.0.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-hdr/3.7.0/imageio-hdr-3.7.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.7.0.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-icns/3.7.0/imageio-icns-3.7.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.7.0.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-iff/3.7.0/imageio-iff-3.7.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.7.0.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-jpeg/3.7.0/imageio-jpeg-3.7.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.7.0.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-pcx/3.7.0/imageio-pcx-3.7.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.7.0.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-pict/3.7.0/imageio-pict-3.7.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.7.0.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-pnm/3.7.0/imageio-pnm-3.7.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.7.0.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-psd/3.7.0/imageio-psd-3.7.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.7.0.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-sgi/3.7.0/imageio-sgi-3.7.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.7.0.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-tga/3.7.0/imageio-tga-3.7.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.7.0.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-thumbsdb/3.7.0/imageio-thumbsdb-3.7.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.7.0.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-tiff/3.7.0/imageio-tiff-3.7.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.7.0.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-webp/3.7.0/imageio-webp-3.7.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.7.0.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-xwd/3.7.0/imageio-xwd-3.7.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 plugins requiring 3rd party libs
|
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.7.0.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-batik/3.7.0/imageio-batik-3.7.0.jar)
|
||||||
|
|
||||||
Photoshop Path support for ImageIO
|
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.7.0.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-clippath/3.7.0/imageio-clippath-3.7.0.jar)
|
||||||
|
|
||||||
Servlet support
|
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.7.0.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/servlet/servlet/3.7.0/servlet-3.7.0.jar)
|
||||||
* [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)
|
|
||||||
|
##### 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
|
## License
|
||||||
|
|
||||||
This project is provided under the OSI approved [BSD license](https://opensource.org/licenses/BSD-3-Clause):
|
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.
|
All rights reserved.
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
Redistribution and use in source and binary forms, with or without
|
||||||
@@ -509,9 +473,8 @@ This project is provided under the OSI approved [BSD license](https://opensource
|
|||||||
|
|
||||||
q: How do I use it?
|
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,
|
a: The easiest way is to build your own project using Maven, and just add dependencies to the specific plug-ins you need.
|
||||||
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.
|
||||||
If you don't use such a build tool, 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?
|
q: What changes do I have to make to my code in order to use the plug-ins?
|
||||||
@@ -529,41 +492,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.
|
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).
|
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
|
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
|
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
|
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.
|
cases you'll end up using the TwelveMonkeys plug-ins instead.
|
||||||
|
|
||||||
|
|
||||||
q: Why is there no support for common formats like GIF or PNG?
|
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).
|
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.
|
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.
|
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:
|
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.
|
- 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.
|
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.
|
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>
|
<parent>
|
||||||
<groupId>com.twelvemonkeys</groupId>
|
<groupId>com.twelvemonkeys</groupId>
|
||||||
<artifactId>twelvemonkeys</artifactId>
|
<artifactId>twelvemonkeys</artifactId>
|
||||||
<version>3.12.1-SNAPSHOT</version>
|
<version>3.7.1</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<groupId>com.twelvemonkeys.bom</groupId>
|
<groupId>com.twelvemonkeys.bom</groupId>
|
||||||
@@ -63,11 +63,6 @@
|
|||||||
<artifactId>imageio-hdr</artifactId>
|
<artifactId>imageio-hdr</artifactId>
|
||||||
<version>${project.version}</version>
|
<version>${project.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>com.twelvemonkeys.imageio</groupId>
|
|
||||||
<artifactId>imageio-dds</artifactId>
|
|
||||||
<version>${project.version}</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.twelvemonkeys.imageio</groupId>
|
<groupId>com.twelvemonkeys.imageio</groupId>
|
||||||
<artifactId>imageio-icns</artifactId>
|
<artifactId>imageio-icns</artifactId>
|
||||||
|
|||||||
@@ -4,13 +4,13 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>com.twelvemonkeys.common</groupId>
|
<groupId>com.twelvemonkeys.common</groupId>
|
||||||
<artifactId>common</artifactId>
|
<artifactId>common</artifactId>
|
||||||
<version>3.12.1-SNAPSHOT</version>
|
<version>3.7.1</version>
|
||||||
</parent>
|
</parent>
|
||||||
<artifactId>common-image</artifactId>
|
<artifactId>common-image</artifactId>
|
||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
<name>TwelveMonkeys :: Common :: Image</name>
|
<name>TwelveMonkeys :: Common :: Image</name>
|
||||||
<description>
|
<description>
|
||||||
TwelveMonkeys Common image support classes.
|
The TwelveMonkeys Common Image support
|
||||||
</description>
|
</description>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
@@ -28,14 +28,12 @@
|
|||||||
<artifactId>common-io</artifactId>
|
<artifactId>common-io</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>jmagick</groupId>
|
||||||
|
<artifactId>jmagick</artifactId>
|
||||||
|
<version>6.2.4</version>
|
||||||
|
<optional>true</optional>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
|
||||||
<plugins>
|
|
||||||
<plugin>
|
|
||||||
<groupId>org.apache.felix</groupId>
|
|
||||||
<artifactId>maven-bundle-plugin</artifactId>
|
|
||||||
</plugin>
|
|
||||||
</plugins>
|
|
||||||
</build>
|
|
||||||
</project>
|
</project>
|
||||||
|
|||||||
+87
-97
@@ -79,7 +79,7 @@ public final class BufferedImageFactory {
|
|||||||
private int scanSize;
|
private int scanSize;
|
||||||
|
|
||||||
private ColorModel sourceColorModel;
|
private ColorModel sourceColorModel;
|
||||||
private Hashtable<?, ?> sourceProperties; // ImageConsumer API dictates Hashtable
|
private Hashtable sourceProperties; // ImageConsumer API dictates Hashtable
|
||||||
|
|
||||||
private Object sourcePixels;
|
private Object sourcePixels;
|
||||||
|
|
||||||
@@ -91,21 +91,21 @@ public final class BufferedImageFactory {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a {@code BufferedImageFactory}.
|
* Creates a {@code BufferedImageFactory}.
|
||||||
* @param source the source image
|
* @param pSource the source image
|
||||||
* @throws IllegalArgumentException if {@code source == null}
|
* @throws IllegalArgumentException if {@code pSource == null}
|
||||||
*/
|
*/
|
||||||
public BufferedImageFactory(final Image source) {
|
public BufferedImageFactory(final Image pSource) {
|
||||||
this(source != null ? source.getSource() : null);
|
this(pSource != null ? pSource.getSource() : null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a {@code BufferedImageFactory}.
|
* Creates a {@code BufferedImageFactory}.
|
||||||
* @param source the source image producer
|
* @param pSource the source image producer
|
||||||
* @throws IllegalArgumentException if {@code source == null}
|
* @throws IllegalArgumentException if {@code pSource == null}
|
||||||
*/
|
*/
|
||||||
public BufferedImageFactory(final ImageProducer source) {
|
public BufferedImageFactory(final ImageProducer pSource) {
|
||||||
Validate.notNull(source, "source");
|
Validate.notNull(pSource, "source");
|
||||||
producer = source;
|
producer = pSource;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -155,44 +155,44 @@ public final class BufferedImageFactory {
|
|||||||
/**
|
/**
|
||||||
* Sets the source region (AOI) for the new image.
|
* 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
|
// 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();
|
dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
x = region.x;
|
x = pRegion.x;
|
||||||
y = region.y;
|
y = pRegion.y;
|
||||||
width = region.width;
|
width = pRegion.width;
|
||||||
height = region.height;
|
height = pRegion.height;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the source subsampling for the new image.
|
* Sets the source subsampling for the new image.
|
||||||
*
|
*
|
||||||
* @param xSubsampling horizontal subsampling factor
|
* @param pXSub horizontal subsampling factor
|
||||||
* @param ySubsampling vertical 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
|
// Re-fetch everything, if subsampling changed
|
||||||
if (xSub != xSubsampling || ySub != ySubsampling) {
|
if (xSub != pXSub || ySub != pYSub) {
|
||||||
dispose();
|
dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (xSubsampling > 1) {
|
if (pXSub > 1) {
|
||||||
xSub = xSubsampling;
|
xSub = pXSub;
|
||||||
}
|
}
|
||||||
if (ySubsampling > 1) {
|
if (pYSub > 1) {
|
||||||
ySub = ySubsampling;
|
ySub = pYSub;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private synchronized void doFetch(final boolean colorModelOnly) throws ImageConversionException {
|
private synchronized void doFetch(boolean pColorModelOnly) throws ImageConversionException {
|
||||||
if (!fetching && (!colorModelOnly && buffered == null || buffered == null && sourceColorModel == null)) {
|
if (!fetching && (!pColorModelOnly && buffered == null || buffered == null && sourceColorModel == null)) {
|
||||||
// NOTE: Subsampling is only applied if extracting full image
|
// 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 only sampling a region, the region must be scaled too
|
||||||
if (width > 0 && height > 0) {
|
if (width > 0 && height > 0) {
|
||||||
width = (width + xSub - 1) / xSub;
|
width = (width + xSub - 1) / xSub;
|
||||||
@@ -207,41 +207,38 @@ public final class BufferedImageFactory {
|
|||||||
|
|
||||||
// Start fetching
|
// Start fetching
|
||||||
fetching = true;
|
fetching = true;
|
||||||
readColorModelOnly = colorModelOnly;
|
readColorModelOnly = pColorModelOnly;
|
||||||
|
|
||||||
producer.startProduction(consumer); // Note: If single-thread (synchronous), this call will block
|
producer.startProduction(consumer); // Note: If single-thread (synchronous), this call will block
|
||||||
|
|
||||||
// Wait until the producer wakes us up, by calling imageComplete
|
// Wait until the producer wakes us up, by calling imageComplete
|
||||||
while (fetching) {
|
while (fetching) {
|
||||||
try {
|
try {
|
||||||
wait(200L);
|
wait(200l);
|
||||||
}
|
}
|
||||||
catch (InterruptedException e) {
|
catch (InterruptedException e) {
|
||||||
throw new ImageConversionException("Image conversion aborted: " + e.getMessage(), e);
|
throw new ImageConversionException("Image conversion aborted: " + e.getMessage(), e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
if (consumerException != null) {
|
||||||
if (consumerException != null) {
|
throw new ImageConversionException("Image conversion failed: " + consumerException.getMessage(), consumerException);
|
||||||
throw new ImageConversionException("Image conversion failed: " + consumerException.getMessage(), consumerException);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (colorModelOnly) {
|
|
||||||
createColorModel();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
createBuffered();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
finally {
|
|
||||||
// Clean up, in case any objects are copied/cloned, so we can free resources
|
if (pColorModelOnly) {
|
||||||
freeResources();
|
createColorModel();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
createBuffered();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void createColorModel() {
|
private void createColorModel() {
|
||||||
colorModel = sourceColorModel;
|
colorModel = sourceColorModel;
|
||||||
|
|
||||||
|
// Clean up, in case any objects are copied/cloned, so we can free resources
|
||||||
|
freeResources();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void createBuffered() {
|
private void createBuffered() {
|
||||||
@@ -256,9 +253,8 @@ public final class BufferedImageFactory {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (buffered == null) {
|
// Clean up, in case any objects are copied/cloned, so we can free resources
|
||||||
throw new ImageConversionException("Could not create BufferedImage");
|
freeResources();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void freeResources() {
|
private void freeResources() {
|
||||||
@@ -284,27 +280,27 @@ public final class BufferedImageFactory {
|
|||||||
/**
|
/**
|
||||||
* Adds a progress listener to this factory.
|
* Adds a progress listener to this factory.
|
||||||
*
|
*
|
||||||
* @param listener the progress listener
|
* @param pListener the progress listener
|
||||||
*/
|
*/
|
||||||
public void addProgressListener(ProgressListener listener) {
|
public void addProgressListener(ProgressListener pListener) {
|
||||||
if (listener == null) {
|
if (pListener == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (listeners == null) {
|
if (listeners == null) {
|
||||||
listeners = new CopyOnWriteArrayList<>();
|
listeners = new CopyOnWriteArrayList<ProgressListener>();
|
||||||
}
|
}
|
||||||
|
|
||||||
listeners.add(listener);
|
listeners.add(pListener);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes a progress listener from this factory.
|
* Removes a progress listener from this factory.
|
||||||
*
|
*
|
||||||
* @param listener the progress listener
|
* @param pListener the progress listener
|
||||||
*/
|
*/
|
||||||
public void removeProgressListener(ProgressListener listener) {
|
public void removeProgressListener(ProgressListener pListener) {
|
||||||
if (listener == null) {
|
if (pListener == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -312,7 +308,7 @@ public final class BufferedImageFactory {
|
|||||||
return;
|
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}
|
* Converts an array of {@code int} pixels to an array of {@code short}
|
||||||
* pixels. The conversion is done, by masking out the
|
* pixels. The conversion is done, by masking out the
|
||||||
* <em>higher 16 bits</em> of the {@code int}.
|
* <em>higher 16 bits</em> of the {@code int}.
|
||||||
* <p>
|
*
|
||||||
* For any given {@code int}, the {@code short} value is computed as
|
* For any given {@code int}, the {@code short} value is computed as
|
||||||
* follows:
|
* follows:
|
||||||
* <blockquote>{@code
|
* <blockquote>{@code
|
||||||
* short value = (short) (intValue & 0x0000ffff);
|
* short value = (short) (intValue & 0x0000ffff);
|
||||||
* }</blockquote>
|
* }</blockquote>
|
||||||
* </p>
|
|
||||||
*
|
*
|
||||||
* @param inputPixels the pixel data to convert
|
* @param pPixels the pixel data to convert
|
||||||
* @return an array of {@code short}s, same length as {@code inputPixels}
|
* @return an array of {@code short}s, same lenght as {@code pPixels}
|
||||||
*/
|
*/
|
||||||
private static short[] toShortPixels(int[] inputPixels) {
|
private static short[] toShortPixels(int[] pPixels) {
|
||||||
short[] pixels = new short[inputPixels.length];
|
short[] pixels = new short[pPixels.length];
|
||||||
|
|
||||||
for (int i = 0; i < pixels.length; i++) {
|
for (int i = 0; i < pixels.length; i++) {
|
||||||
pixels[i] = (short) (inputPixels[i] & 0xffff);
|
pixels[i] = (short) (pPixels[i] & 0xffff);
|
||||||
}
|
}
|
||||||
|
|
||||||
return pixels;
|
return pixels;
|
||||||
@@ -356,17 +351,17 @@ public final class BufferedImageFactory {
|
|||||||
* @see BufferedImageFactory#addProgressListener
|
* @see BufferedImageFactory#addProgressListener
|
||||||
* @see BufferedImageFactory#removeProgressListener
|
* @see BufferedImageFactory#removeProgressListener
|
||||||
*/
|
*/
|
||||||
public interface ProgressListener extends EventListener {
|
public static interface ProgressListener extends EventListener {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reports progress to this listener.
|
* Reports progress to this listener.
|
||||||
* Invoked by the {@code BufferedImageFactory} to report progress in
|
* Invoked by the {@code BufferedImageFactory} to report progress in
|
||||||
* the image decoding.
|
* the image decoding.
|
||||||
*
|
*
|
||||||
* @param factory the factory reporting the progress
|
* @param pFactory the factory reporting the progress
|
||||||
* @param percentage the percentage of progress
|
* @param pPercentage the percentage of progress
|
||||||
*/
|
*/
|
||||||
void progress(BufferedImageFactory factory, float percentage);
|
void progress(BufferedImageFactory pFactory, float pPercentage);
|
||||||
}
|
}
|
||||||
|
|
||||||
private class Consumer implements ImageConsumer {
|
private class Consumer implements ImageConsumer {
|
||||||
@@ -451,18 +446,18 @@ public final class BufferedImageFactory {
|
|||||||
processProgress(pY + pHeight);
|
processProgress(pY + pHeight);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setPixels(int x, int y, int width, int height, ColorModel colorModel, short[] pixels, int offset, int scanSize) {
|
public void setPixels(int pX, int pY, int pWidth, int pHeight, ColorModel pModel, short[] pPixels, int pOffset, int pScanSize) {
|
||||||
setPixelsImpl(x, y, width, height, colorModel, pixels, offset, scanSize);
|
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
|
// NOTE: There seems to be a "bug" in AreaAveragingScaleFilter, as it
|
||||||
// first passes the original color model through in setColorModel, then
|
// first passes the original color model through in setColorModel, then
|
||||||
// later replaces it with the default RGB in the first setPixels call
|
// 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).
|
// (this is probably allowed according to the spec, but it's a waste of time and space).
|
||||||
if (sourceColorModel != colorModel) {
|
if (sourceColorModel != pModel) {
|
||||||
if (sourcePixels == null) {
|
if (/*sourceColorModel == null ||*/ sourcePixels == null) {
|
||||||
sourceColorModel = colorModel;
|
sourceColorModel = pModel;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
throw new IllegalStateException("Change of ColorModel after pixel delivery not supported");
|
throw new IllegalStateException("Change of ColorModel after pixel delivery not supported");
|
||||||
@@ -475,16 +470,17 @@ public final class BufferedImageFactory {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public void imageComplete(int pStatus) {
|
||||||
public void imageComplete(int status) {
|
|
||||||
fetching = false;
|
fetching = false;
|
||||||
|
|
||||||
if (producer != null) {
|
if (producer != null) {
|
||||||
producer.removeConsumer(this);
|
producer.removeConsumer(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (status == ImageConsumer.IMAGEERROR) {
|
switch (pStatus) {
|
||||||
consumerException = new ImageConversionException("ImageConsumer.IMAGEERROR");
|
case ImageConsumer.IMAGEERROR:
|
||||||
|
consumerException = new ImageConversionException("ImageConsumer.IMAGEERROR");
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
synchronized (BufferedImageFactory.this) {
|
synchronized (BufferedImageFactory.this) {
|
||||||
@@ -492,18 +488,16 @@ public final class BufferedImageFactory {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public void setColorModel(ColorModel pModel) {
|
||||||
public void setColorModel(ColorModel colorModel) {
|
setColorModelOnce(pModel);
|
||||||
setColorModelOnce(colorModel);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public void setDimensions(int pWidth, int pHeight) {
|
||||||
public void setDimensions(int w, int h) {
|
|
||||||
if (width < 0) {
|
if (width < 0) {
|
||||||
width = w - x;
|
width = pWidth - x;
|
||||||
}
|
}
|
||||||
if (height < 0) {
|
if (height < 0) {
|
||||||
height = h - y;
|
height = pHeight - y;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hmm.. Special case, but is it a good idea?
|
// Hmm.. Special case, but is it a good idea?
|
||||||
@@ -512,31 +506,27 @@ public final class BufferedImageFactory {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public void setHints(int pHintflags) {
|
||||||
public void setHints(int hintFlags) {
|
|
||||||
// ignore
|
// ignore
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public void setPixels(int pX, int pY, int pWidth, int pHeight, ColorModel pModel, byte[] pPixels, int pOffset, int pScanSize) {
|
||||||
public void setPixels(int x, int y, int width, int height, ColorModel colorModel, byte[] pixels, int offset, int scanSize) {
|
setPixelsImpl(pX, pY, pWidth, pHeight, pModel, pPixels, pOffset, pScanSize);
|
||||||
setPixelsImpl(x, y, width, height, colorModel, pixels, offset, scanSize);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public void setPixels(int pX, int pY, int pWeigth, int pHeight, ColorModel pModel, int[] pPixels, int pOffset, int pScanSize) {
|
||||||
public void setPixels(int x, int y, int width, int height, ColorModel colorModel, int[] pixels, int offset, int scanSize) {
|
if (pModel.getTransferType() == DataBuffer.TYPE_USHORT) {
|
||||||
if (colorModel.getTransferType() == DataBuffer.TYPE_USHORT) {
|
|
||||||
// NOTE: Workaround for limitation in ImageConsumer API
|
// NOTE: Workaround for limitation in ImageConsumer API
|
||||||
// Convert int[] to short[], to be compatible with the ColorModel
|
// 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 {
|
else {
|
||||||
setPixelsImpl(x, y, width, height, colorModel, pixels, offset, scanSize);
|
setPixelsImpl(pX, pY, pWeigth, pHeight, pModel, pPixels, pOffset, pScanSize);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public void setProperties(Hashtable pProperties) {
|
||||||
public void setProperties(Hashtable properties) {
|
sourceProperties = pProperties;
|
||||||
sourceProperties = properties;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -844,7 +844,7 @@ public final class ImageUtil {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < mapSize1; i++) {
|
for (int i = 0; i > mapSize1; i++) {
|
||||||
if (icm1.getRGB(i) != icm2.getRGB(i)) {
|
if (icm1.getRGB(i) != icm2.getRGB(i)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
Regular → Executable
+22
-17
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2024, Paul Allen, Harald Kuhr
|
* Copyright (c) 2008, Harald Kuhr
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@@ -28,23 +28,28 @@
|
|||||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.twelvemonkeys.imageio.plugins.dds;
|
|
||||||
|
|
||||||
import com.twelvemonkeys.imageio.spi.ReaderWriterProviderInfo;
|
package com.twelvemonkeys.image;
|
||||||
|
|
||||||
final class DDSProviderInfo extends ReaderWriterProviderInfo {
|
/**
|
||||||
DDSProviderInfo() {
|
* Magick
|
||||||
super(
|
*
|
||||||
DDSProviderInfo.class,
|
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||||
new String[]{"DDS", "dds"},
|
* @author last modified by $Author: haku $
|
||||||
new String[]{"dds"},
|
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-core/src/main/java/com/twelvemonkeys/image/Magick.java#1 $
|
||||||
new String[]{"image/vnd-ms.dds"},
|
*/
|
||||||
"com.twelvemonkeys.imageio.plugins.dds.DDSImageReader",
|
final class Magick {
|
||||||
new String[]{"com.twelvemonkeys.imageio.plugins.dds.DDSImageReaderSpi"},
|
static final boolean DEBUG = useDebug();
|
||||||
null,
|
|
||||||
null,
|
private static boolean useDebug() {
|
||||||
false, null, null, null, null,
|
try {
|
||||||
true, null, null, null, null
|
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;
|
package com.twelvemonkeys.image;
|
||||||
|
|
||||||
import java.awt.*;
|
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.*;
|
import java.awt.image.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -101,6 +103,15 @@ import java.awt.image.*;
|
|||||||
* BufferedImage scaled = new ResampleOp(w, h).filter(temp, null);
|
* BufferedImage scaled = new ResampleOp(w, h).filter(temp, null);
|
||||||
* </pre></blockquote>
|
* </pre></blockquote>
|
||||||
* <p>
|
* <p>
|
||||||
|
* For maximum performance, this class will use native code, through
|
||||||
|
* <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
|
* This {@code BufferedImageOp} is based on C example code found in
|
||||||
* <a href="http://www.acm.org/tog/GraphicsGems/">Graphics Gems III</a>,
|
* <a href="http://www.acm.org/tog/GraphicsGems/">Graphics Gems III</a>,
|
||||||
* Filtered Image Rescaling, by Dale Schumacher (with additional improvments by
|
* Filtered Image Rescaling, by Dale Schumacher (with additional improvments by
|
||||||
@@ -128,6 +139,9 @@ import java.awt.image.*;
|
|||||||
// TODO: Consider using AffineTransformOp for more operations!?
|
// TODO: Consider using AffineTransformOp for more operations!?
|
||||||
public class ResampleOp implements BufferedImageOp/* TODO: RasterOp */ {
|
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.
|
* 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);
|
new Value(KEY_RESAMPLE_INTERPOLATION, "Blackman-Sinc", FILTER_BLACKMAN_SINC);
|
||||||
|
|
||||||
// Member variables
|
// Member variables
|
||||||
private final int width;
|
// Package access, to allow access from MagickAccelerator
|
||||||
private final int height;
|
int width;
|
||||||
|
int height;
|
||||||
|
|
||||||
private final int filterType;
|
int filterType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* RendereingHints.Key implementation, works only with Value values.
|
* RendereingHints.Key implementation, works only with Value values.
|
||||||
@@ -532,6 +547,16 @@ public class ResampleOp implements BufferedImageOp/* TODO: RasterOp */ {
|
|||||||
// Fall through
|
// 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
|
// If filter type != POINT or BOX and input has IndexColorModel, convert
|
||||||
// to true color, with alpha reflecting that of the original color model.
|
// to true color, with alpha reflecting that of the original color model.
|
||||||
BufferedImage temp;
|
BufferedImage temp;
|
||||||
@@ -546,7 +571,7 @@ public class ResampleOp implements BufferedImageOp/* TODO: RasterOp */ {
|
|||||||
|
|
||||||
// Create or convert output to a suitable image
|
// Create or convert output to a suitable image
|
||||||
// TODO: OPTIMIZE: Don't really need to convert all types to same as input
|
// 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);
|
resample(temp, result, filter);
|
||||||
|
|
||||||
@@ -1255,12 +1280,12 @@ public class ResampleOp implements BufferedImageOp/* TODO: RasterOp */ {
|
|||||||
/*
|
/*
|
||||||
* image rescaling routine
|
* image rescaling routine
|
||||||
*/
|
*/
|
||||||
static class Contributor {
|
class Contributor {
|
||||||
int pixel;
|
int pixel;
|
||||||
double weight;
|
double weight;
|
||||||
}
|
}
|
||||||
|
|
||||||
static class ContributorList {
|
class ContributorList {
|
||||||
int n;/* number of contributors (may be < p.length) */
|
int n;/* number of contributors (may be < p.length) */
|
||||||
Contributor[] p;/* pointer to list of contributions */
|
Contributor[] p;/* pointer to list of contributions */
|
||||||
}
|
}
|
||||||
|
|||||||
+26
-24
@@ -31,7 +31,9 @@
|
|||||||
package com.twelvemonkeys.image;
|
package com.twelvemonkeys.image;
|
||||||
|
|
||||||
import static java.lang.Math.min;
|
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.color.ColorSpace;
|
||||||
import java.awt.geom.AffineTransform;
|
import java.awt.geom.AffineTransform;
|
||||||
@@ -47,7 +49,7 @@ import java.util.List;
|
|||||||
|
|
||||||
import javax.imageio.ImageTypeSpecifier;
|
import javax.imageio.ImageTypeSpecifier;
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* AffineTransformOpTest.
|
* AffineTransformOpTest.
|
||||||
@@ -144,12 +146,12 @@ public class AffineTransformOpTest {
|
|||||||
BufferedImage jreResult = jreOp.filter(image, null);
|
BufferedImage jreResult = jreOp.filter(image, null);
|
||||||
BufferedImage tmResult = tmOp.filter(image, null);
|
BufferedImage tmResult = tmOp.filter(image, null);
|
||||||
|
|
||||||
assertNotNull(tmResult, "No result!");
|
assertNotNull("No result!", tmResult);
|
||||||
assertEquals(jreResult.getType(), tmResult.getType(), "Bad type");
|
assertEquals("Bad type", jreResult.getType(), tmResult.getType());
|
||||||
assertEquals(jreResult.getColorModel(), tmResult.getColorModel(), "Incorrect color model");
|
assertEquals("Incorrect color model", jreResult.getColorModel(), tmResult.getColorModel());
|
||||||
|
|
||||||
assertEquals(jreResult.getWidth(), tmResult.getWidth(), "Incorrect width");
|
assertEquals("Incorrect width", jreResult.getWidth(), tmResult.getWidth());
|
||||||
assertEquals(jreResult.getHeight(), tmResult.getHeight(), "Incorrect height");
|
assertEquals("Incorrect height", jreResult.getHeight(), tmResult.getHeight());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -162,7 +164,7 @@ public class AffineTransformOpTest {
|
|||||||
BufferedImage image = spec.createBufferedImage(width, height);
|
BufferedImage image = spec.createBufferedImage(width, height);
|
||||||
|
|
||||||
BufferedImage tmResult = tmOp.filter(image, null);
|
BufferedImage tmResult = tmOp.filter(image, null);
|
||||||
assertNotNull(tmResult, "No result!");
|
assertNotNull("No result!", tmResult);
|
||||||
|
|
||||||
BufferedImage jreResult = null;
|
BufferedImage jreResult = null;
|
||||||
|
|
||||||
@@ -174,18 +176,18 @@ public class AffineTransformOpTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (jreResult != null) {
|
if (jreResult != null) {
|
||||||
assertEquals(jreResult.getType(), tmResult.getType(), "Bad type");
|
assertEquals("Bad type", jreResult.getType(), tmResult.getType());
|
||||||
assertEquals(jreResult.getColorModel(), tmResult.getColorModel(), "Incorrect color model");
|
assertEquals("Incorrect color model", jreResult.getColorModel(), tmResult.getColorModel());
|
||||||
|
|
||||||
assertEquals(jreResult.getWidth(), tmResult.getWidth(), "Incorrect width");
|
assertEquals("Incorrect width", jreResult.getWidth(), tmResult.getWidth());
|
||||||
assertEquals(jreResult.getHeight(), tmResult.getHeight(), "Incorrect height");
|
assertEquals("Incorrect height", jreResult.getHeight(), tmResult.getHeight());
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
assertEquals(spec.getBufferedImageType(), tmResult.getType(), "Bad type");
|
assertEquals("Bad type", spec.getBufferedImageType(), tmResult.getType());
|
||||||
assertEquals(spec.getColorModel(), tmResult.getColorModel(), "Incorrect color model");
|
assertEquals("Incorrect color model", spec.getColorModel(), tmResult.getColorModel());
|
||||||
|
|
||||||
assertEquals(height, tmResult.getWidth(), "Incorrect width");
|
assertEquals("Incorrect width", height, tmResult.getWidth());
|
||||||
assertEquals(width, tmResult.getHeight(), "Incorrect height");
|
assertEquals("Incorrect height", width, tmResult.getHeight());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -234,12 +236,12 @@ public class AffineTransformOpTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (jreResult != null) {
|
if (jreResult != null) {
|
||||||
assertEquals(jreResult.getWidth(), tmResult.getWidth(), "Incorrect width");
|
assertEquals("Incorrect width", jreResult.getWidth(), tmResult.getWidth());
|
||||||
assertEquals(jreResult.getHeight(), tmResult.getHeight(), "Incorrect height");
|
assertEquals("Incorrect height", jreResult.getHeight(), tmResult.getHeight());
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
assertEquals(height, tmResult.getWidth(), "Incorrect width");
|
assertEquals("Incorrect width", height, tmResult.getWidth());
|
||||||
assertEquals(width, tmResult.getHeight(), "Incorrect height");
|
assertEquals("Incorrect height", width, tmResult.getHeight());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -275,12 +277,12 @@ public class AffineTransformOpTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (jreResult != null) {
|
if (jreResult != null) {
|
||||||
assertEquals(jreResult.getWidth(), tmResult.getWidth(), "Incorrect width");
|
assertEquals("Incorrect width", jreResult.getWidth(), tmResult.getWidth());
|
||||||
assertEquals(jreResult.getHeight(), tmResult.getHeight(), "Incorrect height");
|
assertEquals("Incorrect height", jreResult.getHeight(), tmResult.getHeight());
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
assertEquals(height, tmResult.getWidth(), "Incorrect width");
|
assertEquals("Incorrect width", height, tmResult.getWidth());
|
||||||
assertEquals(width, tmResult.getHeight(), "Incorrect height");
|
assertEquals("Incorrect height", width, tmResult.getHeight());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+42
-48
@@ -30,16 +30,18 @@
|
|||||||
|
|
||||||
package com.twelvemonkeys.image;
|
package com.twelvemonkeys.image;
|
||||||
|
|
||||||
import org.junit.jupiter.api.Disabled;
|
import org.junit.Ignore;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.awt.color.*;
|
import java.awt.color.ColorSpace;
|
||||||
import java.awt.image.*;
|
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.net.URL;
|
||||||
import java.time.Duration;
|
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.*;
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* BufferedImageFactoryTestCase
|
* 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$
|
* @version $Id: BufferedImageFactoryTestCase.java,v 1.0 May 7, 2010 12:40:08 PM haraldk Exp$
|
||||||
*/
|
*/
|
||||||
public class BufferedImageFactoryTest {
|
public class BufferedImageFactoryTest {
|
||||||
@Test
|
@Test(expected = IllegalArgumentException.class)
|
||||||
public void testCreateNullImage() {
|
public void testCreateNullImage() {
|
||||||
assertThrows(IllegalArgumentException.class, () -> {
|
new BufferedImageFactory((Image) null);
|
||||||
new BufferedImageFactory((Image) null);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test(expected = IllegalArgumentException.class)
|
||||||
public void testCreateNullProducer() {
|
public void testCreateNullProducer() {
|
||||||
assertThrows(IllegalArgumentException.class, () -> {
|
new BufferedImageFactory((ImageProducer) null);
|
||||||
new BufferedImageFactory((ImageProducer) null);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// NPE in Toolkit, ok
|
// NPE in Toolkit, ok
|
||||||
@Test
|
@Test(expected = RuntimeException.class)
|
||||||
public void testGetBufferedImageErrorSourceByteArray() {
|
public void testGetBufferedImageErrorSourceByteArray() {
|
||||||
assertThrows(RuntimeException.class, () -> {
|
Image source = Toolkit.getDefaultToolkit().createImage((byte[]) null);
|
||||||
Image source = Toolkit.getDefaultToolkit().createImage((byte[]) null);
|
|
||||||
new BufferedImageFactory(source);
|
new BufferedImageFactory(source);
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test(expected = IllegalArgumentException.class)
|
||||||
public void testGetBufferedImageErrorSourceImageProducer() {
|
public void testGetBufferedImageErrorSourceImageProducer() {
|
||||||
Image source = Toolkit.getDefaultToolkit().createImage((ImageProducer) null);
|
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...
|
// 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
|
// 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")
|
@Ignore("Bug in Toolkit")
|
||||||
@Test
|
@Test(timeout = 1000, expected = ImageConversionException.class)
|
||||||
public void testGetBufferedImageErrorSourceString() {
|
public void testGetBufferedImageErrorSourceString() {
|
||||||
assertTimeoutPreemptively(Duration.ofMillis(1000), () -> {
|
Image source = Toolkit.getDefaultToolkit().createImage((String) null);
|
||||||
Image source = Toolkit.getDefaultToolkit().createImage((String) null);
|
|
||||||
BufferedImageFactory factory = new BufferedImageFactory(source);
|
BufferedImageFactory factory = new BufferedImageFactory(source);
|
||||||
assertThrows(ImageConversionException.class, factory::getBufferedImage);
|
factory.getBufferedImage();
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is a little random, and it would be nicer if we could throw an IllegalArgumentException on create.
|
// 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...
|
// Unfortunately, the API doesn't allow this...
|
||||||
@Test
|
@Test(timeout = 1000, expected = ImageConversionException.class)
|
||||||
public void testGetBufferedImageErrorSourceURL() {
|
public void testGetBufferedImageErrorSourceURL() {
|
||||||
assertTimeoutPreemptively(Duration.ofMillis(1000), () -> {
|
Image source = Toolkit.getDefaultToolkit().createImage(getClass().getResource("/META-INF/MANIFEST.MF"));
|
||||||
Image source = Toolkit.getDefaultToolkit().createImage((String) null);
|
|
||||||
BufferedImageFactory factory = new BufferedImageFactory(source);
|
BufferedImageFactory factory = new BufferedImageFactory(source);
|
||||||
assertThrows(ImageConversionException.class, factory::getBufferedImage);
|
factory.getBufferedImage();
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -172,7 +166,7 @@ public class BufferedImageFactoryTest {
|
|||||||
|
|
||||||
assertEquals(3, colorModel.getNumColorComponents());
|
assertEquals(3, colorModel.getNumColorComponents());
|
||||||
assertEquals(ColorSpace.getInstance(ColorSpace.CS_sRGB), colorModel.getColorSpace());
|
assertEquals(ColorSpace.getInstance(ColorSpace.CS_sRGB), colorModel.getColorSpace());
|
||||||
assertInstanceOf(IndexColorModel.class, colorModel);
|
assertTrue(colorModel instanceof IndexColorModel);
|
||||||
|
|
||||||
assertTrue(colorModel.hasAlpha());
|
assertTrue(colorModel.hasAlpha());
|
||||||
assertEquals(4, colorModel.getNumComponents());
|
assertEquals(4, colorModel.getNumComponents());
|
||||||
@@ -203,7 +197,7 @@ public class BufferedImageFactoryTest {
|
|||||||
|
|
||||||
for (int y = 0; y < image.getHeight(); y++) {
|
for (int y = 0; y < image.getHeight(); y++) {
|
||||||
for (int x = 0; x < image.getWidth(); x++) {
|
for (int x = 0; x < image.getWidth(); x++) {
|
||||||
assertEquals(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 y = 0; y < image.getHeight(); y++) {
|
||||||
for (int x = 0; x < image.getWidth(); x++) {
|
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 y = 0; y < image.getHeight(); y++) {
|
||||||
for (int x = 0; x < image.getWidth(); x++) {
|
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
|
// Listener should abort ASAP
|
||||||
factory.addProgressListener(new BufferedImageFactory.ProgressListener() {
|
factory.addProgressListener(new BufferedImageFactory.ProgressListener() {
|
||||||
public void progress(BufferedImageFactory factory, float percentage) {
|
public void progress(BufferedImageFactory pFactory, float pPercentage) {
|
||||||
if (percentage > 5) {
|
if (pPercentage > 5) {
|
||||||
factory.abort();
|
pFactory.abort();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -349,7 +343,7 @@ public class BufferedImageFactoryTest {
|
|||||||
VerifyingListener listener = new VerifyingListener(factory);
|
VerifyingListener listener = new VerifyingListener(factory);
|
||||||
factory.addProgressListener(listener);
|
factory.addProgressListener(listener);
|
||||||
factory.removeProgressListener(new BufferedImageFactory.ProgressListener() {
|
factory.removeProgressListener(new BufferedImageFactory.ProgressListener() {
|
||||||
public void progress(BufferedImageFactory factory, float percentage) {
|
public void progress(BufferedImageFactory pFactory, float pPercentage) {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
factory.getBufferedImage();
|
factory.getBufferedImage();
|
||||||
@@ -386,11 +380,11 @@ public class BufferedImageFactoryTest {
|
|||||||
this.factory = factory;
|
this.factory = factory;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void progress(BufferedImageFactory factory, float percentage) {
|
public void progress(BufferedImageFactory pFactory, float pPercentage) {
|
||||||
assertEquals(this.factory, factory);
|
assertEquals(factory, pFactory);
|
||||||
assertTrue(percentage >= progress && percentage <= 100f);
|
assertTrue(pPercentage >= progress && pPercentage <= 100f);
|
||||||
|
|
||||||
progress = percentage;
|
progress = pPercentage;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -30,7 +30,7 @@
|
|||||||
|
|
||||||
package com.twelvemonkeys.image;
|
package com.twelvemonkeys.image;
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import javax.imageio.ImageIO;
|
import javax.imageio.ImageIO;
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
@@ -39,7 +39,7 @@ import java.awt.image.IndexColorModel;
|
|||||||
import java.awt.image.RenderedImage;
|
import java.awt.image.RenderedImage;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.*;
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
public class ImageUtilTest {
|
public class ImageUtilTest {
|
||||||
|
|
||||||
@@ -116,8 +116,8 @@ public class ImageUtilTest {
|
|||||||
public void testImageIsNotBufferedImage() {
|
public void testImageIsNotBufferedImage() {
|
||||||
// Should not be a buffered image
|
// Should not be a buffered image
|
||||||
assertFalse(
|
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
|
if (original != notContrasted) { // Don't care to test if images are same
|
||||||
for (int y = 0; y < original.getHeight(); y++) {
|
for (int y = 0; y < original.getHeight(); y++) {
|
||||||
for (int x = 0; x < original.getWidth(); x++) {
|
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
|
// RED
|
||||||
if (oR < 127) {
|
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 {
|
else {
|
||||||
assertTrue(oR <= cR && cR <= dR, "Contrast should be increased or same");
|
assertTrue("Contrast should be increased or same", oR <= cR && cR <= dR);
|
||||||
}
|
}
|
||||||
// GREEN
|
// GREEN
|
||||||
if (oG < 127) {
|
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 {
|
else {
|
||||||
assertTrue(oG <= cG && cG <= dG, "Contrast should be increased or same");
|
assertTrue("Contrast should be increased or same", oG <= cG && cG <= dG);
|
||||||
}
|
}
|
||||||
// BLUE
|
// BLUE
|
||||||
if (oB < 127) {
|
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 {
|
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 r = rgb >> 16 & 0xFF;
|
||||||
int g = rgb >> 8 & 0xFF;
|
int g = rgb >> 8 & 0xFF;
|
||||||
int b = rgb & 0xFF;
|
int b = rgb & 0xFF;
|
||||||
assertTrue(r == 0 || r == 255, "Max contrast should only produce primary colors");
|
assertTrue("Max contrast should only produce primary colors", r == 0 || r == 255);
|
||||||
assertTrue(g == 0 || g == 255, "Max contrast should only produce primary colors");
|
assertTrue("Max contrast should only produce primary colors", g == 0 || g == 255);
|
||||||
assertTrue(b == 0 || b == 255, "Max contrast should only produce primary colors");
|
assertTrue("Max contrast should only produce primary colors", b == 0 || b == 255);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -327,24 +327,24 @@ public class ImageUtilTest {
|
|||||||
|
|
||||||
// RED
|
// RED
|
||||||
if (oR >= 127) {
|
if (oR >= 127) {
|
||||||
assertTrue(oR >= cR, "Contrast should be decreased or same");
|
assertTrue("Contrast should be decreased or same", oR >= cR);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
assertTrue(oR <= cR, "Contrast should be increased or same");
|
assertTrue("Contrast should be increased or same", oR <= cR);
|
||||||
}
|
}
|
||||||
// GREEN
|
// GREEN
|
||||||
if (oG >= 127) {
|
if (oG >= 127) {
|
||||||
assertTrue(oG >= cG, "Contrast should be decreased or same");
|
assertTrue("Contrast should be decreased or same", oG >= cG);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
assertTrue(oG <= cG, "Contrast should be increased or same");
|
assertTrue("Contrast should be increased or same", oG <= cG);
|
||||||
}
|
}
|
||||||
// BLUE
|
// BLUE
|
||||||
if (oB >= 127) {
|
if (oB >= 127) {
|
||||||
assertTrue(oB >= cB, "Contrast should be decreased or same");
|
assertTrue("Contrast should be decreased or same", oB >= cB);
|
||||||
}
|
}
|
||||||
else {
|
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 r = rgb >> 16 & 0xFF;
|
||||||
int g = rgb >> 8 & 0xFF;
|
int g = rgb >> 8 & 0xFF;
|
||||||
int b = rgb & 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
|
if (original != notSharpened) { // Don't care to test if images are same
|
||||||
for (int y = 0; y < original.getHeight(); y++) {
|
for (int y = 0; y < original.getHeight(); y++) {
|
||||||
for (int x = 0; x < original.getWidth(); x++) {
|
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);
|
// 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);
|
// 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);
|
// 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);
|
// assertEquals("Difference should not change", diffSharpened, diffMore);
|
||||||
assertTrue(absDiffSharpened < absDiffMore, "Abs difference should increase");
|
assertTrue("Abs difference should increase", absDiffSharpened < absDiffMore);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -466,7 +466,7 @@ public class ImageUtilTest {
|
|||||||
if (original != notBlurred) { // Don't care to test if images are same
|
if (original != notBlurred) { // Don't care to test if images are same
|
||||||
for (int y = 0; y < original.getHeight(); y++) {
|
for (int y = 0; y < original.getHeight(); y++) {
|
||||||
for (int x = 0; x < original.getWidth(); x++) {
|
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);
|
// 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);
|
// 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);
|
// 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);
|
// assertEquals("Difference should not change", diffBlurred, diffMore);
|
||||||
assertTrue(absDiffBlurred > absDiffMore, "Abs difference should decrease");
|
assertTrue("Abs difference should decrease", absDiffBlurred > absDiffMore);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -528,7 +528,7 @@ public class ImageUtilTest {
|
|||||||
assertNotNull(sunflower);
|
assertNotNull(sunflower);
|
||||||
|
|
||||||
BufferedImage image = ImageUtil.createIndexed(sunflower);
|
BufferedImage image = ImageUtil.createIndexed(sunflower);
|
||||||
assertNotNull(image, "Image was null");
|
assertNotNull("Image was null", image);
|
||||||
assertInstanceOf(IndexColorModel.class, image.getColorModel());
|
assertTrue(image.getColorModel() instanceof IndexColorModel);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,8 +30,8 @@
|
|||||||
|
|
||||||
package com.twelvemonkeys.image;
|
package com.twelvemonkeys.image;
|
||||||
|
|
||||||
import org.junit.jupiter.api.Disabled;
|
import org.junit.Ignore;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.awt.image.BufferedImage;
|
import java.awt.image.BufferedImage;
|
||||||
@@ -40,7 +40,7 @@ import java.util.ArrayList;
|
|||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.*;
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ResampleOpTestCase
|
* 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
|
// 1x1
|
||||||
@@ -358,7 +358,7 @@ public class ResampleOpTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Disabled("Not for general unit testing")
|
@Ignore("Not for general unit testing")
|
||||||
@Test
|
@Test
|
||||||
public void testTime() {
|
public void testTime() {
|
||||||
int iterations = 1000;
|
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>
|
<parent>
|
||||||
<groupId>com.twelvemonkeys.common</groupId>
|
<groupId>com.twelvemonkeys.common</groupId>
|
||||||
<artifactId>common</artifactId>
|
<artifactId>common</artifactId>
|
||||||
<version>3.12.1-SNAPSHOT</version>
|
<version>3.7.1</version>
|
||||||
</parent>
|
</parent>
|
||||||
<artifactId>common-io</artifactId>
|
<artifactId>common-io</artifactId>
|
||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
<name>TwelveMonkeys :: Common :: IO</name>
|
<name>TwelveMonkeys :: Common :: IO</name>
|
||||||
<description>
|
<description>
|
||||||
TwelveMonkeys Common I/O support classes.
|
The TwelveMonkeys Common IO support
|
||||||
</description>
|
</description>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
@@ -31,12 +31,4 @@
|
|||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
|
||||||
<plugins>
|
|
||||||
<plugin>
|
|
||||||
<groupId>org.apache.felix</groupId>
|
|
||||||
<artifactId>maven-bundle-plugin</artifactId>
|
|
||||||
</plugin>
|
|
||||||
</plugins>
|
|
||||||
</build>
|
|
||||||
</project>
|
</project>
|
||||||
|
|||||||
@@ -56,8 +56,8 @@ public class CompoundReader extends Reader {
|
|||||||
|
|
||||||
private int currentReader;
|
private int currentReader;
|
||||||
private int markedReader;
|
private int markedReader;
|
||||||
private long mark;
|
private int mark;
|
||||||
private long next;
|
private int mNext;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new compound reader.
|
* 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
|
finalLock = pReaders; // NOTE: It's ok to sync on pReaders, as the
|
||||||
// reference can't change, only it's elements
|
// reference can't change, only it's elements
|
||||||
|
|
||||||
readers = new ArrayList<>();
|
readers = new ArrayList<Reader>();
|
||||||
|
|
||||||
boolean markSupported = true;
|
boolean markSupported = true;
|
||||||
while (pReaders.hasNext()) {
|
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!
|
// NOTE: Reset mNext for every reader, and record marked reader in mark/reset methods!
|
||||||
next = 0;
|
mNext = 0;
|
||||||
return current;
|
return current;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -135,7 +135,7 @@ public class CompoundReader extends Reader {
|
|||||||
|
|
||||||
synchronized (finalLock) {
|
synchronized (finalLock) {
|
||||||
ensureOpen();
|
ensureOpen();
|
||||||
mark = next;
|
mark = mNext;
|
||||||
markedReader = currentReader;
|
markedReader = currentReader;
|
||||||
|
|
||||||
current.mark(pReadLimit);
|
current.mark(pReadLimit);
|
||||||
@@ -158,7 +158,7 @@ public class CompoundReader extends Reader {
|
|||||||
}
|
}
|
||||||
current.reset();
|
current.reset();
|
||||||
|
|
||||||
next = mark;
|
mNext = mark;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -177,13 +177,13 @@ public class CompoundReader extends Reader {
|
|||||||
return read(); // In case of 0-length readers
|
return read(); // In case of 0-length readers
|
||||||
}
|
}
|
||||||
|
|
||||||
next++;
|
mNext++;
|
||||||
|
|
||||||
return read;
|
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) {
|
synchronized (finalLock) {
|
||||||
int read = current.read(pBuffer, pOffset, pLength);
|
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
|
return read(pBuffer, pOffset, pLength); // In case of 0-length readers
|
||||||
}
|
}
|
||||||
|
|
||||||
next += read;
|
mNext += read;
|
||||||
|
|
||||||
return read;
|
return read;
|
||||||
}
|
}
|
||||||
@@ -213,7 +213,7 @@ public class CompoundReader extends Reader {
|
|||||||
return skip(pChars); // In case of 0-length readers
|
return skip(pChars); // In case of 0-length readers
|
||||||
}
|
}
|
||||||
|
|
||||||
next += skipped;
|
mNext += skipped;
|
||||||
|
|
||||||
return skipped;
|
return skipped;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,7 +34,6 @@ import java.io.ByteArrayInputStream;
|
|||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.util.Arrays;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An unsynchronized {@code ByteArrayOutputStream} implementation. This version
|
* An unsynchronized {@code ByteArrayOutputStream} implementation. This version
|
||||||
@@ -43,8 +42,11 @@ import java.util.Arrays;
|
|||||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||||
* @version $Id: FastByteArrayOutputStream.java#2 $
|
* @version $Id: FastByteArrayOutputStream.java#2 $
|
||||||
*/
|
*/
|
||||||
// TODO: Performance test of a stream impl that uses list of fixed size blocks, rather than contiguous block
|
// TODO: Performance test of a stream impl that uses list of fixed size blocks, rather than contiguous block
|
||||||
public final class FastByteArrayOutputStream extends ByteArrayOutputStream {
|
public final class FastByteArrayOutputStream extends ByteArrayOutputStream {
|
||||||
|
/** Max grow size (unless if writing more than this amount of bytes) */
|
||||||
|
protected int maxGrowSize = 1024 * 1024; // 1 MB
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a {@code ByteArrayOutputStream} with the given initial buffer
|
* Creates a {@code ByteArrayOutputStream} with the given initial buffer
|
||||||
* size.
|
* size.
|
||||||
@@ -95,8 +97,10 @@ public final class FastByteArrayOutputStream extends ByteArrayOutputStream {
|
|||||||
|
|
||||||
private void growIfNeeded(int pNewCount) {
|
private void growIfNeeded(int pNewCount) {
|
||||||
if (pNewCount > buf.length) {
|
if (pNewCount > buf.length) {
|
||||||
int newSize = Math.max(buf.length << 1, pNewCount);
|
int newSize = Math.max(Math.min(buf.length << 1, buf.length + maxGrowSize), pNewCount);
|
||||||
buf = Arrays.copyOf(buf, newSize);
|
byte[] newBuf = new byte[newSize];
|
||||||
|
System.arraycopy(buf, 0, newBuf, 0, count);
|
||||||
|
buf = newBuf;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -109,7 +113,10 @@ public final class FastByteArrayOutputStream extends ByteArrayOutputStream {
|
|||||||
// Non-synchronized version of toByteArray
|
// Non-synchronized version of toByteArray
|
||||||
@Override
|
@Override
|
||||||
public byte[] toByteArray() {
|
public byte[] toByteArray() {
|
||||||
return Arrays.copyOf(buf, count);
|
byte[] newBuf = new byte[count];
|
||||||
|
System.arraycopy(buf, 0, newBuf, 0, count);
|
||||||
|
|
||||||
|
return newBuf;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -50,8 +50,8 @@ public class StringArrayReader extends StringReader {
|
|||||||
protected final Object finalLock;
|
protected final Object finalLock;
|
||||||
private int currentSting;
|
private int currentSting;
|
||||||
private int markedString;
|
private int markedString;
|
||||||
private long mark;
|
private int mark;
|
||||||
private long next;
|
private int next;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new string array reader.
|
* 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) {
|
synchronized (finalLock) {
|
||||||
int read = current.read(pBuffer, pOffset, pLength);
|
int read = current.read(pBuffer, pOffset, pLength);
|
||||||
|
|
||||||
|
|||||||
@@ -41,20 +41,21 @@ import java.io.InputStream;
|
|||||||
* underlying stream.
|
* underlying stream.
|
||||||
*
|
*
|
||||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||||
|
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-core/src/main/java/com/twelvemonkeys/io/SubStream.java#2 $
|
||||||
*/
|
*/
|
||||||
public final class SubStream extends FilterInputStream {
|
public final class SubStream extends FilterInputStream {
|
||||||
private long bytesLeft;
|
private long bytesLeft;
|
||||||
private int markLimit;
|
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 pStream the underlying input stream
|
||||||
* @param length maximum number of bytes to read from this stream
|
* @param pLength maximum number of bytes to read drom this stream
|
||||||
*/
|
*/
|
||||||
public SubStream(final InputStream stream, final long length) {
|
public SubStream(final InputStream pStream, final long pLength) {
|
||||||
super(Validate.notNull(stream, "stream"));
|
super(Validate.notNull(pStream, "stream"));
|
||||||
bytesLeft = Validate.isTrue(length >= 0, length, "length < 0: %s");
|
bytesLeft = pLength;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -63,23 +64,22 @@ public final class SubStream extends FilterInputStream {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void close() throws IOException {
|
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) {
|
while (bytesLeft > 0) {
|
||||||
if (skip(bytesLeft) <= 0 && read() < 0) {
|
//noinspection ResultOfMethodCallIgnored
|
||||||
break;
|
skip(bytesLeft);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int available() throws IOException {
|
public int available() throws IOException {
|
||||||
return (int) findMaxLen(super.available());
|
return (int) Math.min(super.available(), bytesLeft);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void mark(int readLimit) {
|
public void mark(int pReadLimit) {
|
||||||
super.mark(readLimit);// This either succeeds or does nothing...
|
super.mark(pReadLimit);// This either succeeds or does nothing...
|
||||||
markLimit = readLimit;
|
markLimit = pReadLimit;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -93,42 +93,44 @@ public final class SubStream extends FilterInputStream {
|
|||||||
if (bytesLeft-- <= 0) {
|
if (bytesLeft-- <= 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return super.read();
|
return super.read();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int read(byte[] bytes) throws IOException {
|
public final int read(byte[] pBytes) throws IOException {
|
||||||
return read(bytes, 0, bytes.length);
|
return read(pBytes, 0, pBytes.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@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) {
|
if (bytesLeft <= 0) {
|
||||||
return -1;
|
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;
|
bytesLeft = read < 0 ? 0 : bytesLeft - read;
|
||||||
|
|
||||||
return 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.
|
* 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
|
* @return the maximum number of bytes to read
|
||||||
*/
|
*/
|
||||||
private long findMaxLen(long length) {
|
private long findMaxLen(long pLength) {
|
||||||
return bytesLeft < length ? Math.max(bytesLeft, 0) : length;
|
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,39 +45,39 @@ import java.nio.ByteBuffer;
|
|||||||
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-core/src/main/java/com/twelvemonkeys/io/enc/DecoderStream.java#2 $
|
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-core/src/main/java/com/twelvemonkeys/io/enc/DecoderStream.java#2 $
|
||||||
*/
|
*/
|
||||||
public final class DecoderStream extends FilterInputStream {
|
public final class DecoderStream extends FilterInputStream {
|
||||||
private final ByteBuffer buffer;
|
protected final ByteBuffer buffer;
|
||||||
private final Decoder decoder;
|
protected final Decoder decoder;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new decoder stream and chains it to the
|
* Creates a new decoder stream and chains it to the
|
||||||
* input stream specified by the {@code stream} argument.
|
* input stream specified by the {@code pStream} argument.
|
||||||
* The stream will use a default decode buffer size.
|
* The stream will use a default decode buffer size.
|
||||||
*
|
*
|
||||||
* @param stream the underlying input stream.
|
* @param pStream the underlying input stream.
|
||||||
* @param decoder the decoder that will be used to decode the underlying stream
|
* @param pDecoder the decoder that will be used to decode the underlying stream
|
||||||
*
|
*
|
||||||
* @see java.io.FilterInputStream#in
|
* @see java.io.FilterInputStream#in
|
||||||
*/
|
*/
|
||||||
public DecoderStream(final InputStream stream, final Decoder decoder) {
|
public DecoderStream(final InputStream pStream, final Decoder pDecoder) {
|
||||||
// TODO: Let the decoder decide preferred buffer size
|
// TODO: Let the decoder decide preferred buffer size
|
||||||
this(stream, decoder, 1024);
|
this(pStream, pDecoder, 1024);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new decoder stream and chains it to the
|
* Creates a new decoder stream and chains it to the
|
||||||
* input stream specified by the {@code stream} argument.
|
* input stream specified by the {@code pStream} argument.
|
||||||
*
|
*
|
||||||
* @param stream the underlying input stream.
|
* @param pStream the underlying input stream.
|
||||||
* @param decoder the decoder that will be used to decode the underlying stream
|
* @param pDecoder the decoder that will be used to decode the underlying stream
|
||||||
* @param bufferSize the size of the decode buffer
|
* @param pBufferSize the size of the decode buffer
|
||||||
*
|
*
|
||||||
* @see java.io.FilterInputStream#in
|
* @see java.io.FilterInputStream#in
|
||||||
*/
|
*/
|
||||||
public DecoderStream(final InputStream stream, final Decoder decoder, final int bufferSize) {
|
public DecoderStream(final InputStream pStream, final Decoder pDecoder, final int pBufferSize) {
|
||||||
super(stream);
|
super(pStream);
|
||||||
|
|
||||||
this.decoder = decoder;
|
decoder = pDecoder;
|
||||||
buffer = ByteBuffer.allocate(bufferSize); // TODO: Allow decoder to specify minimum buffer size
|
buffer = ByteBuffer.allocate(pBufferSize);
|
||||||
buffer.flip();
|
buffer.flip();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -95,15 +95,15 @@ public final class DecoderStream extends FilterInputStream {
|
|||||||
return buffer.get() & 0xff;
|
return buffer.get() & 0xff;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int read(final byte[] bytes, final int offset, final int length) throws IOException {
|
public int read(final byte pBytes[], final int pOffset, final int pLength) throws IOException {
|
||||||
if (bytes == null) {
|
if (pBytes == null) {
|
||||||
throw new NullPointerException();
|
throw new NullPointerException();
|
||||||
}
|
}
|
||||||
else if ((offset < 0) || (offset > bytes.length) || (length < 0) ||
|
else if ((pOffset < 0) || (pOffset > pBytes.length) || (pLength < 0) ||
|
||||||
((offset + length) > bytes.length) || ((offset + length) < 0)) {
|
((pOffset + pLength) > pBytes.length) || ((pOffset + pLength) < 0)) {
|
||||||
throw new IndexOutOfBoundsException("bytes.length=" + bytes.length + " offset=" + offset + " length=" + length);
|
throw new IndexOutOfBoundsException("bytes.length=" + pBytes.length + " offset=" + pOffset + " length=" + pLength);
|
||||||
}
|
}
|
||||||
else if (length == 0) {
|
else if (pLength == 0) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -114,11 +114,11 @@ public final class DecoderStream extends FilterInputStream {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read until we have read length bytes, or have reached EOF
|
// Read until we have read pLength bytes, or have reached EOF
|
||||||
int count = 0;
|
int count = 0;
|
||||||
int off = offset;
|
int off = pOffset;
|
||||||
|
|
||||||
while (length > count) {
|
while (pLength > count) {
|
||||||
if (!buffer.hasRemaining()) {
|
if (!buffer.hasRemaining()) {
|
||||||
if (fill() < 0) {
|
if (fill() < 0) {
|
||||||
break;
|
break;
|
||||||
@@ -126,8 +126,8 @@ public final class DecoderStream extends FilterInputStream {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Copy as many bytes as possible
|
// Copy as many bytes as possible
|
||||||
int dstLen = Math.min(length - count, buffer.remaining());
|
int dstLen = Math.min(pLength - count, buffer.remaining());
|
||||||
buffer.get(bytes, off, dstLen);
|
buffer.get(pBytes, off, dstLen);
|
||||||
|
|
||||||
// Update offset (rest)
|
// Update offset (rest)
|
||||||
off += dstLen;
|
off += dstLen;
|
||||||
@@ -139,7 +139,7 @@ public final class DecoderStream extends FilterInputStream {
|
|||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
public long skip(final long length) throws IOException {
|
public long skip(final long pLength) throws IOException {
|
||||||
// End of file?
|
// End of file?
|
||||||
if (!buffer.hasRemaining()) {
|
if (!buffer.hasRemaining()) {
|
||||||
if (fill() < 0) {
|
if (fill() < 0) {
|
||||||
@@ -147,10 +147,10 @@ public final class DecoderStream extends FilterInputStream {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Skip until we have skipped length bytes, or have reached EOF
|
// Skip until we have skipped pLength bytes, or have reached EOF
|
||||||
long total = 0;
|
long total = 0;
|
||||||
|
|
||||||
while (total < length) {
|
while (total < pLength) {
|
||||||
if (!buffer.hasRemaining()) {
|
if (!buffer.hasRemaining()) {
|
||||||
if (fill() < 0) {
|
if (fill() < 0) {
|
||||||
break;
|
break;
|
||||||
@@ -158,7 +158,7 @@ public final class DecoderStream extends FilterInputStream {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NOTE: Skipped can never be more than avail, which is an int, so the cast is safe
|
// NOTE: Skipped can never be more than avail, which is an int, so the cast is safe
|
||||||
int skipped = (int) Math.min(length - total, buffer.remaining());
|
int skipped = (int) Math.min(pLength - total, buffer.remaining());
|
||||||
buffer.position(buffer.position() + skipped);
|
buffer.position(buffer.position() + skipped);
|
||||||
total += skipped;
|
total += skipped;
|
||||||
}
|
}
|
||||||
@@ -174,7 +174,7 @@ public final class DecoderStream extends FilterInputStream {
|
|||||||
*
|
*
|
||||||
* @throws IOException if an I/O error occurs
|
* @throws IOException if an I/O error occurs
|
||||||
*/
|
*/
|
||||||
private int fill() throws IOException {
|
protected int fill() throws IOException {
|
||||||
buffer.clear();
|
buffer.clear();
|
||||||
int read = decoder.decode(in, buffer);
|
int read = decoder.decode(in, buffer);
|
||||||
|
|
||||||
|
|||||||
@@ -45,39 +45,41 @@ import java.nio.ByteBuffer;
|
|||||||
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-core/src/main/java/com/twelvemonkeys/io/enc/EncoderStream.java#2 $
|
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-core/src/main/java/com/twelvemonkeys/io/enc/EncoderStream.java#2 $
|
||||||
*/
|
*/
|
||||||
public final class EncoderStream extends FilterOutputStream {
|
public final class EncoderStream extends FilterOutputStream {
|
||||||
|
// TODO: This class need a test case ASAP!!!
|
||||||
|
|
||||||
private final Encoder encoder;
|
protected final Encoder encoder;
|
||||||
private final boolean flushOnWrite;
|
private final boolean flushOnWrite;
|
||||||
|
|
||||||
private final ByteBuffer buffer;
|
protected final ByteBuffer buffer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates an output stream filter built on top of the specified
|
* Creates an output stream filter built on top of the specified
|
||||||
* underlying output stream.
|
* underlying output stream.
|
||||||
*
|
*
|
||||||
* @param stream the underlying output stream
|
* @param pStream the underlying output stream
|
||||||
* @param encoder the encoder to use
|
* @param pEncoder the encoder to use
|
||||||
*/
|
*/
|
||||||
public EncoderStream(final OutputStream stream, final Encoder encoder) {
|
public EncoderStream(final OutputStream pStream, final Encoder pEncoder) {
|
||||||
this(stream, encoder, false);
|
this(pStream, pEncoder, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates an output stream filter built on top of the specified
|
* Creates an output stream filter built on top of the specified
|
||||||
* underlying output stream.
|
* underlying output stream.
|
||||||
*
|
*
|
||||||
* @param stream the underlying output stream
|
* @param pStream the underlying output stream
|
||||||
* @param encoder the encoder to use
|
* @param pEncoder the encoder to use
|
||||||
* @param flushOnWrite if {@code true}, calls to the byte-array
|
* @param pFlushOnWrite if {@code true}, calls to the byte-array
|
||||||
* {@code write} methods will automatically flush the buffer.
|
* {@code write} methods will automatically flush the buffer.
|
||||||
*/
|
*/
|
||||||
public EncoderStream(final OutputStream stream, final Encoder encoder, final boolean flushOnWrite) {
|
public EncoderStream(final OutputStream pStream, final Encoder pEncoder, final boolean pFlushOnWrite) {
|
||||||
super(stream);
|
super(pStream);
|
||||||
|
|
||||||
this.encoder = encoder;
|
encoder = pEncoder;
|
||||||
this.flushOnWrite = flushOnWrite;
|
flushOnWrite = pFlushOnWrite;
|
||||||
|
|
||||||
buffer = ByteBuffer.allocate(1024);
|
buffer = ByteBuffer.allocate(1024);
|
||||||
|
buffer.flip();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void close() throws IOException {
|
public void close() throws IOException {
|
||||||
@@ -102,33 +104,33 @@ public final class EncoderStream extends FilterOutputStream {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void write(final byte[] bytes) throws IOException {
|
public final void write(final byte[] pBytes) throws IOException {
|
||||||
write(bytes, 0, bytes.length);
|
write(pBytes, 0, pBytes.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Verify that this works for the general case (it probably won't)...
|
// TODO: Verify that this works for the general case (it probably won't)...
|
||||||
// TODO: We might need a way to explicitly flush the encoder, or specify
|
// TODO: We might need a way to explicitly flush the encoder, or specify
|
||||||
// that the encoder can't buffer. In that case, the encoder should probably
|
// that the encoder can't buffer. In that case, the encoder should probably
|
||||||
// tell the EncoderStream how large buffer it prefers...
|
// tell the EncoderStream how large buffer it prefers...
|
||||||
public void write(final byte[] values, final int offset, final int length) throws IOException {
|
public void write(final byte[] pBytes, final int pOffset, final int pLength) throws IOException {
|
||||||
if (!flushOnWrite && length < buffer.remaining()) {
|
if (!flushOnWrite && pLength < buffer.remaining()) {
|
||||||
// Buffer data
|
// Buffer data
|
||||||
buffer.put(values, offset, length);
|
buffer.put(pBytes, pOffset, pLength);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// Encode data already in the buffer
|
// Encode data already in the buffer
|
||||||
encodeBuffer();
|
encodeBuffer();
|
||||||
|
|
||||||
// Encode rest without buffering
|
// Encode rest without buffering
|
||||||
encoder.encode(out, ByteBuffer.wrap(values, offset, length));
|
encoder.encode(out, ByteBuffer.wrap(pBytes, pOffset, pLength));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void write(final int value) throws IOException {
|
public void write(final int pByte) throws IOException {
|
||||||
if (!buffer.hasRemaining()) {
|
if (!buffer.hasRemaining()) {
|
||||||
encodeBuffer(); // Resets bufferPos to 0
|
encodeBuffer(); // Resets bufferPos to 0
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer.put((byte) value);
|
buffer.put((byte) pByte);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ package com.twelvemonkeys.io;
|
|||||||
|
|
||||||
import com.twelvemonkeys.lang.StringUtil;
|
import com.twelvemonkeys.lang.StringUtil;
|
||||||
import com.twelvemonkeys.util.CollectionUtil;
|
import com.twelvemonkeys.util.CollectionUtil;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.Reader;
|
import java.io.Reader;
|
||||||
@@ -39,8 +40,7 @@ import java.io.StringReader;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
import static org.junit.Assert.*;
|
||||||
import static org.junit.jupiter.api.Assertions.*;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* CompoundReaderTestCase
|
* CompoundReaderTestCase
|
||||||
|
|||||||
+3
-2
@@ -30,11 +30,12 @@
|
|||||||
|
|
||||||
package com.twelvemonkeys.io;
|
package com.twelvemonkeys.io;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
import static org.junit.Assert.assertEquals;
|
||||||
import static org.junit.jupiter.api.Assertions.*;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* FastByteArrayOutputStreamTestCase
|
* FastByteArrayOutputStreamTestCase
|
||||||
|
|||||||
@@ -30,10 +30,11 @@
|
|||||||
|
|
||||||
package com.twelvemonkeys.io;
|
package com.twelvemonkeys.io;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
import static org.junit.Assert.*;
|
||||||
import static org.junit.jupiter.api.Assertions.*;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* MemoryCacheSeekableStreamTestCase
|
* MemoryCacheSeekableStreamTestCase
|
||||||
@@ -91,13 +92,13 @@ public class FileSeekableStreamTest extends SeekableInputStreamAbstractTest {
|
|||||||
try {
|
try {
|
||||||
FileUtil.read(stream); // Read until EOF
|
FileUtil.read(stream); // Read until EOF
|
||||||
|
|
||||||
assertEquals(-1, stream.read(), "EOF not reached (test case broken)");
|
assertEquals("EOF not reached (test case broken)", -1, stream.read());
|
||||||
assertFalse(closed[0], "Underlying stream closed before close");
|
assertFalse("Underlying stream closed before close", closed[0]);
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
stream.close();
|
stream.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
assertTrue(closed[0], "Underlying stream not closed");
|
assertTrue("Underlying stream not closed", closed[0]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,14 +46,14 @@
|
|||||||
package com.twelvemonkeys.io;
|
package com.twelvemonkeys.io;
|
||||||
|
|
||||||
import com.twelvemonkeys.lang.ObjectAbstractTest;
|
import com.twelvemonkeys.lang.ObjectAbstractTest;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
import static org.junit.Assert.*;
|
||||||
import static org.junit.jupiter.api.Assertions.*;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* InputStreamAbstractTestCase
|
* InputStreamAbstractTestCase
|
||||||
@@ -104,15 +104,15 @@ public abstract class InputStreamAbstractTest extends ObjectAbstractTest {
|
|||||||
int size = 5;
|
int size = 5;
|
||||||
InputStream input = makeInputStream(makeOrderedArray(size));
|
InputStream input = makeInputStream(makeOrderedArray(size));
|
||||||
for (int i = 0; i < size; i++) {
|
for (int i = 0; i < size; i++) {
|
||||||
assertTrue((size - i) >= input.available(), "Check Size [" + i + "]");
|
assertTrue("Check Size [" + i + "]", (size - i) >= input.available());
|
||||||
assertEquals(i, input.read(), "Check Value [" + i + "]");
|
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
|
// Test reading after the end of file
|
||||||
try {
|
try {
|
||||||
int result = input.read();
|
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) {
|
catch (IOException e) {
|
||||||
fail("Should not have thrown an IOException: " + e.getMessage());
|
fail("Should not have thrown an IOException: " + e.getMessage());
|
||||||
@@ -122,12 +122,12 @@ public abstract class InputStreamAbstractTest extends ObjectAbstractTest {
|
|||||||
@Test
|
@Test
|
||||||
public void testAvailable() throws Exception {
|
public void testAvailable() throws Exception {
|
||||||
InputStream input = makeInputStream(1);
|
InputStream input = makeInputStream(1);
|
||||||
assertFalse(input.read() < 0, "Unexpected EOF");
|
assertFalse("Unexpected EOF", input.read() < 0);
|
||||||
assertEquals(0, input.available(), "Available after contents all read");
|
assertEquals("Available after contents all read", 0, input.available());
|
||||||
|
|
||||||
// Check availbale is zero after End of file
|
// Check availbale is zero after End of file
|
||||||
assertEquals(-1, input.read(), "End of File");
|
assertEquals("End of File", -1, input.read());
|
||||||
assertEquals( 0, input.available(), "Available after End of File");
|
assertEquals("Available after End of File", 0, input.available());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -138,26 +138,26 @@ public abstract class InputStreamAbstractTest extends ObjectAbstractTest {
|
|||||||
|
|
||||||
// Read into array
|
// Read into array
|
||||||
int count1 = input.read(bytes);
|
int count1 = input.read(bytes);
|
||||||
assertEquals(bytes.length, count1, "Read 1");
|
assertEquals("Read 1", bytes.length, count1);
|
||||||
for (int i = 0; i < count1; i++) {
|
for (int i = 0; i < count1; i++) {
|
||||||
assertEquals(i, bytes[i], "Check Bytes 1");
|
assertEquals("Check Bytes 1", i, bytes[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read into array
|
// Read into array
|
||||||
int count2 = input.read(bytes);
|
int count2 = input.read(bytes);
|
||||||
assertEquals(5, count2, "Read 2");
|
assertEquals("Read 2", 5, count2);
|
||||||
for (int i = 0; i < count2; i++) {
|
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
|
// End of File
|
||||||
int count3 = input.read(bytes);
|
int count3 = input.read(bytes);
|
||||||
assertEquals(-1, count3, "Read 3 (EOF)");
|
assertEquals("Read 3 (EOF)", -1, count3);
|
||||||
|
|
||||||
// Test reading after the end of file
|
// Test reading after the end of file
|
||||||
try {
|
try {
|
||||||
int result = input.read(bytes);
|
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) {
|
catch (IOException e) {
|
||||||
fail("Should not have thrown an IOException: " + e.getMessage());
|
fail("Should not have thrown an IOException: " + e.getMessage());
|
||||||
@@ -170,20 +170,20 @@ public abstract class InputStreamAbstractTest extends ObjectAbstractTest {
|
|||||||
int offset = 2;
|
int offset = 2;
|
||||||
int lth = 4;
|
int lth = 4;
|
||||||
int count5 = input.read(bytes, offset, lth);
|
int count5 = input.read(bytes, offset, lth);
|
||||||
assertEquals(lth, count5, "Read 5");
|
assertEquals("Read 5", lth, count5);
|
||||||
for (int i = offset; i < lth; i++) {
|
for (int i = offset; i < lth; i++) {
|
||||||
assertEquals(i - offset, bytes[i], "Check Bytes 2");
|
assertEquals("Check Bytes 2", i - offset, bytes[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testEOF() throws Exception {
|
public void testEOF() throws Exception {
|
||||||
InputStream input = makeInputStream(makeOrderedArray(2));
|
InputStream input = makeInputStream(makeOrderedArray(2));
|
||||||
assertEquals(0, input.read(), "Read 1");
|
assertEquals("Read 1", 0, input.read());
|
||||||
assertEquals(1, input.read(), "Read 2");
|
assertEquals("Read 2", 1, input.read());
|
||||||
assertEquals(-1, input.read(), "Read 3");
|
assertEquals("Read 3", -1, input.read());
|
||||||
assertEquals(-1, input.read(), "Read 4");
|
assertEquals("Read 4", -1, input.read());
|
||||||
assertEquals(-1, input.read(), "Read 5");
|
assertEquals("Read 5", -1, input.read());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -205,7 +205,7 @@ public abstract class InputStreamAbstractTest extends ObjectAbstractTest {
|
|||||||
fail("Should throw IOException");
|
fail("Should throw IOException");
|
||||||
}
|
}
|
||||||
catch (IOException e) {
|
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.
|
// No mark may either throw exception, or reset to beginning of stream.
|
||||||
try {
|
try {
|
||||||
input.reset();
|
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) {
|
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
|
// Read further
|
||||||
for (int i = 0; i < 3; i++) {
|
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
|
// Reset
|
||||||
@@ -257,7 +257,7 @@ public abstract class InputStreamAbstractTest extends ObjectAbstractTest {
|
|||||||
|
|
||||||
// Read from marked position
|
// Read from marked position
|
||||||
for (int i = 0; i < readlimit + 1; i++) {
|
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
|
// Read past marked position
|
||||||
for (int i = 0; i < readlimit + 1; i++) {
|
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
|
// Reset after read limit passed, may either throw exception, or reset to last mark
|
||||||
try {
|
try {
|
||||||
input.reset();
|
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) {
|
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();
|
int first = input.read();
|
||||||
assertTrue(first >= 0, "Expected to read positive value");
|
assertTrue("Expected to read positive value", first >= 0);
|
||||||
|
|
||||||
int readlimit = 5;
|
int readlimit = 5;
|
||||||
|
|
||||||
// Mark
|
// Mark
|
||||||
input.mark(readlimit);
|
input.mark(readlimit);
|
||||||
int read = input.read();
|
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);
|
||||||
assertTrue(input.read() >= 0);
|
assertTrue(input.read() >= 0);
|
||||||
|
|
||||||
input.reset();
|
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
|
// Reset after read limit passed, may either throw exception, or reset to last good mark
|
||||||
try {
|
try {
|
||||||
input.reset();
|
input.reset();
|
||||||
int reRead = input.read();
|
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) {
|
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 {
|
public void testSkip() throws Exception {
|
||||||
InputStream input = makeInputStream(makeOrderedArray(10));
|
InputStream input = makeInputStream(makeOrderedArray(10));
|
||||||
|
|
||||||
assertEquals(0, input.read(), "Unexpected value read");
|
assertEquals("Unexpected value read", 0, input.read());
|
||||||
assertEquals(1, input.read(), "Unexpected value read");
|
assertEquals("Unexpected value read", 1, input.read());
|
||||||
assertEquals(5, input.skip(5), "Unexpected number of bytes skipped");
|
assertEquals("Unexpected number of bytes skipped", 5, input.skip(5));
|
||||||
assertEquals(7, input.read(), "Unexpected value read");
|
assertEquals("Unexpected value read", 7, input.read());
|
||||||
|
|
||||||
assertEquals(2, input.skip(5), "Unexpected number of bytes skipped"); // only 2 left to skip
|
assertEquals("Unexpected number of bytes skipped", 2, input.skip(5)); // only 2 left to skip
|
||||||
assertEquals(-1, input.read(), "Unexpected value read after EOF");
|
assertEquals("Unexpected value read after EOF", -1, input.read());
|
||||||
|
|
||||||
// Spec says skip might return 0 or negative after EOF...
|
// Spec says skip might return 0 or negative after EOF...
|
||||||
assertTrue(input.skip(5) <= 0, "Positive value skipped after EOF"); // End of file
|
assertTrue("Positive value skipped after EOF", input.skip(5) <= 0); // End of file
|
||||||
assertEquals(-1, input.read(), "Unexpected value read after EOF");
|
assertEquals("Unexpected value read after EOF", -1, input.read());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
+3
-2
@@ -30,11 +30,12 @@
|
|||||||
|
|
||||||
package com.twelvemonkeys.io;
|
package com.twelvemonkeys.io;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
import static org.junit.Assert.*;
|
||||||
import static org.junit.jupiter.api.Assertions.*;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* LittleEndianDataInputStreamTest
|
* LittleEndianDataInputStreamTest
|
||||||
|
|||||||
@@ -31,12 +31,13 @@
|
|||||||
package com.twelvemonkeys.io;
|
package com.twelvemonkeys.io;
|
||||||
|
|
||||||
import com.twelvemonkeys.lang.ObjectAbstractTest;
|
import com.twelvemonkeys.lang.ObjectAbstractTest;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
import static org.junit.Assert.assertNotNull;
|
||||||
import static org.junit.jupiter.api.Assertions.*;
|
import static org.junit.Assert.fail;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* InputStreamAbstractTestCase
|
* InputStreamAbstractTestCase
|
||||||
|
|||||||
@@ -31,12 +31,12 @@
|
|||||||
package com.twelvemonkeys.io;
|
package com.twelvemonkeys.io;
|
||||||
|
|
||||||
import com.twelvemonkeys.lang.ObjectAbstractTest;
|
import com.twelvemonkeys.lang.ObjectAbstractTest;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.Reader;
|
import java.io.Reader;
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
import static org.junit.Assert.*;
|
||||||
import static org.junit.jupiter.api.Assertions.*;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ReaderAbstractTestCase
|
* ReaderAbstractTestCase
|
||||||
@@ -112,7 +112,7 @@ public abstract class ReaderAbstractTest extends ObjectAbstractTest {
|
|||||||
int toSkip = mInput.length();
|
int toSkip = mInput.length();
|
||||||
while (toSkip > 0) {
|
while (toSkip > 0) {
|
||||||
long skipped = reader.skip(toSkip);
|
long skipped = reader.skip(toSkip);
|
||||||
assertFalse(skipped < 0, "Skipped < 0");
|
assertFalse("Skipped < 0", skipped < 0);
|
||||||
toSkip -= skipped;
|
toSkip -= skipped;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -30,8 +30,10 @@
|
|||||||
|
|
||||||
package com.twelvemonkeys.io;
|
package com.twelvemonkeys.io;
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.Test;
|
||||||
import static org.junit.jupiter.api.Assertions.*;
|
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
import static org.junit.Assert.fail;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* SeekableAbstractTestCase
|
* SeekableAbstractTestCase
|
||||||
|
|||||||
+23
-22
@@ -30,13 +30,14 @@
|
|||||||
|
|
||||||
package com.twelvemonkeys.io;
|
package com.twelvemonkeys.io;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.EOFException;
|
import java.io.EOFException;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
import static org.junit.Assert.*;
|
||||||
import static org.junit.jupiter.api.Assertions.*;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* SeekableInputStreamAbstractTest
|
* SeekableInputStreamAbstractTest
|
||||||
@@ -78,25 +79,25 @@ public abstract class SeekableInputStreamAbstractTest extends InputStreamAbstrac
|
|||||||
return; // Not supported, skip test
|
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;
|
int readlimit = 5;
|
||||||
|
|
||||||
// Mark
|
// Mark
|
||||||
input.mark(readlimit);
|
input.mark(readlimit);
|
||||||
int read = input.read();
|
int read = input.read();
|
||||||
assertTrue(read >= 0, "Expected to read positive value");
|
assertTrue("Expected to read positive value", read >= 0);
|
||||||
|
|
||||||
input.reset();
|
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
|
// Reset after read limit passed, may either throw exception, or reset to last good mark
|
||||||
try {
|
try {
|
||||||
input.reset();
|
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) {
|
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);
|
seekable.seek(pos);
|
||||||
long streamPos = seekable.getStreamPosition();
|
long streamPos = seekable.getStreamPosition();
|
||||||
assertEquals(pos, streamPos, "Stream positon should match seeked position");
|
assertEquals("Stream positon should match seeked position", pos, streamPos);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -136,7 +137,7 @@ public abstract class SeekableInputStreamAbstractTest extends InputStreamAbstrac
|
|||||||
seekable.seek(pos);
|
seekable.seek(pos);
|
||||||
seekable.flushBefore(pos);
|
seekable.flushBefore(pos);
|
||||||
long flushedPos = seekable.getFlushedPosition();
|
long flushedPos = seekable.getFlushedPosition();
|
||||||
assertEquals(pos, flushedPos, "Flushed positon should match position");
|
assertEquals("Flushed positon should match position", pos, flushedPos);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
seekable.seek(pos - 1);
|
seekable.seek(pos - 1);
|
||||||
@@ -381,13 +382,13 @@ public abstract class SeekableInputStreamAbstractTest extends InputStreamAbstrac
|
|||||||
int val;
|
int val;
|
||||||
|
|
||||||
val = stream.read();
|
val = stream.read();
|
||||||
assertFalse(val == -1, "Unexepected EOF");
|
assertFalse("Unexepected EOF", val == -1);
|
||||||
val = stream.read();
|
val = stream.read();
|
||||||
assertFalse(val == -1, "Unexepected EOF");
|
assertFalse("Unexepected EOF", val == -1);
|
||||||
val = stream.read();
|
val = stream.read();
|
||||||
assertFalse(val == -1, "Unexepected EOF");
|
assertFalse("Unexepected EOF", val == -1);
|
||||||
val = stream.read();
|
val = stream.read();
|
||||||
assertFalse(val == -1, "Unexepected EOF");
|
assertFalse("Unexepected EOF", val == -1);
|
||||||
|
|
||||||
stream.seek(0);
|
stream.seek(0);
|
||||||
|
|
||||||
@@ -421,19 +422,19 @@ public abstract class SeekableInputStreamAbstractTest extends InputStreamAbstrac
|
|||||||
|
|
||||||
stream.seek(0);
|
stream.seek(0);
|
||||||
for (int i = 0; i < bytes.length; i += 2) {
|
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);
|
int count = stream.read(buffer, 0, 2);
|
||||||
assertEquals(2, count);
|
assertEquals(2, count);
|
||||||
assertEquals(bytes[i], buffer[0], 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(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 + 1], buffer[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
stream.seek(0);
|
stream.seek(0);
|
||||||
for (int i = 0; i < bytes.length; i++) {
|
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();
|
int actual = stream.read();
|
||||||
assertEquals(bytes[i] & 0xff, 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(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], (byte) actual);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -455,14 +456,14 @@ public abstract class SeekableInputStreamAbstractTest extends InputStreamAbstrac
|
|||||||
try {
|
try {
|
||||||
FileUtil.read(stream); // Read until EOF
|
FileUtil.read(stream); // Read until EOF
|
||||||
|
|
||||||
assertEquals(-1, stream.read(), "EOF not reached (test case broken)");
|
assertEquals("EOF not reached (test case broken)", -1, stream.read());
|
||||||
assertFalse(closed[0], "Underlying stream closed before close");
|
assertFalse("Underlying stream closed before close", closed[0]);
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
stream.close();
|
stream.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
assertTrue(closed[0], "Underlying stream not closed");
|
assertTrue("Underlying stream not closed", closed[0]);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -31,12 +31,12 @@
|
|||||||
package com.twelvemonkeys.io;
|
package com.twelvemonkeys.io;
|
||||||
|
|
||||||
import com.twelvemonkeys.lang.StringUtil;
|
import com.twelvemonkeys.lang.StringUtil;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.Reader;
|
import java.io.Reader;
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
import static org.junit.Assert.*;
|
||||||
import static org.junit.jupiter.api.Assertions.*;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* StringArrayReaderTestCase
|
* 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;
|
package com.twelvemonkeys.io.enc;
|
||||||
|
|
||||||
import com.twelvemonkeys.io.FileUtil;
|
import com.twelvemonkeys.io.FileUtil;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
import static org.junit.jupiter.api.Assertions.*;
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base64DecoderTest
|
* Base64DecoderTest
|
||||||
* <p/>
|
* <p/>
|
||||||
@@ -64,7 +66,7 @@ public class Base64DecoderTest extends DecoderAbstractTest {
|
|||||||
|
|
||||||
FileUtil.copy(in, bytes);
|
FileUtil.copy(in, bytes);
|
||||||
|
|
||||||
assertEquals("", new String(bytes.toByteArray()), "Strings does not match");
|
assertEquals("Strings does not match", "", new String(bytes.toByteArray()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -76,7 +78,7 @@ public class Base64DecoderTest extends DecoderAbstractTest {
|
|||||||
|
|
||||||
FileUtil.copy(in, bytes);
|
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
|
@Test
|
||||||
@@ -91,12 +93,11 @@ public class Base64DecoderTest extends DecoderAbstractTest {
|
|||||||
|
|
||||||
FileUtil.copy(in, bytes);
|
FileUtil.copy(in, bytes);
|
||||||
|
|
||||||
assertEquals(
|
assertEquals("Strings does not match",
|
||||||
"Lorem ipsum dolor sit amet, consectetuer adipiscing " +
|
"Lorem ipsum dolor sit amet, consectetuer adipiscing " +
|
||||||
"elit. Fusce est. Morbi luctus consectetuer justo. Vivamus " +
|
"elit. Fusce est. Morbi luctus consectetuer justo. Vivamus " +
|
||||||
"dapibus laoreet purus. Nunc viverra dictum nisl. Integer " +
|
"dapibus laoreet purus. Nunc viverra dictum nisl. Integer " +
|
||||||
"ullamcorper, nisi in dictum amet.",
|
"ullamcorper, nisi in dictum amet.",
|
||||||
new String(bytes.toByteArray()),
|
new String(bytes.toByteArray()));
|
||||||
"Strings does not match");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -30,12 +30,13 @@
|
|||||||
|
|
||||||
package com.twelvemonkeys.io.enc;
|
package com.twelvemonkeys.io.enc;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
import static org.junit.jupiter.api.Assertions.*;
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base64EncoderTest
|
* Base64EncoderTest
|
||||||
@@ -62,7 +63,7 @@ public class Base64EncoderTest extends EncoderAbstractTest {
|
|||||||
OutputStream out = new EncoderStream(bytes, createEncoder(), true);
|
OutputStream out = new EncoderStream(bytes, createEncoder(), true);
|
||||||
out.write(data.getBytes());
|
out.write(data.getBytes());
|
||||||
|
|
||||||
assertEquals("", new String(bytes.toByteArray()), "Strings does not match");
|
assertEquals("Strings does not match", "", new String(bytes.toByteArray()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -73,7 +74,7 @@ public class Base64EncoderTest extends EncoderAbstractTest {
|
|||||||
OutputStream out = new EncoderStream(bytes, createEncoder(), true);
|
OutputStream out = new EncoderStream(bytes, createEncoder(), true);
|
||||||
out.write(data.getBytes());
|
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
|
@Test
|
||||||
@@ -87,12 +88,11 @@ public class Base64EncoderTest extends EncoderAbstractTest {
|
|||||||
OutputStream out = new EncoderStream(bytes, createEncoder(), true);
|
OutputStream out = new EncoderStream(bytes, createEncoder(), true);
|
||||||
out.write(data.getBytes());
|
out.write(data.getBytes());
|
||||||
|
|
||||||
assertEquals(
|
assertEquals("Strings does not match",
|
||||||
"TG9yZW0gaXBzdW0gZG9sb3Igc2l0IGFtZXQsIGNvbnNlY3RldHVlciBhZGlwaXNjaW5nIGVsaXQuIEZ1" +
|
"TG9yZW0gaXBzdW0gZG9sb3Igc2l0IGFtZXQsIGNvbnNlY3RldHVlciBhZGlwaXNjaW5nIGVsaXQuIEZ1" +
|
||||||
"c2NlIGVzdC4gTW9yYmkgbHVjdHVzIGNvbnNlY3RldHVlciBqdXN0by4gVml2YW11cyBkYXBpYnVzIGxh" +
|
"c2NlIGVzdC4gTW9yYmkgbHVjdHVzIGNvbnNlY3RldHVlciBqdXN0by4gVml2YW11cyBkYXBpYnVzIGxh" +
|
||||||
"b3JlZXQgcHVydXMuIE51bmMgdml2ZXJyYSBkaWN0dW0gbmlzbC4gSW50ZWdlciB1bGxhbWNvcnBlciwg" +
|
"b3JlZXQgcHVydXMuIE51bmMgdml2ZXJyYSBkaWN0dW0gbmlzbC4gSW50ZWdlciB1bGxhbWNvcnBlciwg" +
|
||||||
"bmlzaSBpbiBkaWN0dW0gYW1ldC4=",
|
"bmlzaSBpbiBkaWN0dW0gYW1ldC4=",
|
||||||
new String(bytes.toByteArray()),
|
new String(bytes.toByteArray()));
|
||||||
"Strings does not match");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,13 +32,12 @@ package com.twelvemonkeys.io.enc;
|
|||||||
|
|
||||||
import com.twelvemonkeys.io.FileUtil;
|
import com.twelvemonkeys.io.FileUtil;
|
||||||
import com.twelvemonkeys.lang.ObjectAbstractTest;
|
import com.twelvemonkeys.lang.ObjectAbstractTest;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
import java.awt.image.ImageProducer;
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
import static org.junit.Assert.*;
|
||||||
import static org.junit.jupiter.api.Assertions.*;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* AbstractDecoderTest
|
* AbstractDecoderTest
|
||||||
@@ -56,13 +55,13 @@ public abstract class DecoderAbstractTest extends ObjectAbstractTest {
|
|||||||
return createDecoder();
|
return createDecoder();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test(expected = NullPointerException.class)
|
||||||
public final void testNullDecode() throws IOException {
|
public final void testNullDecode() throws IOException {
|
||||||
Decoder decoder = createDecoder();
|
Decoder decoder = createDecoder();
|
||||||
ByteArrayInputStream bytes = new ByteArrayInputStream(new byte[20]);
|
ByteArrayInputStream bytes = new ByteArrayInputStream(new byte[20]);
|
||||||
assertThrows(NullPointerException.class, () -> {
|
|
||||||
decoder.decode(bytes, null);
|
decoder.decode(bytes, null);
|
||||||
});
|
fail("null should throw NullPointerException");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -72,7 +71,7 @@ public abstract class DecoderAbstractTest extends ObjectAbstractTest {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
int count = decoder.decode(bytes, ByteBuffer.allocate(128));
|
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) {
|
catch (EOFException allowed) {
|
||||||
// Okay
|
// Okay
|
||||||
@@ -95,7 +94,7 @@ public abstract class DecoderAbstractTest extends ObjectAbstractTest {
|
|||||||
byte[] encoded = outBytes.toByteArray();
|
byte[] encoded = outBytes.toByteArray();
|
||||||
|
|
||||||
byte[] decoded = FileUtil.read(new DecoderStream(new ByteArrayInputStream(encoded), createDecoder()));
|
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());
|
InputStream in = new DecoderStream(new ByteArrayInputStream(encoded), createDecoder());
|
||||||
outBytes = new ByteArrayOutputStream();
|
outBytes = new ByteArrayOutputStream();
|
||||||
@@ -104,7 +103,7 @@ public abstract class DecoderAbstractTest extends ObjectAbstractTest {
|
|||||||
in.close();
|
in.close();
|
||||||
|
|
||||||
decoded = outBytes.toByteArray();
|
decoded = outBytes.toByteArray();
|
||||||
assertArrayEquals(data, decoded, String.format("Data %d", pLength));
|
assertArrayEquals(String.format("Data %d", pLength), data, decoded);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
@@ -1,130 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2022, 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.io.enc;
|
|
||||||
|
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
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.*;
|
|
||||||
|
|
||||||
public class DecoderStreamTest {
|
|
||||||
|
|
||||||
private final Random rng = new Random(5467809876546L);
|
|
||||||
|
|
||||||
private byte[] createData(final int length) {
|
|
||||||
byte[] data = new byte[length];
|
|
||||||
rng.nextBytes(data);
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testDecodeSingleBytes() throws IOException {
|
|
||||||
byte[] data = createData(1327);
|
|
||||||
|
|
||||||
InputStream source = new ByteArrayInputStream(data);
|
|
||||||
try (InputStream stream = new DecoderStream(source, new NullDecoder())) {
|
|
||||||
for (byte datum : data) {
|
|
||||||
int read = stream.read();
|
|
||||||
assertNotEquals(-1, read);
|
|
||||||
assertEquals(datum, (byte) read);
|
|
||||||
}
|
|
||||||
|
|
||||||
assertEquals(-1, stream.read());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testDecodeArray() throws IOException {
|
|
||||||
int length = 793;
|
|
||||||
byte[] data = createData(length * 10);
|
|
||||||
|
|
||||||
InputStream source = new ByteArrayInputStream(data);
|
|
||||||
byte[] result = new byte[477];
|
|
||||||
|
|
||||||
try (InputStream stream = new DecoderStream(source, new NullDecoder())) {
|
|
||||||
int dataOffset = 0;
|
|
||||||
while (dataOffset < data.length) {
|
|
||||||
int count = stream.read(result);
|
|
||||||
|
|
||||||
assertFalse(count <= 0);
|
|
||||||
assertArrayEquals(Arrays.copyOfRange(data, dataOffset, dataOffset + count), Arrays.copyOfRange(result, 0, count));
|
|
||||||
|
|
||||||
dataOffset += count;
|
|
||||||
}
|
|
||||||
|
|
||||||
assertEquals(-1, stream.read());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testDecodeArrayOffset() throws IOException {
|
|
||||||
int length = 793;
|
|
||||||
byte[] data = createData(length * 10);
|
|
||||||
|
|
||||||
InputStream source = new ByteArrayInputStream(data);
|
|
||||||
byte[] result = new byte[477];
|
|
||||||
|
|
||||||
try (InputStream stream = new DecoderStream(source, new NullDecoder())) {
|
|
||||||
int dataOffset = 0;
|
|
||||||
while (dataOffset < data.length) {
|
|
||||||
int resultOffset = dataOffset % result.length;
|
|
||||||
int count = stream.read(result, resultOffset, result.length - resultOffset);
|
|
||||||
|
|
||||||
assertFalse(count <= 0);
|
|
||||||
assertArrayEquals(Arrays.copyOfRange(data, dataOffset + resultOffset, dataOffset + count), Arrays.copyOfRange(result, resultOffset, count));
|
|
||||||
|
|
||||||
dataOffset += count;
|
|
||||||
}
|
|
||||||
|
|
||||||
assertEquals(-1, stream.read());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final class NullDecoder implements Decoder {
|
|
||||||
@Override
|
|
||||||
public int decode(InputStream stream, ByteBuffer buffer) throws IOException {
|
|
||||||
int read = stream.read(buffer.array(), buffer.arrayOffset(), buffer.remaining());
|
|
||||||
|
|
||||||
if (read > 0) {
|
|
||||||
// Set position, should be equivalent to using buffer.put(stream.read()) until EOF or buffer full
|
|
||||||
buffer.position(read);
|
|
||||||
}
|
|
||||||
|
|
||||||
return read;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -33,12 +33,13 @@ package com.twelvemonkeys.io.enc;
|
|||||||
import com.twelvemonkeys.io.FileUtil;
|
import com.twelvemonkeys.io.FileUtil;
|
||||||
import com.twelvemonkeys.lang.ObjectAbstractTest;
|
import com.twelvemonkeys.lang.ObjectAbstractTest;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
import static org.junit.Assert.assertArrayEquals;
|
||||||
import static org.junit.jupiter.api.Assertions.*;
|
import static org.junit.Assert.fail;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* AbstractEncoderTest
|
* AbstractEncoderTest
|
||||||
|
|||||||
@@ -1,110 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2022, 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.io.enc;
|
|
||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.OutputStream;
|
|
||||||
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.*;
|
|
||||||
|
|
||||||
public class EncoderStreamTest {
|
|
||||||
|
|
||||||
private final Random rng = new Random(5467809876546L);
|
|
||||||
|
|
||||||
private byte[] createData(final int length) {
|
|
||||||
byte[] data = new byte[length];
|
|
||||||
rng.nextBytes(data);
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testEncodeSingleBytes() throws IOException {
|
|
||||||
byte[] data = createData(1327);
|
|
||||||
|
|
||||||
ByteArrayOutputStream result = new ByteArrayOutputStream();
|
|
||||||
try (OutputStream stream = new EncoderStream(result, new NullEncoder())) {
|
|
||||||
for (byte datum : data) {
|
|
||||||
stream.write(datum);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
assertArrayEquals(data, result.toByteArray());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testEncodeArray() throws IOException {
|
|
||||||
byte[] data = createData(1793);
|
|
||||||
|
|
||||||
ByteArrayOutputStream result = new ByteArrayOutputStream();
|
|
||||||
try (OutputStream stream = new EncoderStream(result, new NullEncoder())) {
|
|
||||||
for (int i = 0; i < 10; i++) {
|
|
||||||
stream.write(data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
byte[] encoded = result.toByteArray();
|
|
||||||
|
|
||||||
for (int i = 0; i < 10; i++) {
|
|
||||||
assertArrayEquals(data, Arrays.copyOfRange(encoded, i * data.length, (i + 1) * data.length));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testEncodeArrayOffset() throws IOException {
|
|
||||||
byte[] data = createData(87);
|
|
||||||
|
|
||||||
ByteArrayOutputStream result = new ByteArrayOutputStream();
|
|
||||||
try (OutputStream stream = new EncoderStream(result, new NullEncoder())) {
|
|
||||||
for (int i = 0; i < 10; i++) {
|
|
||||||
stream.write(data, 13, 59);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
byte[] original = Arrays.copyOfRange(data, 13, 13 + 59);
|
|
||||||
byte[] encoded = result.toByteArray();
|
|
||||||
|
|
||||||
for (int i = 0; i < 10; i++) {
|
|
||||||
assertArrayEquals(original, Arrays.copyOfRange(encoded, i * original.length, (i + 1) * original.length));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final class NullEncoder implements Encoder {
|
|
||||||
@Override
|
|
||||||
public void encode(OutputStream stream, ByteBuffer buffer) throws IOException {
|
|
||||||
stream.write(buffer.array(), buffer.arrayOffset(), buffer.remaining());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+16
-17
@@ -31,9 +31,9 @@
|
|||||||
package com.twelvemonkeys.io.ole2;
|
package com.twelvemonkeys.io.ole2;
|
||||||
|
|
||||||
import com.twelvemonkeys.io.MemoryCacheSeekableStream;
|
import com.twelvemonkeys.io.MemoryCacheSeekableStream;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
import javax.imageio.stream.MemoryCacheImageInputStream;
|
import javax.imageio.stream.MemoryCacheImageInputStream;
|
||||||
import java.awt.image.ImageProducer;
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
@@ -43,8 +43,8 @@ import java.nio.ByteOrder;
|
|||||||
import java.util.SortedSet;
|
import java.util.SortedSet;
|
||||||
import java.util.TreeSet;
|
import java.util.TreeSet;
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
import static org.junit.Assert.*;
|
||||||
import static org.junit.jupiter.api.Assertions.*;
|
|
||||||
/**
|
/**
|
||||||
* CompoundDocumentTestCase
|
* CompoundDocumentTestCase
|
||||||
*
|
*
|
||||||
@@ -59,8 +59,8 @@ public class CompoundDocumentTest {
|
|||||||
protected final CompoundDocument createTestDocument() throws IOException {
|
protected final CompoundDocument createTestDocument() throws IOException {
|
||||||
URL input = getClass().getResource(SAMPLE_DATA);
|
URL input = getClass().getResource(SAMPLE_DATA);
|
||||||
|
|
||||||
assertNotNull(input, "Missing test resource!");
|
assertNotNull("Missing test resource!", input);
|
||||||
assertEquals( "file", input.getProtocol(), "Test resource not a file:// resource");
|
assertEquals("Test resource not a file:// resource", "file", input.getProtocol());
|
||||||
|
|
||||||
try {
|
try {
|
||||||
return new CompoundDocument(new File(input.toURI()));
|
return new CompoundDocument(new File(input.toURI()));
|
||||||
@@ -103,7 +103,7 @@ public class CompoundDocumentTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test(expected = UnsupportedOperationException.class)
|
||||||
public void testChildEntriesUnmodifiable() throws IOException {
|
public void testChildEntriesUnmodifiable() throws IOException {
|
||||||
try (CompoundDocument document = createTestDocument()) {
|
try (CompoundDocument document = createTestDocument()) {
|
||||||
Entry root = document.getRootEntry();
|
Entry root = document.getRootEntry();
|
||||||
@@ -111,10 +111,9 @@ public class CompoundDocumentTest {
|
|||||||
assertNotNull(root);
|
assertNotNull(root);
|
||||||
|
|
||||||
SortedSet<Entry> children = root.getChildEntries();
|
SortedSet<Entry> children = root.getChildEntries();
|
||||||
assertThrows(UnsupportedOperationException.class, () -> {
|
|
||||||
// Should not be allowed, as it modifies the internal structure
|
// Should not be allowed, as it modifies the internal structure
|
||||||
children.remove(children.first());
|
children.remove(children.first());
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -129,7 +128,7 @@ public class CompoundDocumentTest {
|
|||||||
Entry catalog = root.getChildEntry("Catalog");
|
Entry catalog = root.getChildEntry("Catalog");
|
||||||
|
|
||||||
assertNotNull(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 {
|
public void testReadCatalogInputStream() throws IOException {
|
||||||
InputStream input = getClass().getResourceAsStream(SAMPLE_DATA);
|
InputStream input = getClass().getResourceAsStream(SAMPLE_DATA);
|
||||||
|
|
||||||
assertNotNull(input, "Missing test resource!");
|
assertNotNull("Missing test resource!", input);
|
||||||
|
|
||||||
CompoundDocument document = new CompoundDocument(input);
|
CompoundDocument document = new CompoundDocument(input);
|
||||||
Entry root = document.getRootEntry();
|
Entry root = document.getRootEntry();
|
||||||
@@ -146,14 +145,14 @@ public class CompoundDocumentTest {
|
|||||||
|
|
||||||
Entry catalog = root.getChildEntry("Catalog");
|
Entry catalog = root.getChildEntry("Catalog");
|
||||||
assertNotNull(catalog);
|
assertNotNull(catalog);
|
||||||
assertNotNull(catalog.getInputStream(), "Input stream may not be null");
|
assertNotNull("Input stream may not be null", catalog.getInputStream());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testReadCatalogSeekableStream() throws IOException {
|
public void testReadCatalogSeekableStream() throws IOException {
|
||||||
InputStream input = getClass().getResourceAsStream(SAMPLE_DATA);
|
InputStream input = getClass().getResourceAsStream(SAMPLE_DATA);
|
||||||
|
|
||||||
assertNotNull(input, "Missing test resource!");
|
assertNotNull("Missing test resource!", input);
|
||||||
|
|
||||||
CompoundDocument document = new CompoundDocument(new MemoryCacheSeekableStream(input));
|
CompoundDocument document = new CompoundDocument(new MemoryCacheSeekableStream(input));
|
||||||
Entry root = document.getRootEntry();
|
Entry root = document.getRootEntry();
|
||||||
@@ -162,14 +161,14 @@ public class CompoundDocumentTest {
|
|||||||
|
|
||||||
Entry catalog = root.getChildEntry("Catalog");
|
Entry catalog = root.getChildEntry("Catalog");
|
||||||
assertNotNull(catalog);
|
assertNotNull(catalog);
|
||||||
assertNotNull(catalog.getInputStream(), "Input stream may not be null");
|
assertNotNull("Input stream may not be null", catalog.getInputStream());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testReadCatalogImageInputStream() throws IOException {
|
public void testReadCatalogImageInputStream() throws IOException {
|
||||||
InputStream input = getClass().getResourceAsStream(SAMPLE_DATA);
|
InputStream input = getClass().getResourceAsStream(SAMPLE_DATA);
|
||||||
|
|
||||||
assertNotNull(input, "Missing test resource!");
|
assertNotNull("Missing test resource!", input);
|
||||||
|
|
||||||
MemoryCacheImageInputStream stream = new MemoryCacheImageInputStream(input);
|
MemoryCacheImageInputStream stream = new MemoryCacheImageInputStream(input);
|
||||||
stream.setByteOrder(ByteOrder.LITTLE_ENDIAN);
|
stream.setByteOrder(ByteOrder.LITTLE_ENDIAN);
|
||||||
@@ -184,6 +183,6 @@ public class CompoundDocumentTest {
|
|||||||
Entry catalog = root.getChildEntry("Catalog");
|
Entry catalog = root.getChildEntry("Catalog");
|
||||||
|
|
||||||
assertNotNull(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;
|
package com.twelvemonkeys.io.ole2;
|
||||||
|
|
||||||
import com.twelvemonkeys.io.*;
|
import com.twelvemonkeys.io.*;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
|
|
||||||
|
|||||||
+4
-4
@@ -33,6 +33,7 @@ package com.twelvemonkeys.io.ole2;
|
|||||||
import com.twelvemonkeys.io.InputStreamAbstractTest;
|
import com.twelvemonkeys.io.InputStreamAbstractTest;
|
||||||
import com.twelvemonkeys.io.LittleEndianDataOutputStream;
|
import com.twelvemonkeys.io.LittleEndianDataOutputStream;
|
||||||
import com.twelvemonkeys.io.MemoryCacheSeekableStream;
|
import com.twelvemonkeys.io.MemoryCacheSeekableStream;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
@@ -41,8 +42,7 @@ import java.io.InputStream;
|
|||||||
import java.nio.charset.Charset;
|
import java.nio.charset.Charset;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
import static org.junit.Assert.*;
|
||||||
import static org.junit.jupiter.api.Assertions.*;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* CompoundDocument_StreamTestCase
|
* CompoundDocument_StreamTestCase
|
||||||
@@ -165,8 +165,8 @@ public class CompoundDocument_StreamTest extends InputStreamAbstractTest {
|
|||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
|
|
||||||
assertFalse(count < 32, "Short stream");
|
assertFalse("Short stream", count < 32);
|
||||||
assertFalse(count > 32, "Stream overrun");
|
assertFalse("Stream overrun", count > 32);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
@@ -30,8 +30,9 @@
|
|||||||
|
|
||||||
package com.twelvemonkeys.net;
|
package com.twelvemonkeys.net;
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.Test;
|
||||||
import static org.junit.jupiter.api.Assertions.*;
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* HTTPUtilTest
|
* HTTPUtilTest
|
||||||
|
|||||||
@@ -4,25 +4,17 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>com.twelvemonkeys.common</groupId>
|
<groupId>com.twelvemonkeys.common</groupId>
|
||||||
<artifactId>common</artifactId>
|
<artifactId>common</artifactId>
|
||||||
<version>3.12.1-SNAPSHOT</version>
|
<version>3.7.1</version>
|
||||||
</parent>
|
</parent>
|
||||||
<artifactId>common-lang</artifactId>
|
<artifactId>common-lang</artifactId>
|
||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
<name>TwelveMonkeys :: Common :: Language support</name>
|
<name>TwelveMonkeys :: Common :: Language support</name>
|
||||||
<description>
|
<description>
|
||||||
TwelveMonkeys Common language support classes.
|
The TwelveMonkeys Common Language support
|
||||||
</description>
|
</description>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<project.jpms.module.name>com.twelvemonkeys.common.lang</project.jpms.module.name>
|
<project.jpms.module.name>com.twelvemonkeys.common.lang</project.jpms.module.name>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
<build>
|
|
||||||
<plugins>
|
|
||||||
<plugin>
|
|
||||||
<groupId>org.apache.felix</groupId>
|
|
||||||
<artifactId>maven-bundle-plugin</artifactId>
|
|
||||||
</plugin>
|
|
||||||
</plugins>
|
|
||||||
</build>
|
|
||||||
</project>
|
</project>
|
||||||
|
|||||||
@@ -904,7 +904,7 @@ public final class StringUtil {
|
|||||||
}
|
}
|
||||||
catch (ParseException pe) {
|
catch (ParseException pe) {
|
||||||
// Wrap in RuntimeException
|
// 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;
|
package com.twelvemonkeys.lang;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
import static org.junit.Assert.*;
|
||||||
import static org.junit.jupiter.api.Assertions.*;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* BeanUtilTestCase
|
* BeanUtilTestCase
|
||||||
@@ -160,8 +161,10 @@ public class BeanUtilTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
assertNotNull(bean.getAmbiguous());
|
assertNotNull(bean.getAmbiguous());
|
||||||
assertEquals("one", bean.getAmbiguous(), "String converted rather than invoking setAmbiguous(String), ordering not predictable");
|
assertEquals("String converted rather than invoking setAmbiguous(String), ordering not predictable",
|
||||||
assertSame(value, bean.getAmbiguous(), "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
|
@Test
|
||||||
@@ -181,10 +184,10 @@ public class BeanUtilTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
assertNotNull(bean.getAmbiguous());
|
assertNotNull(bean.getAmbiguous());
|
||||||
assertEquals(2, bean.getAmbiguous(),
|
assertEquals("Integer converted rather than invoking setAmbiguous(Integer), ordering not predictable",
|
||||||
"Integer converted rather than invoking setAmbiguous(Integer), ordering not predictable");
|
2, bean.getAmbiguous());
|
||||||
assertSame(value, bean.getAmbiguous(),
|
assertSame("Integer converted rather than invoking setAmbiguous(Integer), ordering not predictable",
|
||||||
"Integer converted rather than invoking setAmbiguous(Integer), ordering not predictable");
|
value, bean.getAmbiguous());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -204,8 +207,10 @@ public class BeanUtilTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
assertNotNull(bean.getAmbiguous());
|
assertNotNull(bean.getAmbiguous());
|
||||||
assertEquals(value.getClass(), bean.getAmbiguous().getClass(), "Object converted rather than invoking setAmbiguous(Object), ordering not predictable");
|
assertEquals("Object converted rather than invoking setAmbiguous(Object), ordering not predictable",
|
||||||
assertSame(value, bean.getAmbiguous(), "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 {
|
static class TestBean {
|
||||||
|
|||||||
@@ -30,16 +30,16 @@
|
|||||||
|
|
||||||
package com.twelvemonkeys.lang;
|
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.Arrays;
|
||||||
import java.util.Calendar;
|
import java.util.Calendar;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.TimeZone;
|
import java.util.TimeZone;
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
import static org.junit.Assert.assertEquals;
|
||||||
import org.junit.jupiter.params.ParameterizedTest;
|
|
||||||
import org.junit.jupiter.params.provider.MethodSource;
|
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.*;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* DateUtilTest
|
* DateUtilTest
|
||||||
@@ -48,9 +48,12 @@ import static org.junit.jupiter.api.Assertions.*;
|
|||||||
* @author last modified by $Author: haraldk$
|
* @author last modified by $Author: haraldk$
|
||||||
* @version $Id: DateUtilTest.java,v 1.0 11.04.12 16:21 haraldk Exp$
|
* @version $Id: DateUtilTest.java,v 1.0 11.04.12 16:21 haraldk Exp$
|
||||||
*/
|
*/
|
||||||
|
@RunWith(Parameterized.class)
|
||||||
public class DateUtilTest {
|
public class DateUtilTest {
|
||||||
|
|
||||||
|
private final TimeZone timeZone;
|
||||||
|
|
||||||
|
@Parameterized.Parameters
|
||||||
public static List<Object[]> timeZones() {
|
public static List<Object[]> timeZones() {
|
||||||
return Arrays.asList(new Object[][] {
|
return Arrays.asList(new Object[][] {
|
||||||
{TimeZone.getTimeZone("UTC")},
|
{TimeZone.getTimeZone("UTC")},
|
||||||
@@ -59,6 +62,10 @@ public class DateUtilTest {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public DateUtilTest(final TimeZone timeZone) {
|
||||||
|
this.timeZone = timeZone;
|
||||||
|
}
|
||||||
|
|
||||||
private Calendar getCalendar(long time) {
|
private Calendar getCalendar(long time) {
|
||||||
return getCalendar(time, TimeZone.getDefault());
|
return getCalendar(time, TimeZone.getDefault());
|
||||||
}
|
}
|
||||||
@@ -94,9 +101,8 @@ public class DateUtilTest {
|
|||||||
assertEquals(0, calendar.get(Calendar.MINUTE));
|
assertEquals(0, calendar.get(Calendar.MINUTE));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ParameterizedTest
|
@Test
|
||||||
@MethodSource("timeZones")
|
public void testRoundToHourTZ() {
|
||||||
public void testRoundToHourTZ(TimeZone timeZone) {
|
|
||||||
Calendar calendar = getCalendar(DateUtil.roundToHour(System.currentTimeMillis(), timeZone), timeZone);
|
Calendar calendar = getCalendar(DateUtil.roundToHour(System.currentTimeMillis(), timeZone), timeZone);
|
||||||
|
|
||||||
assertEquals(0, calendar.get(Calendar.MILLISECOND));
|
assertEquals(0, calendar.get(Calendar.MILLISECOND));
|
||||||
@@ -114,9 +120,8 @@ public class DateUtilTest {
|
|||||||
assertEquals(0, calendar.get(Calendar.HOUR_OF_DAY));
|
assertEquals(0, calendar.get(Calendar.HOUR_OF_DAY));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ParameterizedTest
|
@Test
|
||||||
@MethodSource("timeZones")
|
public void testRoundToDayTZ() {
|
||||||
public void testRoundToDayTZ(TimeZone timeZone) {
|
|
||||||
Calendar calendar = getCalendar(DateUtil.roundToDay(System.currentTimeMillis(), timeZone), timeZone);
|
Calendar calendar = getCalendar(DateUtil.roundToDay(System.currentTimeMillis(), timeZone), timeZone);
|
||||||
|
|
||||||
assertEquals(0, calendar.get(Calendar.MILLISECOND));
|
assertEquals(0, calendar.get(Calendar.MILLISECOND));
|
||||||
|
|||||||
@@ -30,11 +30,12 @@
|
|||||||
|
|
||||||
package com.twelvemonkeys.lang;
|
package com.twelvemonkeys.lang;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
import static org.junit.Assert.*;
|
||||||
import static org.junit.jupiter.api.Assertions.*;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* AbstractObjectTestCase
|
* AbstractObjectTestCase
|
||||||
@@ -78,10 +79,10 @@ public abstract class ObjectAbstractTest {
|
|||||||
|
|
||||||
Class cl = obj.getClass();
|
Class cl = obj.getClass();
|
||||||
if (isEqualsOverriden(cl)) {
|
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)) {
|
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
|
@Test
|
||||||
public void testObjectEqualsSelf() {
|
public void testObjectEqualsSelf() {
|
||||||
Object obj = makeObject();
|
Object obj = makeObject();
|
||||||
assertEquals(obj, obj, "An Object should equal itself");
|
assertEquals("An Object should equal itself", obj, obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -114,26 +115,32 @@ public abstract class ObjectAbstractTest {
|
|||||||
Object obj = makeObject();
|
Object obj = makeObject();
|
||||||
// NOTE: Makes sure this doesn't throw NPE either
|
// NOTE: Makes sure this doesn't throw NPE either
|
||||||
//noinspection ObjectEqualsNull
|
//noinspection ObjectEqualsNull
|
||||||
assertFalse(obj.equals(null), "An object should never equal null");
|
assertFalse("An object should never equal null", obj.equals(null));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testObjectHashCodeEqualsSelfHashCode() {
|
public void testObjectHashCodeEqualsSelfHashCode() {
|
||||||
Object obj = makeObject();
|
Object obj = makeObject();
|
||||||
assertEquals(obj.hashCode(), obj.hashCode(), "hashCode should be repeatable");
|
assertEquals("hashCode should be repeatable", obj.hashCode(), obj.hashCode());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testObjectHashCodeEqualsContract() {
|
public void testObjectHashCodeEqualsContract() {
|
||||||
Object obj1 = makeObject();
|
Object obj1 = makeObject();
|
||||||
if (obj1.equals(obj1)) {
|
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
|
// TODO: Make sure we create at least one equal object, and one different object
|
||||||
Object obj2 = makeObject();
|
Object obj2 = makeObject();
|
||||||
if (obj1.equals(obj2)) {
|
if (obj1.equals(obj2)) {
|
||||||
assertEquals(obj1.hashCode(), obj2.hashCode(), "[2] When two objects are equal, their hashCodes should be also.");
|
assertEquals(
|
||||||
assertTrue(obj2.equals(obj1), "When obj1.equals(obj2) is true, then obj2.equals(obj1) should also be true");
|
"[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);
|
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
|
// TODO: This can only be asserted if equals() test is based on
|
||||||
// value equality, not reference (identity) equality
|
// value equality, not reference (identity) equality
|
||||||
// Maybe it's possible to do a reflective introspection of
|
// Maybe it's possible to do a reflective introspection of
|
||||||
// the objects fields?
|
// the objects fields?
|
||||||
if (isHashCodeOverriden(cl)) {
|
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
|
// Maybe it's possible to do a reflective introspection of
|
||||||
// the objects fields?
|
// the objects fields?
|
||||||
if (isEqualsOverriden(obj.getClass())) {
|
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;
|
package com.twelvemonkeys.lang;
|
||||||
|
|
||||||
|
import org.junit.Ignore;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
|
|
||||||
import org.junit.jupiter.api.Disabled;
|
import static org.junit.Assert.assertEquals;
|
||||||
import org.junit.jupiter.api.Test;
|
import static org.junit.Assert.assertNotNull;
|
||||||
import static org.junit.jupiter.api.Assertions.*;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* PlatformTest
|
* PlatformTest
|
||||||
@@ -119,7 +121,7 @@ public class PlatformTest {
|
|||||||
assertEquals(Platform.Architecture.X86, platform.getArchitecture());
|
assertEquals(Platform.Architecture.X86, platform.getArchitecture());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Disabled("Known issue, needs resolve")
|
@Ignore("Known issue, needs resolve")
|
||||||
@Test
|
@Test
|
||||||
public void testCreateWindows686() {
|
public void testCreateWindows686() {
|
||||||
Platform platform = new Platform(createProperties("Windows", "5.1", "686"));
|
Platform platform = new Platform(createProperties("Windows", "5.1", "686"));
|
||||||
@@ -127,7 +129,7 @@ public class PlatformTest {
|
|||||||
assertEquals(Platform.Architecture.X86, platform.getArchitecture());
|
assertEquals(Platform.Architecture.X86, platform.getArchitecture());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Disabled("Known issue, needs resolve")
|
@Ignore("Known issue, needs resolve")
|
||||||
@Test
|
@Test
|
||||||
public void testCreateLinuxX86() {
|
public void testCreateLinuxX86() {
|
||||||
Platform platform = new Platform(createProperties("Linux", "3.0.18", "x86"));
|
Platform platform = new Platform(createProperties("Linux", "3.0.18", "x86"));
|
||||||
|
|||||||
@@ -30,6 +30,8 @@
|
|||||||
|
|
||||||
package com.twelvemonkeys.lang;
|
package com.twelvemonkeys.lang;
|
||||||
|
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.sql.Timestamp;
|
import java.sql.Timestamp;
|
||||||
import java.text.DateFormat;
|
import java.text.DateFormat;
|
||||||
@@ -39,8 +41,8 @@ import java.util.Date;
|
|||||||
import java.util.GregorianCalendar;
|
import java.util.GregorianCalendar;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.Test;
|
||||||
import static org.junit.jupiter.api.Assertions.*;
|
|
||||||
/**
|
/**
|
||||||
* StringUtilTestCase
|
* StringUtilTestCase
|
||||||
*
|
*
|
||||||
@@ -163,10 +165,10 @@ public class StringUtilTest {
|
|||||||
// Test all alpha-chars
|
// Test all alpha-chars
|
||||||
for (int i = 'a'; i < 'z'; i++) {
|
for (int i = 'a'; i < 'z'; i++) {
|
||||||
if (TEST_STRING.indexOf(i) < 0) {
|
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 {
|
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
|
// Test all alpha-chars
|
||||||
for (int i = 'a'; i < 'z'; i++) {
|
for (int i = 'a'; i < 'z'; i++) {
|
||||||
if ((TEST_STRING.indexOf(i) < 0) && (TEST_STRING.indexOf(Character.toUpperCase((char) i)) < 0)) {
|
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 {
|
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
|
// Test all alpha-chars
|
||||||
for (int i = 'a'; i < 'z'; i++) {
|
for (int i = 'a'; i < 'z'; i++) {
|
||||||
if ((TEST_STRING.indexOf(i) < 0) && (TEST_STRING.indexOf(Character.toUpperCase((char) i)) < 0)) {
|
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 {
|
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
|
// Test all alpha-chars
|
||||||
for (int i = 'a'; i < 'z'; i++) {
|
for (int i = 'a'; i < 'z'; i++) {
|
||||||
if ((TEST_STRING.indexOf(i) < 0) && (TEST_STRING.indexOf(Character.toUpperCase((char) i)) < 0)) {
|
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 {
|
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
|
// Test all alpha-chars
|
||||||
for (int i = 'a'; i < 'z'; i++) {
|
for (int i = 'a'; i < 'z'; i++) {
|
||||||
if ((TEST_STRING.indexOf(i) < 0) && (TEST_STRING.indexOf(Character.toUpperCase((char) i)) < 0)) {
|
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 {
|
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
|
// Test all alpha-chars
|
||||||
for (int i = 'a'; i < 'z'; i++) {
|
for (int i = 'a'; i < 'z'; i++) {
|
||||||
if ((TEST_STRING.indexOf(i) < 0) && (TEST_STRING.indexOf(Character.toUpperCase((char) i)) < 0)) {
|
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 {
|
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.clear();
|
||||||
cal.set(Calendar.HOUR, 1);
|
cal.set(Calendar.HOUR, 1);
|
||||||
cal.set(Calendar.MINUTE, 2);
|
cal.set(Calendar.MINUTE, 2);
|
||||||
format = new SimpleDateFormat("HH:mm");
|
date = StringUtil.toDate("1:02 am",
|
||||||
date = StringUtil.toDate("1:02", format);
|
DateFormat.getTimeInstance(DateFormat.SHORT, Locale.US));
|
||||||
assertNotNull(date);
|
assertNotNull(date);
|
||||||
assertEquals(cal.getTime(), date);
|
assertEquals(cal.getTime(), date);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,7 +30,7 @@
|
|||||||
|
|
||||||
package com.twelvemonkeys.lang;
|
package com.twelvemonkeys.lang;
|
||||||
|
|
||||||
import org.junit.jupiter.api.Disabled;
|
import org.junit.Ignore;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* SystemUtilTest
|
* SystemUtilTest
|
||||||
@@ -39,6 +39,6 @@ import org.junit.jupiter.api.Disabled;
|
|||||||
* @author last modified by $Author: haraldk$
|
* @author last modified by $Author: haraldk$
|
||||||
* @version $Id: SystemUtilTest.java,v 1.0 11.04.12 16:21 haraldk Exp$
|
* @version $Id: SystemUtilTest.java,v 1.0 11.04.12 16:21 haraldk Exp$
|
||||||
*/
|
*/
|
||||||
@Disabled
|
@Ignore
|
||||||
public class SystemUtilTest {
|
public class SystemUtilTest {
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
+137
-91
@@ -45,11 +45,12 @@
|
|||||||
|
|
||||||
package com.twelvemonkeys.util;
|
package com.twelvemonkeys.util;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
import java.lang.reflect.Array;
|
import java.lang.reflect.Array;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
import static org.junit.Assert.*;
|
||||||
import static org.junit.jupiter.api.Assertions.*;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Abstract test class for {@link java.util.Collection} methods and contracts.
|
* Abstract test class for {@link java.util.Collection} methods and contracts.
|
||||||
@@ -250,8 +251,11 @@ public abstract class CollectionAbstractTest extends ObjectAbstractTest {
|
|||||||
*/
|
*/
|
||||||
public void verifyAll() {
|
public void verifyAll() {
|
||||||
int confirmedSize = confirmed.size();
|
int confirmedSize = confirmed.size();
|
||||||
assertEquals(confirmedSize, collection.size(), "Collection size should match confirmed collection's");
|
assertEquals("Collection size should match confirmed collection's",
|
||||||
assertEquals(confirmed.isEmpty(), collection.isEmpty(), "Collection isEmpty() result 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
|
// verify the collections are the same by attempting to match each
|
||||||
// object in the collection and confirmed collection. To account for
|
// 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]);
|
boolean r = collection.add(elements[i]);
|
||||||
confirmed.add(elements[i]);
|
confirmed.add(elements[i]);
|
||||||
verifyAll();
|
verifyAll();
|
||||||
assertTrue(r, "Empty collection changed after add");
|
assertTrue("Empty collection changed after add", r);
|
||||||
assertEquals(1, collection.size(), "Collection size is 1 after first add");
|
assertEquals("Collection size is 1 after first add", 1, collection.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
resetEmpty();
|
resetEmpty();
|
||||||
@@ -528,8 +532,10 @@ public abstract class CollectionAbstractTest extends ObjectAbstractTest {
|
|||||||
confirmed.add(elements[i]);
|
confirmed.add(elements[i]);
|
||||||
verifyAll();
|
verifyAll();
|
||||||
if (r) size++;
|
if (r) size++;
|
||||||
assertEquals(size, collection.size(), "Collection size should grow after add");
|
assertEquals("Collection size should grow after add",
|
||||||
assertTrue(collection.contains(elements[i]), "Collection should contain added element");
|
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));
|
boolean r = collection.addAll(Arrays.asList(elements));
|
||||||
confirmed.addAll(Arrays.asList(elements));
|
confirmed.addAll(Arrays.asList(elements));
|
||||||
verifyAll();
|
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++) {
|
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();
|
resetFull();
|
||||||
@@ -557,11 +564,13 @@ public abstract class CollectionAbstractTest extends ObjectAbstractTest {
|
|||||||
r = collection.addAll(Arrays.asList(elements));
|
r = collection.addAll(Arrays.asList(elements));
|
||||||
confirmed.addAll(Arrays.asList(elements));
|
confirmed.addAll(Arrays.asList(elements));
|
||||||
verifyAll();
|
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++) {
|
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();
|
resetFull();
|
||||||
size = collection.size();
|
size = collection.size();
|
||||||
@@ -569,9 +578,11 @@ public abstract class CollectionAbstractTest extends ObjectAbstractTest {
|
|||||||
confirmed.addAll(Arrays.asList(getFullElements()));
|
confirmed.addAll(Arrays.asList(getFullElements()));
|
||||||
verifyAll();
|
verifyAll();
|
||||||
if (r) {
|
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 {
|
} 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();
|
resetEmpty();
|
||||||
elements = getFullElements();
|
elements = getFullElements();
|
||||||
for(int i = 0; i < elements.length; i++) {
|
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
|
// make sure calls to "contains" don't change anything
|
||||||
verifyAll();
|
verifyAll();
|
||||||
|
|
||||||
elements = getOtherElements();
|
elements = getOtherElements();
|
||||||
for(int i = 0; i < elements.length; i++) {
|
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
|
// make sure calls to "contains" don't change anything
|
||||||
verifyAll();
|
verifyAll();
|
||||||
@@ -670,7 +683,8 @@ public abstract class CollectionAbstractTest extends ObjectAbstractTest {
|
|||||||
resetFull();
|
resetFull();
|
||||||
elements = getFullElements();
|
elements = getFullElements();
|
||||||
for(int i = 0; i < elements.length; i++) {
|
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
|
// make sure calls to "contains" don't change anything
|
||||||
verifyAll();
|
verifyAll();
|
||||||
@@ -678,7 +692,8 @@ public abstract class CollectionAbstractTest extends ObjectAbstractTest {
|
|||||||
resetFull();
|
resetFull();
|
||||||
elements = getOtherElements();
|
elements = getOtherElements();
|
||||||
for(int i = 0; i < elements.length; i++) {
|
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() {
|
public void testCollectionContainsAll() {
|
||||||
resetEmpty();
|
resetEmpty();
|
||||||
Collection col = new HashSet();
|
Collection col = new HashSet();
|
||||||
assertTrue(collection.containsAll(col),
|
assertTrue("Every Collection should contain all elements of an " +
|
||||||
"Every Collection should contain all elements of an " +
|
"empty Collection.", collection.containsAll(col));
|
||||||
"empty Collection.");
|
|
||||||
col.addAll(Arrays.asList(getOtherElements()));
|
col.addAll(Arrays.asList(getOtherElements()));
|
||||||
assertTrue(!collection.containsAll(col),
|
assertTrue("Empty Collection shouldn't contain all elements of " +
|
||||||
"Empty Collection shouldn't contain all elements of " +
|
"a non-empty Collection.", !collection.containsAll(col));
|
||||||
"a non-empty Collection.");
|
|
||||||
// make sure calls to "containsAll" don't change anything
|
// make sure calls to "containsAll" don't change anything
|
||||||
verifyAll();
|
verifyAll();
|
||||||
|
|
||||||
resetFull();
|
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.clear();
|
||||||
col.addAll(Arrays.asList(getFullElements()));
|
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
|
// make sure calls to "containsAll" don't change anything
|
||||||
verifyAll();
|
verifyAll();
|
||||||
|
|
||||||
@@ -713,17 +728,18 @@ public abstract class CollectionAbstractTest extends ObjectAbstractTest {
|
|||||||
int max = (getFullElements().length == 1 ? 1 :
|
int max = (getFullElements().length == 1 ? 1 :
|
||||||
(getFullElements().length <= 5 ? getFullElements().length - 1 : 5));
|
(getFullElements().length <= 5 ? getFullElements().length - 1 : 5));
|
||||||
col = Arrays.asList(getFullElements()).subList(min, max);
|
col = Arrays.asList(getFullElements()).subList(min, max);
|
||||||
assertTrue(collection.containsAll(col), "Full collection should containAll partial full " +
|
assertTrue("Full collection should containAll partial full " +
|
||||||
"elements");
|
"elements", collection.containsAll(col));
|
||||||
assertTrue(collection.containsAll(collection), "Full collection should containAll itself");
|
assertTrue("Full collection should containAll itself",
|
||||||
|
collection.containsAll(collection));
|
||||||
// make sure calls to "containsAll" don't change anything
|
// make sure calls to "containsAll" don't change anything
|
||||||
verifyAll();
|
verifyAll();
|
||||||
|
|
||||||
col = new ArrayList();
|
col = new ArrayList();
|
||||||
col.addAll(Arrays.asList(getFullElements()));
|
col.addAll(Arrays.asList(getFullElements()));
|
||||||
col.addAll(Arrays.asList(getFullElements()));
|
col.addAll(Arrays.asList(getFullElements()));
|
||||||
assertTrue(collection.containsAll(col), "Full collection should containAll duplicate full " +
|
assertTrue("Full collection should containAll duplicate full " +
|
||||||
"elements");
|
"elements", collection.containsAll(col));
|
||||||
|
|
||||||
// make sure calls to "containsAll" don't change anything
|
// make sure calls to "containsAll" don't change anything
|
||||||
verifyAll();
|
verifyAll();
|
||||||
@@ -735,12 +751,14 @@ public abstract class CollectionAbstractTest extends ObjectAbstractTest {
|
|||||||
@Test
|
@Test
|
||||||
public void testCollectionIsEmpty() {
|
public void testCollectionIsEmpty() {
|
||||||
resetEmpty();
|
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
|
// make sure calls to "isEmpty() don't change anything
|
||||||
verifyAll();
|
verifyAll();
|
||||||
|
|
||||||
resetFull();
|
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
|
// make sure calls to "isEmpty() don't change anything
|
||||||
verifyAll();
|
verifyAll();
|
||||||
}
|
}
|
||||||
@@ -753,7 +771,8 @@ public abstract class CollectionAbstractTest extends ObjectAbstractTest {
|
|||||||
public void testCollectionIterator() {
|
public void testCollectionIterator() {
|
||||||
resetEmpty();
|
resetEmpty();
|
||||||
Iterator it1 = collection.iterator();
|
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 {
|
try {
|
||||||
it1.next();
|
it1.next();
|
||||||
fail("Iterator at end of Collection should throw " +
|
fail("Iterator at end of Collection should throw " +
|
||||||
@@ -767,17 +786,18 @@ public abstract class CollectionAbstractTest extends ObjectAbstractTest {
|
|||||||
resetFull();
|
resetFull();
|
||||||
it1 = collection.iterator();
|
it1 = collection.iterator();
|
||||||
for (int i = 0; i < collection.size(); i++) {
|
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();
|
it1.next();
|
||||||
}
|
}
|
||||||
assertTrue(!it1.hasNext(), "Iterator should be finished");
|
assertTrue("Iterator should be finished", !it1.hasNext());
|
||||||
|
|
||||||
ArrayList list = new ArrayList();
|
ArrayList list = new ArrayList();
|
||||||
it1 = collection.iterator();
|
it1 = collection.iterator();
|
||||||
for (int i = 0; i < collection.size(); i++) {
|
for (int i = 0; i < collection.size(); i++) {
|
||||||
Object next = it1.next();
|
Object next = it1.next();
|
||||||
assertTrue(collection.contains(next), "Collection should contain element returned by " +
|
assertTrue("Collection should contain element returned by " +
|
||||||
"its iterator");
|
"its iterator", collection.contains(next));
|
||||||
list.add(next);
|
list.add(next);
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
@@ -845,10 +865,11 @@ public abstract class CollectionAbstractTest extends ObjectAbstractTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
size--;
|
size--;
|
||||||
assertEquals(size, collection.size(), "Collection should shrink by one after " +
|
assertEquals("Collection should shrink by one after " +
|
||||||
"iterator.remove");
|
"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();
|
resetFull();
|
||||||
iter = collection.iterator();
|
iter = collection.iterator();
|
||||||
@@ -873,7 +894,8 @@ public abstract class CollectionAbstractTest extends ObjectAbstractTest {
|
|||||||
resetEmpty();
|
resetEmpty();
|
||||||
Object[] elements = getFullElements();
|
Object[] elements = getFullElements();
|
||||||
for (int i = 0; i < elements.length; i++) {
|
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();
|
verifyAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -881,14 +903,16 @@ public abstract class CollectionAbstractTest extends ObjectAbstractTest {
|
|||||||
|
|
||||||
resetFull();
|
resetFull();
|
||||||
for (int i = 0; i < other.length; i++) {
|
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();
|
verifyAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
int size = collection.size();
|
int size = collection.size();
|
||||||
for (int i = 0; i < elements.length; i++) {
|
for (int i = 0; i < elements.length; i++) {
|
||||||
resetFull();
|
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
|
// if the elements aren't distinguishable, we can just remove a
|
||||||
// matching element from the confirmed collection and verify
|
// matching element from the confirmed collection and verify
|
||||||
@@ -903,7 +927,8 @@ public abstract class CollectionAbstractTest extends ObjectAbstractTest {
|
|||||||
verifyAll();
|
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;
|
if (!isRemoveSupported()) return;
|
||||||
|
|
||||||
resetEmpty();
|
resetEmpty();
|
||||||
assertTrue(!collection.removeAll(Collections.EMPTY_SET),
|
assertTrue("Emtpy collection removeAll should return false for " +
|
||||||
"Emtpy collection removeAll should return false for " +
|
"empty input",
|
||||||
"empty input");
|
!collection.removeAll(Collections.EMPTY_SET));
|
||||||
verifyAll();
|
verifyAll();
|
||||||
|
|
||||||
assertTrue(!collection.removeAll(new ArrayList(collection)),
|
assertTrue("Emtpy collection removeAll should return false for " +
|
||||||
"Emtpy collection removeAll should return false for " +
|
"nonempty input",
|
||||||
"nonempty input");
|
!collection.removeAll(new ArrayList(collection)));
|
||||||
verifyAll();
|
verifyAll();
|
||||||
|
|
||||||
resetFull();
|
resetFull();
|
||||||
assertTrue(!collection.removeAll(Collections.EMPTY_SET),
|
assertTrue("Full collection removeAll should return false for " +
|
||||||
"Full collection removeAll should return false for " +
|
"empty input",
|
||||||
"empty input");
|
!collection.removeAll(Collections.EMPTY_SET));
|
||||||
verifyAll();
|
verifyAll();
|
||||||
|
|
||||||
assertTrue(!collection.removeAll(Arrays.asList(getOtherElements())),
|
assertTrue("Full collection removeAll should return false for other elements",
|
||||||
"Full collection removeAll should return false for other elements");
|
!collection.removeAll(Arrays.asList(getOtherElements())));
|
||||||
verifyAll();
|
verifyAll();
|
||||||
|
|
||||||
assertTrue(collection.removeAll(new HashSet(collection)),
|
assertTrue("Full collection removeAll should return true for full elements",
|
||||||
"Full collection removeAll should return true for full elements");
|
collection.removeAll(new HashSet(collection)));
|
||||||
confirmed.removeAll(new HashSet(confirmed));
|
confirmed.removeAll(new HashSet(confirmed));
|
||||||
verifyAll();
|
verifyAll();
|
||||||
|
|
||||||
@@ -947,14 +972,17 @@ public abstract class CollectionAbstractTest extends ObjectAbstractTest {
|
|||||||
int max = (getFullElements().length == 1 ? 1 :
|
int max = (getFullElements().length == 1 ? 1 :
|
||||||
(getFullElements().length <= 5 ? getFullElements().length - 1 : 5));
|
(getFullElements().length <= 5 ? getFullElements().length - 1 : 5));
|
||||||
Collection all = Arrays.asList(getFullElements()).subList(min, max);
|
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);
|
confirmed.removeAll(all);
|
||||||
verifyAll();
|
verifyAll();
|
||||||
|
|
||||||
assertTrue(collection.size() < size, "Collection should shrink after removeAll");
|
assertTrue("Collection should shrink after removeAll",
|
||||||
|
collection.size() < size);
|
||||||
Iterator iter = all.iterator();
|
Iterator iter = all.iterator();
|
||||||
while (iter.hasNext()) {
|
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 elements = Arrays.asList(getFullElements());
|
||||||
List other = Arrays.asList(getOtherElements());
|
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();
|
verifyAll();
|
||||||
|
|
||||||
assertTrue(!collection.retainAll(elements), "Empty retainAll() should return false");
|
assertTrue("Empty retainAll() should return false",
|
||||||
|
!collection.retainAll(elements));
|
||||||
verifyAll();
|
verifyAll();
|
||||||
|
|
||||||
resetFull();
|
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);
|
confirmed.retainAll(Collections.EMPTY_SET);
|
||||||
verifyAll();
|
verifyAll();
|
||||||
|
|
||||||
resetFull();
|
resetFull();
|
||||||
assertTrue(collection.retainAll(other), "Collection changed from retainAll other");
|
assertTrue("Collection changed from retainAll other",
|
||||||
|
collection.retainAll(other));
|
||||||
confirmed.retainAll(other);
|
confirmed.retainAll(other);
|
||||||
verifyAll();
|
verifyAll();
|
||||||
|
|
||||||
resetFull();
|
resetFull();
|
||||||
int size = collection.size();
|
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();
|
verifyAll();
|
||||||
assertEquals(size, collection.size(), "Collection size shouldn't change");
|
assertEquals("Collection size shouldn't change", size,
|
||||||
|
collection.size());
|
||||||
|
|
||||||
if (getFullElements().length > 1) {
|
if (getFullElements().length > 1) {
|
||||||
resetFull();
|
resetFull();
|
||||||
size = collection.size();
|
size = collection.size();
|
||||||
int min = (getFullElements().length < 2 ? 0 : 2);
|
int min = (getFullElements().length < 2 ? 0 : 2);
|
||||||
int max = (getFullElements().length <= 5 ? getFullElements().length - 1 : 5);
|
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));
|
confirmed.retainAll(elements.subList(min, max));
|
||||||
verifyAll();
|
verifyAll();
|
||||||
|
|
||||||
Iterator iter = collection.iterator();
|
Iterator iter = collection.iterator();
|
||||||
while (iter.hasNext()) {
|
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();
|
resetFull();
|
||||||
HashSet set = new HashSet(elements);
|
HashSet set = new HashSet(elements);
|
||||||
size = collection.size();
|
size = collection.size();
|
||||||
assertTrue(!collection.retainAll(set),
|
assertTrue("Collection shouldn't change from retainAll without " +
|
||||||
"Collection shouldn't change from retainAll without duplicate elements");
|
"duplicate elements", !collection.retainAll(set));
|
||||||
verifyAll();
|
verifyAll();
|
||||||
assertEquals( size, collection.size(),
|
assertEquals("Collection size didn't change from nonduplicate " +
|
||||||
"Collection size didn't change from nonduplicate retainAll");
|
"retainAll", size, collection.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1024,10 +1060,11 @@ public abstract class CollectionAbstractTest extends ObjectAbstractTest {
|
|||||||
@Test
|
@Test
|
||||||
public void testCollectionSize() {
|
public void testCollectionSize() {
|
||||||
resetEmpty();
|
resetEmpty();
|
||||||
assertEquals(0, collection.size(), "Size of new Collection is 0.");
|
assertEquals("Size of new Collection is 0.", 0, collection.size());
|
||||||
|
|
||||||
resetFull();
|
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() {
|
public void testCollectionToArray() {
|
||||||
resetEmpty();
|
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();
|
resetFull();
|
||||||
Object[] array = collection.toArray();
|
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();
|
Object[] confirmedArray = confirmed.toArray();
|
||||||
assertEquals(confirmedArray.length, array.length,
|
assertEquals("length of array from confirmed collection should " +
|
||||||
"length of array from confirmed collection should match the length of the collection's array");
|
"match the length of the collection's array",
|
||||||
|
confirmedArray.length, array.length);
|
||||||
boolean[] matched = new boolean[array.length];
|
boolean[] matched = new boolean[array.length];
|
||||||
|
|
||||||
for (int i = 0; i < array.length; i++) {
|
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;
|
boolean match = false;
|
||||||
// find a match in the confirmed array
|
// 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++) {
|
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();
|
resetEmpty();
|
||||||
Object[] a = new Object[] { new Object(), null, null };
|
Object[] a = new Object[] { new Object(), null, null };
|
||||||
Object[] array = collection.toArray(a);
|
Object[] array = collection.toArray(a);
|
||||||
assertArrayEquals(array, a, "Given array shouldn't shrink");
|
assertArrayEquals("Given array shouldn't shrink", array, a);
|
||||||
assertNull(a[0], "Last element should be set to null");
|
assertNull("Last element should be set to null", a[0]);
|
||||||
verifyAll();
|
verifyAll();
|
||||||
|
|
||||||
resetFull();
|
resetFull();
|
||||||
@@ -1104,7 +1146,8 @@ public abstract class CollectionAbstractTest extends ObjectAbstractTest {
|
|||||||
|
|
||||||
array = collection.toArray(new Object[0]);
|
array = collection.toArray(new Object[0]);
|
||||||
a = collection.toArray();
|
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
|
// Figure out if they're all the same class
|
||||||
// TODO: It'd be nicer to detect a common superclass
|
// TODO: It'd be nicer to detect a common superclass
|
||||||
@@ -1120,10 +1163,11 @@ public abstract class CollectionAbstractTest extends ObjectAbstractTest {
|
|||||||
}
|
}
|
||||||
a = (Object[])Array.newInstance(cl, 0);
|
a = (Object[])Array.newInstance(cl, 0);
|
||||||
array = collection.toArray(a);
|
array = collection.toArray(a);
|
||||||
assertEquals(a.getClass(), array.getClass(), "toArray(Object[]) should return correct array type");
|
assertEquals("toArray(Object[]) should return correct array type",
|
||||||
assertEquals(Arrays.asList(array),
|
a.getClass(), array.getClass());
|
||||||
Arrays.asList(collection.toArray()),
|
assertEquals("type-specific toArrays should be equal",
|
||||||
"type-specific toArrays should be equal");
|
Arrays.asList(array),
|
||||||
|
Arrays.asList(collection.toArray()));
|
||||||
verifyAll();
|
verifyAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1134,10 +1178,12 @@ public abstract class CollectionAbstractTest extends ObjectAbstractTest {
|
|||||||
@Test
|
@Test
|
||||||
public void testCollectionToString() {
|
public void testCollectionToString() {
|
||||||
resetEmpty();
|
resetEmpty();
|
||||||
assertTrue(collection.toString() != null, "toString shouldn't return null");
|
assertTrue("toString shouldn't return null",
|
||||||
|
collection.toString() != null);
|
||||||
|
|
||||||
resetFull();
|
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;
|
package com.twelvemonkeys.util;
|
||||||
|
|
||||||
|
import org.junit.Ignore;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
import org.junit.jupiter.api.Disabled;
|
import static org.junit.Assert.*;
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
import static org.junit.jupiter.api.Assertions.*;
|
|
||||||
/**
|
/**
|
||||||
* CollectionUtilTest
|
* CollectionUtilTest
|
||||||
*
|
*
|
||||||
@@ -59,60 +61,44 @@ public class CollectionUtilTest {
|
|||||||
assertArrayEquals(new Object[] {"bar", "baz", 3}, merged);
|
assertArrayEquals(new Object[] {"bar", "baz", 3}, merged);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test(expected = IndexOutOfBoundsException.class)
|
||||||
public void testMergeArraysObjectBadOffset() {
|
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() {
|
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() {
|
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() {
|
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() {
|
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() {
|
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() {
|
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() {
|
public void testMergeArraysObjectNegativeSecondLength() {
|
||||||
assertThrows(IndexOutOfBoundsException.class, () -> {
|
CollectionUtil.mergeArrays(stringObjects, 1, 2, integerObjects, 2, -1);
|
||||||
CollectionUtil.mergeArrays(stringObjects, 1, 2, integerObjects, 2, -1);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -123,24 +109,20 @@ public class CollectionUtilTest {
|
|||||||
assertArrayEquals(new Object[] {"foo", "bar", "baz", 1, 2, 3}, merged);
|
assertArrayEquals(new Object[] {"foo", "bar", "baz", 1, 2, 3}, merged);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test(expected = ArrayStoreException.class)
|
||||||
public void testMergeArraysObjectIllegalType() {
|
public void testMergeArraysObjectIllegalType() {
|
||||||
String[] strings = {"foo", "bar", "baz"};
|
String[] strings = {"foo", "bar", "baz"};
|
||||||
Integer[] integers = {1, 2, 3}; // Integer not assignable to String
|
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() {
|
public void testMergeArraysNativeIllegalType() {
|
||||||
char[] chars = {'a', 'b', 'c'};
|
char[] chars = {'a', 'b', 'c'};
|
||||||
int[] integers = {1, 2, 3}; // Integer not assignable to String
|
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);
|
assertArrayEquals(new int[] {2, 3, 4}, numbers);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test(expected = IllegalArgumentException.class)
|
||||||
public void testEnumIteratorNull() {
|
public void testEnumIteratorNull() {
|
||||||
assertThrows(IllegalArgumentException.class, () -> {
|
CollectionUtil.iterator((Enumeration<Object>) null);
|
||||||
CollectionUtil.iterator((Enumeration<Object>) null);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -203,11 +183,9 @@ public class CollectionUtilTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test(expected = IllegalArgumentException.class)
|
||||||
public void testArrayIteratorNull() {
|
public void testArrayIteratorNull() {
|
||||||
assertThrows(IllegalArgumentException.class, () -> {
|
CollectionUtil.iterator((Object[]) null);
|
||||||
CollectionUtil.iterator((Object[]) null);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -284,7 +262,7 @@ public class CollectionUtilTest {
|
|||||||
|
|
||||||
int count = 0;
|
int count = 0;
|
||||||
for (Object element : elements) {
|
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 > 0, iterator.hasPrevious());
|
||||||
assertEquals(count, iterator.nextIndex());
|
assertEquals(count, iterator.nextIndex());
|
||||||
assertEquals(count - 1, iterator.previousIndex());
|
assertEquals(count - 1, iterator.previousIndex());
|
||||||
@@ -340,7 +318,7 @@ public class CollectionUtilTest {
|
|||||||
assertEquals(elements.length, iterator.nextIndex());
|
assertEquals(elements.length, iterator.nextIndex());
|
||||||
|
|
||||||
for (int i = count; i > 0; i--) {
|
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 < elements.length, iterator.hasNext());
|
||||||
assertEquals(i - 1, iterator.previousIndex());
|
assertEquals(i - 1, iterator.previousIndex());
|
||||||
assertEquals(i, iterator.nextIndex());
|
assertEquals(i, iterator.nextIndex());
|
||||||
@@ -361,24 +339,18 @@ public class CollectionUtilTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test(expected = IllegalArgumentException.class)
|
||||||
public void testArrayIteratorRangeNull() {
|
public void testArrayIteratorRangeNull() {
|
||||||
assertThrows(IllegalArgumentException.class, () -> {
|
CollectionUtil.iterator(null, 0, 0);
|
||||||
CollectionUtil.iterator(null, 0, 0);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test(expected = IllegalArgumentException.class)
|
||||||
public void testArrayIteratorRangeBadStart() {
|
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() {
|
public void testArrayIteratorRangeBadLength() {
|
||||||
assertThrows(IllegalArgumentException.class, () -> {
|
CollectionUtil.iterator(stringObjects, 1, stringObjects.length);
|
||||||
CollectionUtil.iterator(stringObjects, 1, stringObjects.length);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -407,11 +379,9 @@ public class CollectionUtilTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test(expected = IllegalArgumentException.class)
|
||||||
public void testReverseOrderNull() {
|
public void testReverseOrderNull() {
|
||||||
assertThrows(IllegalArgumentException.class, () -> {
|
CollectionUtil.reverseOrder(null);
|
||||||
CollectionUtil.reverseOrder(null);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -461,7 +431,7 @@ public class CollectionUtilTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Disabled("For development only")
|
@Ignore("For development only")
|
||||||
@Test
|
@Test
|
||||||
@SuppressWarnings({"UnusedDeclaration"})
|
@SuppressWarnings({"UnusedDeclaration"})
|
||||||
public void testGenerify() {
|
public void testGenerify() {
|
||||||
|
|||||||
@@ -45,10 +45,11 @@
|
|||||||
|
|
||||||
package com.twelvemonkeys.util;
|
package com.twelvemonkeys.util;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
import org.junit.jupiter.api.*;
|
import static org.junit.Assert.assertTrue;
|
||||||
import static org.junit.jupiter.api.Assertions.*;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests LRUMap.
|
* Tests LRUMap.
|
||||||
@@ -80,8 +81,8 @@ public class LRUMapTest extends LinkedMapTest {
|
|||||||
map2.put(4,"foo"); // removes 1 since max size exceeded
|
map2.put(4,"foo"); // removes 1 since max size exceeded
|
||||||
map2.removeLRU(); // should be Integer(2)
|
map2.removeLRU(); // should be Integer(2)
|
||||||
|
|
||||||
assertTrue(map2.get(new Integer(3)).equals("foo"), "Second to last value should exist");
|
assertTrue("Second to last value should exist",map2.get(new Integer(3)).equals("foo"));
|
||||||
assertTrue(map2.get(new Integer(1)) == null, "First value inserted should not exist");
|
assertTrue("First value inserted should not exist", map2.get(new Integer(1)) == null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -92,8 +93,8 @@ public class LRUMapTest extends LinkedMapTest {
|
|||||||
map2.put(3,"foo");
|
map2.put(3,"foo");
|
||||||
map2.put(4,"bar");
|
map2.put(4,"bar");
|
||||||
|
|
||||||
assertTrue(map2.get(new Integer(4)).equals("bar"), "last value should exist");
|
assertTrue("last value should exist",map2.get(new Integer(4)).equals("bar"));
|
||||||
assertTrue(map2.get(new Integer(1)) == null, "LRU should not exist");
|
assertTrue("LRU should not exist", map2.get(new Integer(1)) == null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -112,8 +113,10 @@ public class LRUMapTest extends LinkedMapTest {
|
|||||||
|
|
||||||
map2.putAll(hashMap);
|
map2.putAll(hashMap);
|
||||||
|
|
||||||
assertTrue(map2.size() == 3, "max size is 3, but actual size is " + map2.size());
|
assertTrue("max size is 3, but actual size is " + map2.size(),
|
||||||
assertTrue(map2.containsKey(new Integer(4)), "map should contain the Integer(4) object");
|
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.put("6","6");
|
||||||
map.setMaxSize(3);
|
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
|
@Test
|
||||||
@@ -156,9 +160,9 @@ public class LRUMapTest extends LinkedMapTest {
|
|||||||
keys[i] = keyIterator.next();
|
keys[i] = keyIterator.next();
|
||||||
}
|
}
|
||||||
|
|
||||||
assertTrue(keys[0].equals("3"), "first evicted should be 3, was " + keys[0]);
|
assertTrue("first evicted should be 3, was " + keys[0], keys[0].equals("3"));
|
||||||
assertTrue(keys[1].equals("1"), "second evicted should be 1, was " + keys[1]);
|
assertTrue("second evicted should be 1, was " + keys[1], keys[1].equals("1"));
|
||||||
assertTrue(keys[2].equals("4"), "third evicted should be 4, was " + keys[2]);
|
assertTrue("third evicted should be 4, was " + keys[2], keys[2].equals("4"));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -188,12 +192,13 @@ public class LRUMapTest extends LinkedMapTest {
|
|||||||
// 4 2
|
// 4 2
|
||||||
counter.remove("5");
|
counter.remove("5");
|
||||||
|
|
||||||
assertTrue(counter.size() == 2, "size should be 2, but was " + counter.size());
|
assertTrue("size should be 2, but was " + counter.size(), counter.size() == 2);
|
||||||
assertTrue(counter.removedCount == 3, "removedCount should be 3 but was " + counter.removedCount);
|
assertTrue("removedCount should be 3 but was " + counter.removedCount,
|
||||||
|
counter.removedCount == 3);
|
||||||
|
|
||||||
assertTrue(counter.list.get(0).equals("2"), "first removed was '2'");
|
assertTrue("first removed was '2'",counter.list.get(0).equals("2"));
|
||||||
assertTrue(counter.list.get(1).equals("3"), "second removed was '3'");
|
assertTrue("second removed was '3'",counter.list.get(1).equals("3"));
|
||||||
assertTrue(counter.list.get(2).equals("1"), "third removed was '1'");
|
assertTrue("third removed was '1'",counter.list.get(2).equals("1"));
|
||||||
|
|
||||||
//assertTrue("oldest key is '4'",counter.get(0).equals("4"));
|
//assertTrue("oldest key is '4'",counter.get(0).equals("4"));
|
||||||
//assertTrue("newest key is '2'",counter.get(1).equals("2"));
|
//assertTrue("newest key is '2'",counter.get(1).equals("2"));
|
||||||
|
|||||||
@@ -45,11 +45,15 @@
|
|||||||
|
|
||||||
package com.twelvemonkeys.util;
|
package com.twelvemonkeys.util;
|
||||||
|
|
||||||
|
import org.junit.After;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import org.junit.jupiter.api.*;
|
import static org.junit.Assert.assertEquals;
|
||||||
import static org.junit.jupiter.api.Assertions.*;
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unit tests
|
* Unit tests
|
||||||
@@ -70,7 +74,7 @@ public class LinkedMapTest extends MapAbstractTest {
|
|||||||
*/
|
*/
|
||||||
protected LinkedMap labRat;
|
protected LinkedMap labRat;
|
||||||
|
|
||||||
@BeforeEach
|
@Before
|
||||||
public void setUp() throws Exception {
|
public void setUp() throws Exception {
|
||||||
// use makeMap and cast the result to a SeqHashMap
|
// use makeMap and cast the result to a SeqHashMap
|
||||||
// so that subclasses of SeqHashMap can share these tests
|
// so that subclasses of SeqHashMap can share these tests
|
||||||
@@ -99,21 +103,27 @@ public class LinkedMapTest extends MapAbstractTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Test size().
|
// 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).
|
// Test clone(), iterator(), and get(Object).
|
||||||
LinkedMap clone = (LinkedMap) labRat.clone();
|
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 origEntries = labRat.entrySet().iterator();
|
||||||
Iterator copiedEntries = clone.entrySet().iterator();
|
Iterator copiedEntries = clone.entrySet().iterator();
|
||||||
while (origEntries.hasNext()) {
|
while (origEntries.hasNext()) {
|
||||||
Map.Entry origEntry = (Map.Entry)origEntries.next();
|
Map.Entry origEntry = (Map.Entry)origEntries.next();
|
||||||
Map.Entry copiedEntry = (Map.Entry)copiedEntries.next();
|
Map.Entry copiedEntry = (Map.Entry)copiedEntries.next();
|
||||||
assertEquals(origEntry.getKey(), copiedEntry.getKey(), "Cloned key does not match original");
|
assertEquals("Cloned key does not match original",
|
||||||
assertEquals(origEntry.getValue(), copiedEntry.getValue(), "Cloned value does not match original");
|
origEntry.getKey(), copiedEntry.getKey());
|
||||||
assertEquals(origEntry, copiedEntry, "Cloned entry does not match original");
|
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()
|
// Test sequence()
|
||||||
/*
|
/*
|
||||||
@@ -197,7 +207,7 @@ public class LinkedMapTest extends MapAbstractTest {
|
|||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@AfterEach
|
@After
|
||||||
public void tearDown() throws Exception {
|
public void tearDown() throws Exception {
|
||||||
labRat = null;
|
labRat = null;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,10 +45,12 @@
|
|||||||
|
|
||||||
package com.twelvemonkeys.util;
|
package com.twelvemonkeys.util;
|
||||||
|
|
||||||
|
import org.junit.After;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
import org.junit.jupiter.api.*;
|
import static org.junit.Assert.*;
|
||||||
import static org.junit.jupiter.api.Assertions.*;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Abstract test class for {@link java.util.Map} methods and contracts.
|
* 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]);
|
m.put(keys[i], values[i]);
|
||||||
}
|
}
|
||||||
catch (NullPointerException exception) {
|
catch (NullPointerException exception) {
|
||||||
assertTrue(keys[i] == null || values[i] == null,
|
assertTrue("NullPointerException only allowed to be thrown if either the key or value is null.",
|
||||||
"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(),
|
assertTrue("NullPointerException on null key, but isAllowNullKey is not overridden to return false.",
|
||||||
"NullPointerException on null key, but isAllowNullKey is not overridden to return false.");
|
keys[i] == null || !isAllowNullKey());
|
||||||
|
|
||||||
assertTrue(values[i] == null || !isAllowNullValue(),
|
assertTrue("NullPointerException on null value, but isAllowNullValue is not overridden to return false.",
|
||||||
"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[] values = getSampleValues();
|
||||||
Object[] newValues = getNewSampleValues();
|
Object[] newValues = getNewSampleValues();
|
||||||
|
|
||||||
assertTrue(keys != null, "failure in test: Must have keys returned from getSampleKeys.");
|
assertTrue("failure in test: Must have keys returned from getSampleKeys.", keys != null);
|
||||||
assertTrue(values != null, "failure in test: Must have values returned from getSampleValues.");
|
assertTrue("failure in test: Must have values returned from getSampleValues.", values != null);
|
||||||
|
|
||||||
// verify keys and values have equivalent lengths (in case getSampleX are
|
// verify keys and values have equivalent lengths (in case getSampleX are
|
||||||
// overridden)
|
// overridden)
|
||||||
assertEquals(keys.length, values.length, "failure in test: not the same number of sample keys and values.");
|
assertEquals("failure in test: not the same number of sample keys and values.", keys.length, values.length);
|
||||||
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 values and new values.", values.length, newValues.length);
|
||||||
|
|
||||||
// verify there aren't duplicate keys, and check values
|
// verify there aren't duplicate keys, and check values
|
||||||
for (int i = 0; i < keys.length - 1; i++) {
|
for (int i = 0; i < keys.length - 1; i++) {
|
||||||
for (int j = i + 1; j < keys.length; j++) {
|
for (int j = i + 1; j < keys.length; j++) {
|
||||||
assertTrue((keys[i] != null || keys[j] != null), "failure in test: duplicate null keys.");
|
assertTrue("failure in test: duplicate null keys.", (keys[i] != null || keys[j] != null));
|
||||||
assertTrue((keys[i] == null || keys[j] == null || (!keys[i].equals(keys[j]) && !keys[j].equals(keys[i]))),
|
assertTrue("failure in test: duplicate non-null key.",
|
||||||
"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("failure in test: found null key, but isNullKeySupported is false.", keys[i] != null || isAllowNullKey());
|
||||||
assertTrue(values[i] != null || isAllowNullValue(),"failure in test: found null value, but isNullValueSupported is false.");
|
assertTrue("failure in test: found null value, but isNullValueSupported is false.", values[i] != null || isAllowNullValue());
|
||||||
assertTrue(newValues[i] != null || isAllowNullValue(), "failure in test: found null new value, but isNullValueSupported is false.");
|
assertTrue("failure in test: found null new value, but isNullValueSupported is false.", newValues[i] != null || isAllowNullValue());
|
||||||
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: 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
|
@Test
|
||||||
public void testMakeMap() {
|
public void testMakeMap() {
|
||||||
Map em = makeEmptyMap();
|
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();
|
Map em2 = makeEmptyMap();
|
||||||
assertTrue(em2 != null, "failure in test: makeEmptyMap must return a non-null map.");
|
assertTrue("failure in test: makeEmptyMap must return a non-null map.", em2 != null);
|
||||||
assertTrue(em != em2, "failure in test: makeEmptyMap must return a new map with each invocation.");
|
assertTrue("failure in test: makeEmptyMap must return a new map with each invocation.", em != em2);
|
||||||
|
|
||||||
Map fm = makeFullMap();
|
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();
|
Map fm2 = makeFullMap();
|
||||||
assertTrue(fm2 != null, "failure in test: makeFullMap must return a non-null map.");
|
assertTrue("failure in test: makeFullMap must return a non-null map.", fm2 != null);
|
||||||
assertTrue(fm != fm2, "failure in test: makeFullMap must return a new map with each invocation.");
|
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
|
@Test
|
||||||
public void testMapIsEmpty() {
|
public void testMapIsEmpty() {
|
||||||
resetEmpty();
|
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();
|
verifyAll();
|
||||||
|
|
||||||
resetFull();
|
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();
|
verifyAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -548,11 +551,11 @@ public abstract class MapAbstractTest extends ObjectAbstractTest {
|
|||||||
@Test
|
@Test
|
||||||
public void testMapSize() {
|
public void testMapSize() {
|
||||||
resetEmpty();
|
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();
|
verifyAll();
|
||||||
|
|
||||||
resetFull();
|
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();
|
verifyAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -599,13 +602,13 @@ public abstract class MapAbstractTest extends ObjectAbstractTest {
|
|||||||
|
|
||||||
resetEmpty();
|
resetEmpty();
|
||||||
for (Object key : keys) {
|
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();
|
verifyAll();
|
||||||
|
|
||||||
resetFull();
|
resetFull();
|
||||||
for (Object key : keys) {
|
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();
|
verifyAll();
|
||||||
}
|
}
|
||||||
@@ -621,13 +624,13 @@ public abstract class MapAbstractTest extends ObjectAbstractTest {
|
|||||||
|
|
||||||
resetEmpty();
|
resetEmpty();
|
||||||
for (Object value : values) {
|
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();
|
verifyAll();
|
||||||
|
|
||||||
resetFull();
|
resetFull();
|
||||||
for (Object value : values) {
|
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();
|
verifyAll();
|
||||||
}
|
}
|
||||||
@@ -638,11 +641,11 @@ public abstract class MapAbstractTest extends ObjectAbstractTest {
|
|||||||
@Test
|
@Test
|
||||||
public void testMapEquals() {
|
public void testMapEquals() {
|
||||||
resetEmpty();
|
resetEmpty();
|
||||||
assertTrue(map.equals(confirmed), "Empty maps unequal.");
|
assertTrue("Empty maps unequal.", map.equals(confirmed));
|
||||||
verifyAll();
|
verifyAll();
|
||||||
|
|
||||||
resetFull();
|
resetFull();
|
||||||
assertTrue(map.equals(confirmed), "Full maps unequal.");
|
assertTrue("Full maps unequal.", map.equals(confirmed));
|
||||||
verifyAll();
|
verifyAll();
|
||||||
|
|
||||||
resetFull();
|
resetFull();
|
||||||
@@ -651,11 +654,11 @@ public abstract class MapAbstractTest extends ObjectAbstractTest {
|
|||||||
Iterator iter = confirmed.keySet().iterator();
|
Iterator iter = confirmed.keySet().iterator();
|
||||||
iter.next();
|
iter.next();
|
||||||
iter.remove();
|
iter.remove();
|
||||||
assertTrue(!map.equals(confirmed), "Different maps equal.");
|
assertTrue("Different maps equal.", !map.equals(confirmed));
|
||||||
|
|
||||||
resetFull();
|
resetFull();
|
||||||
assertTrue(!map.equals(null), "equals(null) returned true.");
|
assertTrue("equals(null) returned true.", !map.equals(null));
|
||||||
assertTrue(!map.equals(new Object()), "equals(new Object()) returned true.");
|
assertTrue("equals(new Object()) returned true.", !map.equals(new Object()));
|
||||||
verifyAll();
|
verifyAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -670,14 +673,14 @@ public abstract class MapAbstractTest extends ObjectAbstractTest {
|
|||||||
Object[] values = getSampleValues();
|
Object[] values = getSampleValues();
|
||||||
|
|
||||||
for (Object key : keys) {
|
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();
|
verifyAll();
|
||||||
|
|
||||||
resetFull();
|
resetFull();
|
||||||
for (int i = 0; i < keys.length; i++) {
|
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
|
@Test
|
||||||
public void testMapHashCode() {
|
public void testMapHashCode() {
|
||||||
resetEmpty();
|
resetEmpty();
|
||||||
assertTrue(map.hashCode() == confirmed.hashCode(), "Empty maps have different hashCodes.");
|
assertTrue("Empty maps have different hashCodes.", map.hashCode() == confirmed.hashCode());
|
||||||
|
|
||||||
resetFull();
|
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
|
@Test
|
||||||
public void testMapToString() {
|
public void testMapToString() {
|
||||||
resetEmpty();
|
resetEmpty();
|
||||||
assertTrue(map.toString() != null, "Empty map toString() should not return null");
|
assertTrue("Empty map toString() should not return null", map.toString() != null);
|
||||||
verifyAll();
|
verifyAll();
|
||||||
|
|
||||||
resetFull();
|
resetFull();
|
||||||
assertTrue(map.toString() != null, "Empty map toString() should not return null");
|
assertTrue("Empty map toString() should not return null", map.toString() != null);
|
||||||
verifyAll();
|
verifyAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -773,23 +776,29 @@ public abstract class MapAbstractTest extends ObjectAbstractTest {
|
|||||||
Object o = map.put(keys[i], values[i]);
|
Object o = map.put(keys[i], values[i]);
|
||||||
confirmed.put(keys[i], values[i]);
|
confirmed.put(keys[i], values[i]);
|
||||||
verifyAll();
|
verifyAll();
|
||||||
assertTrue(o == null, "First map.put should return null");
|
assertTrue("First map.put should return null", o == null);
|
||||||
assertTrue(map.containsKey(keys[i]), "Map should contain key after put");
|
assertTrue("Map should contain key after put",
|
||||||
assertTrue(map.containsValue(values[i]), "Map should contain value after put");
|
map.containsKey(keys[i]));
|
||||||
|
assertTrue("Map should contain value after put",
|
||||||
|
map.containsValue(values[i]));
|
||||||
}
|
}
|
||||||
if (isPutChangeSupported()) {
|
if (isPutChangeSupported()) {
|
||||||
for (int i = 0; i < keys.length; i++) {
|
for (int i = 0; i < keys.length; i++) {
|
||||||
Object o = map.put(keys[i], newValues[i]);
|
Object o = map.put(keys[i], newValues[i]);
|
||||||
confirmed.put(keys[i], newValues[i]);
|
confirmed.put(keys[i], newValues[i]);
|
||||||
verifyAll();
|
verifyAll();
|
||||||
assertEquals(values[i], o, "Map.put should return previous value when changed");
|
assertEquals("Map.put should return previous value when changed",
|
||||||
assertTrue(map.containsKey(keys[i]), "Map should still contain key after put when changed");
|
values[i], o);
|
||||||
assertTrue(map.containsValue(newValues[i]), "Map should contain new value after put when changed");
|
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
|
// if duplicates are allowed, we're not guaranteed that the value
|
||||||
// no longer exists, so don't try checking that.
|
// no longer exists, so don't try checking that.
|
||||||
if (!isAllowDuplicateValues()) {
|
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 o = map.put(key, newValues[i]);
|
||||||
Object value = confirmed.put(key, newValues[i]);
|
Object value = confirmed.put(key, newValues[i]);
|
||||||
verifyAll();
|
verifyAll();
|
||||||
assertEquals(value, o, "Map.put should return previous value when changed");
|
assertEquals("Map.put should return previous value when changed",
|
||||||
assertTrue(map.containsKey(key), "Map should still contain key after put when changed");
|
value, o);
|
||||||
assertTrue(map.containsValue(newValues[i]), "Map should contain new value after put when changed");
|
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
|
// if duplicates are allowed, we're not guaranteed that the value
|
||||||
// no longer exists, so don't try checking that.
|
// no longer exists, so don't try checking that.
|
||||||
if (!isAllowDuplicateValues()) {
|
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();
|
Object[] values = getSampleValues();
|
||||||
for (int i = 0; i < keys.length; i++) {
|
for (int i = 0; i < keys.length; i++) {
|
||||||
Object o = map.remove(keys[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();
|
verifyAll();
|
||||||
|
|
||||||
@@ -968,7 +981,8 @@ public abstract class MapAbstractTest extends ObjectAbstractTest {
|
|||||||
confirmed.remove(keys[i]);
|
confirmed.remove(keys[i]);
|
||||||
verifyAll();
|
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();
|
Object[] other = getOtherKeys();
|
||||||
@@ -977,8 +991,10 @@ public abstract class MapAbstractTest extends ObjectAbstractTest {
|
|||||||
int size = map.size();
|
int size = map.size();
|
||||||
for (int i = 0; i < other.length; i++) {
|
for (int i = 0; i < other.length; i++) {
|
||||||
Object o = map.remove(other[i]);
|
Object o = map.remove(other[i]);
|
||||||
assertEquals(o, null, "map.remove for nonexistent key should return null");
|
assertEquals("map.remove for nonexistent key should return null",
|
||||||
assertEquals(size, map.size(), "map.remove for nonexistent key should not shrink map");
|
o, null);
|
||||||
|
assertEquals("map.remove for nonexistent key should not " +
|
||||||
|
"shrink map", size, map.size());
|
||||||
}
|
}
|
||||||
verifyAll();
|
verifyAll();
|
||||||
}
|
}
|
||||||
@@ -1188,9 +1204,10 @@ public abstract class MapAbstractTest extends ObjectAbstractTest {
|
|||||||
}
|
}
|
||||||
j++;
|
j++;
|
||||||
}
|
}
|
||||||
assertTrue(j < 10000, "values().remove(obj) is broken");
|
assertTrue("values().remove(obj) is broken", j < 10000);
|
||||||
assertTrue(!map.containsValue(sampleValues[i]),
|
assertTrue(
|
||||||
"Value should have been removed from the underlying map.");
|
"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
|
// if key.remove is unsupported, just skip this test
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
assertTrue(!map.containsKey(sampleKeys[i]),
|
assertTrue(
|
||||||
"Key should have been removed from the underlying map.");
|
"Key should have been removed from the underlying map.",
|
||||||
|
!map.containsKey(sampleKeys[i]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1395,7 +1413,7 @@ public abstract class MapAbstractTest extends ObjectAbstractTest {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
assertNotNull(entry, "No matching entry in map for key '" + key + "'");
|
assertNotNull("No matching entry in map for key '" + key + "'", entry);
|
||||||
return entry;
|
return entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1620,14 +1638,14 @@ public abstract class MapAbstractTest extends ObjectAbstractTest {
|
|||||||
public void verifyMap() {
|
public void verifyMap() {
|
||||||
int size = confirmed.size();
|
int size = confirmed.size();
|
||||||
boolean empty = confirmed.isEmpty();
|
boolean empty = confirmed.isEmpty();
|
||||||
assertEquals(size, map.size(), "Map should be same size as HashMap");
|
assertEquals("Map should be same size as HashMap", size, map.size());
|
||||||
assertEquals(empty, map.isEmpty(), "Map should be empty if HashMap is");
|
assertEquals("Map should be empty if HashMap is", empty, map.isEmpty());
|
||||||
assertEquals(confirmed.hashCode(), map.hashCode(), "hashCodes should be the same");
|
assertEquals("hashCodes should be the same", confirmed.hashCode(), map.hashCode());
|
||||||
// this fails for LRUMap because confirmed.equals() somehow modifies
|
// this fails for LRUMap because confirmed.equals() somehow modifies
|
||||||
// map, causing concurrent modification exceptions.
|
// map, causing concurrent modification exceptions.
|
||||||
//assertEquals("Map should still equal HashMap", confirmed, map);
|
//assertEquals("Map should still equal HashMap", confirmed, map);
|
||||||
// this works though and performs the same verification:
|
// 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
|
// TODO: this should really be reexamined to figure out why LRU map
|
||||||
// behaves like it does (the equals shouldn't modify since all accesses
|
// behaves like it does (the equals shouldn't modify since all accesses
|
||||||
// by the confirmed collection should be through an iterator, thus not
|
// by the confirmed collection should be through an iterator, thus not
|
||||||
@@ -1637,29 +1655,29 @@ public abstract class MapAbstractTest extends ObjectAbstractTest {
|
|||||||
public void verifyEntrySet() {
|
public void verifyEntrySet() {
|
||||||
int size = confirmed.size();
|
int size = confirmed.size();
|
||||||
boolean empty = confirmed.isEmpty();
|
boolean empty = confirmed.isEmpty();
|
||||||
assertEquals(size, entrySet.size(),
|
assertEquals("entrySet should be same size as HashMap's\nTest: " + entrySet + "\nReal: " + confirmed.entrySet(),
|
||||||
"entrySet should be same size as HashMap's\nTest: " + entrySet + "\nReal: " + confirmed.entrySet());
|
size, entrySet.size());
|
||||||
assertEquals(empty, entrySet.isEmpty(),
|
assertEquals("entrySet should be empty if HashMap is\nTest: " + entrySet + "\nReal: " + confirmed.entrySet(),
|
||||||
"entrySet should be empty if HashMap is\nTest: " + entrySet + "\nReal: " + confirmed.entrySet());
|
empty, entrySet.isEmpty());
|
||||||
assertTrue(entrySet.containsAll(confirmed.entrySet()),
|
assertTrue("entrySet should contain all HashMap's elements\nTest: " + entrySet + "\nReal: " + confirmed.entrySet(),
|
||||||
"entrySet should contain all HashMap's elements\nTest: " + entrySet + "\nReal: " + confirmed.entrySet());
|
entrySet.containsAll(confirmed.entrySet()));
|
||||||
assertEquals(confirmed.entrySet().hashCode(), entrySet.hashCode(),
|
assertEquals("entrySet hashCodes should be the same\nTest: " + entrySet + "\nReal: " + confirmed.entrySet(),
|
||||||
"entrySet hashCodes should be the same\nTest: " + entrySet + "\nReal: " + confirmed.entrySet());
|
confirmed.entrySet().hashCode(), entrySet.hashCode());
|
||||||
assertEquals(confirmed.entrySet(), entrySet,"Map's entry set should still equal HashMap's");
|
assertEquals("Map's entry set should still equal HashMap's", confirmed.entrySet(), entrySet);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void verifyKeySet() {
|
public void verifyKeySet() {
|
||||||
int size = confirmed.size();
|
int size = confirmed.size();
|
||||||
boolean empty = confirmed.isEmpty();
|
boolean empty = confirmed.isEmpty();
|
||||||
assertEquals(size, keySet.size(),
|
assertEquals("keySet should be same size as HashMap's\nTest: " + keySet + "\nReal: " + confirmed.keySet(),
|
||||||
"keySet should be same size as HashMap's\nTest: " + keySet + "\nReal: " + confirmed.keySet());
|
size, keySet.size());
|
||||||
assertEquals(empty, keySet.isEmpty(),
|
assertEquals("keySet should be empty if HashMap is\nTest: " + keySet + "\nReal: " + confirmed.keySet(),
|
||||||
"keySet should be empty if HashMap is\nTest: " + keySet + "\nReal: " + confirmed.keySet());
|
empty, keySet.isEmpty());
|
||||||
assertTrue(keySet.containsAll(confirmed.keySet()),
|
assertTrue("keySet should contain all HashMap's elements\nTest: " + keySet + "\nReal: " + confirmed.keySet(),
|
||||||
"keySet should contain all HashMap's elements\nTest: " + keySet + "\nReal: " + confirmed.keySet());
|
keySet.containsAll(confirmed.keySet()));
|
||||||
assertEquals(confirmed.keySet().hashCode(), keySet.hashCode(),
|
assertEquals("keySet hashCodes should be the same\nTest: " + keySet + "\nReal: " + confirmed.keySet(),
|
||||||
"keySet hashCodes should be the same\nTest: " + keySet + "\nReal: " + confirmed.keySet());
|
confirmed.keySet().hashCode(), keySet.hashCode());
|
||||||
assertEquals(confirmed.keySet(), keySet, "Map's key set should still equal HashMap's");
|
assertEquals("Map's key set should still equal HashMap's", confirmed.keySet(), keySet);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void verifyValues() {
|
public void verifyValues() {
|
||||||
@@ -1669,23 +1687,23 @@ public abstract class MapAbstractTest extends ObjectAbstractTest {
|
|||||||
int size = confirmed.size();
|
int size = confirmed.size();
|
||||||
boolean empty = confirmed.isEmpty();
|
boolean empty = confirmed.isEmpty();
|
||||||
|
|
||||||
assertEquals(size, values.size(), "values should be same size as HashMap's\nTest: " + test + "\nReal: " + known);
|
assertEquals("values should be same size as HashMap's\nTest: " + test + "\nReal: " + known, size, values.size());
|
||||||
assertEquals(empty, values.isEmpty(), "values should be empty if HashMap is\nTest: " + test + "\nReal: " + known);
|
assertEquals("values should be empty if HashMap is\nTest: " + test + "\nReal: " + known, empty, values.isEmpty());
|
||||||
assertTrue(test.containsAll(known), "values should contain all HashMap's elements\nTest: " + test + "\nReal: " + known);
|
assertTrue("values should contain all HashMap's elements\nTest: " + test + "\nReal: " + known, test.containsAll(known));
|
||||||
assertTrue(known.containsAll(test), "values should contain all HashMap's elements\nTest: " + test + "\nReal: " + known);
|
assertTrue("values should contain all HashMap's elements\nTest: " + test + "\nReal: " + known, known.containsAll(test));
|
||||||
|
|
||||||
for (Object aKnown : known) {
|
for (Object aKnown : known) {
|
||||||
boolean removed = test.remove(aKnown);
|
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.
|
* Erases any leftover instance variables by setting them to null.
|
||||||
*/
|
*/
|
||||||
@AfterEach
|
@After
|
||||||
public void tearDown() throws Exception {
|
public void tearDown() throws Exception {
|
||||||
map = null;
|
map = null;
|
||||||
keySet = null;
|
keySet = null;
|
||||||
|
|||||||
@@ -30,11 +30,13 @@
|
|||||||
|
|
||||||
package com.twelvemonkeys.util;
|
package com.twelvemonkeys.util;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import org.junit.jupiter.api.*;
|
import static org.junit.Assert.assertEquals;
|
||||||
import static org.junit.jupiter.api.Assertions.*;
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* NOTE: This TestCase is written especially for NullMap, and is full of dirty
|
* NOTE: This TestCase is written especially for NullMap, and is full of dirty
|
||||||
@@ -81,12 +83,12 @@ public class NullMapTest extends MapAbstractTest {
|
|||||||
@Override
|
@Override
|
||||||
public void testMapIsEmpty() {
|
public void testMapIsEmpty() {
|
||||||
resetEmpty();
|
resetEmpty();
|
||||||
assertEquals(true, map.isEmpty(),
|
assertEquals("Map.isEmpty() should return true with an empty map",
|
||||||
"Map.isEmpty() should return true with an empty map");
|
true, map.isEmpty());
|
||||||
verifyAll();
|
verifyAll();
|
||||||
resetFull();
|
resetFull();
|
||||||
assertEquals(true, map.isEmpty(),
|
assertEquals("Map.isEmpty() should return true with a full map",
|
||||||
"Map.isEmpty() should return true with a full map");
|
true, map.isEmpty());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Overriden, as this map is always empty
|
// Overriden, as this map is always empty
|
||||||
@@ -94,13 +96,13 @@ public class NullMapTest extends MapAbstractTest {
|
|||||||
@Override
|
@Override
|
||||||
public void testMapSize() {
|
public void testMapSize() {
|
||||||
resetEmpty();
|
resetEmpty();
|
||||||
assertEquals(0, map.size(),
|
assertEquals("Map.size() should be 0 with an empty map",
|
||||||
"Map.size() should be 0 with an empty map");
|
0, map.size());
|
||||||
verifyAll();
|
verifyAll();
|
||||||
|
|
||||||
resetFull();
|
resetFull();
|
||||||
assertEquals(0, map.size(),
|
assertEquals("Map.size() should equal the number of entries " +
|
||||||
"Map.size() should equal the number of entries in the map");
|
"in the map", 0, map.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -110,7 +112,7 @@ public class NullMapTest extends MapAbstractTest {
|
|||||||
|
|
||||||
resetEmpty();
|
resetEmpty();
|
||||||
for (Object key : keys) {
|
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();
|
verifyAll();
|
||||||
}
|
}
|
||||||
@@ -122,7 +124,7 @@ public class NullMapTest extends MapAbstractTest {
|
|||||||
|
|
||||||
resetEmpty();
|
resetEmpty();
|
||||||
for (Object value : values) {
|
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();
|
verifyAll();
|
||||||
}
|
}
|
||||||
@@ -131,7 +133,7 @@ public class NullMapTest extends MapAbstractTest {
|
|||||||
@Override
|
@Override
|
||||||
public void testMapEquals() {
|
public void testMapEquals() {
|
||||||
resetEmpty();
|
resetEmpty();
|
||||||
assertTrue(map.equals(confirmed), "Empty maps unequal.");
|
assertTrue("Empty maps unequal.", map.equals(confirmed));
|
||||||
verifyAll();
|
verifyAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -139,7 +141,8 @@ public class NullMapTest extends MapAbstractTest {
|
|||||||
@Override
|
@Override
|
||||||
public void testMapHashCode() {
|
public void testMapHashCode() {
|
||||||
resetEmpty();
|
resetEmpty();
|
||||||
assertTrue(map.hashCode() == confirmed.hashCode(), "Empty maps have different hashCodes.");
|
assertTrue("Empty maps have different hashCodes.",
|
||||||
|
map.hashCode() == confirmed.hashCode());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -150,7 +153,7 @@ public class NullMapTest extends MapAbstractTest {
|
|||||||
Object[] keys = getSampleKeys();
|
Object[] keys = getSampleKeys();
|
||||||
|
|
||||||
for (Object key : keys) {
|
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();
|
verifyAll();
|
||||||
}
|
}
|
||||||
@@ -167,7 +170,7 @@ public class NullMapTest extends MapAbstractTest {
|
|||||||
Object o = map.put(keys[i], values[i]);
|
Object o = map.put(keys[i], values[i]);
|
||||||
//confirmed.put(keys[i], values[i]);
|
//confirmed.put(keys[i], values[i]);
|
||||||
verifyAll();
|
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++) {
|
for (int i = 0; i < keys.length; i++) {
|
||||||
map.put(keys[i], newValues[i]);
|
map.put(keys[i], newValues[i]);
|
||||||
@@ -180,8 +183,8 @@ public class NullMapTest extends MapAbstractTest {
|
|||||||
@Override
|
@Override
|
||||||
public void testMapToString() {
|
public void testMapToString() {
|
||||||
resetEmpty();
|
resetEmpty();
|
||||||
assertTrue(map.toString() != null,
|
assertTrue("Empty map toString() should not return null",
|
||||||
"Empty map toString() should not return null");
|
map.toString() != null);
|
||||||
verifyAll();
|
verifyAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -199,7 +202,7 @@ public class NullMapTest extends MapAbstractTest {
|
|||||||
Object[] keys = getSampleKeys();
|
Object[] keys = getSampleKeys();
|
||||||
for(int i = 0; i < keys.length; i++) {
|
for(int i = 0; i < keys.length; i++) {
|
||||||
Object o = map.remove(keys[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();
|
verifyAll();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -44,10 +44,12 @@
|
|||||||
*/
|
*/
|
||||||
package com.twelvemonkeys.util;
|
package com.twelvemonkeys.util;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
|
|
||||||
import org.junit.jupiter.api.*;
|
import static org.junit.Assert.assertEquals;
|
||||||
import static org.junit.jupiter.api.Assertions.*;
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Abstract test class for {@link Object} methods and contracts.
|
* Abstract test class for {@link Object} methods and contracts.
|
||||||
@@ -117,7 +119,7 @@ public abstract class ObjectAbstractTest {
|
|||||||
@Test
|
@Test
|
||||||
public void testObjectEqualsSelf() {
|
public void testObjectEqualsSelf() {
|
||||||
Object obj = makeObject();
|
Object obj = makeObject();
|
||||||
assertEquals(obj, obj, "A Object should equal itself");
|
assertEquals("A Object should equal itself", obj, obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -129,24 +131,25 @@ public abstract class ObjectAbstractTest {
|
|||||||
@Test
|
@Test
|
||||||
public void testObjectHashCodeEqualsSelfHashCode() {
|
public void testObjectHashCodeEqualsSelfHashCode() {
|
||||||
Object obj = makeObject();
|
Object obj = makeObject();
|
||||||
assertEquals(obj.hashCode(), obj.hashCode(), "hashCode should be repeatable");
|
assertEquals("hashCode should be repeatable", obj.hashCode(), obj.hashCode());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testObjectHashCodeEqualsContract() {
|
public void testObjectHashCodeEqualsContract() {
|
||||||
Object obj1 = makeObject();
|
Object obj1 = makeObject();
|
||||||
if (obj1.equals(obj1)) {
|
if (obj1.equals(obj1)) {
|
||||||
assertEquals(obj1.hashCode(), obj1.hashCode(),
|
assertEquals(
|
||||||
"[1] When two objects are equal, their hashCodes should be also.");
|
"[1] When two objects are equal, their hashCodes should be also.",
|
||||||
|
obj1.hashCode(), obj1.hashCode());
|
||||||
}
|
}
|
||||||
Object obj2 = makeObject();
|
Object obj2 = makeObject();
|
||||||
if (obj1.equals(obj2)) {
|
if (obj1.equals(obj2)) {
|
||||||
assertEquals(
|
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(
|
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();
|
Object dest = in.readObject();
|
||||||
in.close();
|
in.close();
|
||||||
if (isEqualsCheckable()) {
|
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) {
|
if (object instanceof Serializable) {
|
||||||
String name = getCanonicalEmptyCollectionName(object);
|
String name = getCanonicalEmptyCollectionName(object);
|
||||||
assertTrue(
|
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) {
|
if (object instanceof Serializable) {
|
||||||
String name = getCanonicalFullCollectionName(object);
|
String name = getCanonicalFullCollectionName(object);
|
||||||
assertTrue(
|
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;
|
package com.twelvemonkeys.util;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
import org.junit.jupiter.api.*;
|
import static org.junit.Assert.assertEquals;
|
||||||
import static org.junit.jupiter.api.Assertions.*;
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Abstract test class for {@link Set} methods and contracts.
|
* Abstract test class for {@link Set} methods and contracts.
|
||||||
@@ -77,12 +79,14 @@ public abstract class SetAbstractTest extends CollectionAbstractTest {
|
|||||||
public void verifyAll() {
|
public void verifyAll() {
|
||||||
super.verifyAll();
|
super.verifyAll();
|
||||||
|
|
||||||
assertEquals(confirmed, collection, "Sets should be equal");
|
assertEquals("Sets should be equal", confirmed, collection);
|
||||||
assertEquals(confirmed.hashCode(), collection.hashCode(), "Sets should have equal hashCodes");
|
assertEquals("Sets should have equal hashCodes",
|
||||||
|
confirmed.hashCode(), collection.hashCode());
|
||||||
Collection set = makeConfirmedCollection();
|
Collection set = makeConfirmedCollection();
|
||||||
Iterator iterator = collection.iterator();
|
Iterator iterator = collection.iterator();
|
||||||
while (iterator.hasNext()) {
|
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
|
@Test
|
||||||
public void testSetEquals() {
|
public void testSetEquals() {
|
||||||
resetEmpty();
|
resetEmpty();
|
||||||
assertEquals(getSet(), getConfirmedSet(), "Empty sets should be equal");
|
assertEquals("Empty sets should be equal",
|
||||||
|
getSet(), getConfirmedSet());
|
||||||
verifyAll();
|
verifyAll();
|
||||||
|
|
||||||
Collection set2 = makeConfirmedCollection();
|
Collection set2 = makeConfirmedCollection();
|
||||||
set2.add("foo");
|
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();
|
resetFull();
|
||||||
assertEquals(getSet(), getConfirmedSet(), "Full sets should be equal");
|
assertEquals("Full sets should be equal", getSet(), getConfirmedSet());
|
||||||
verifyAll();
|
verifyAll();
|
||||||
|
|
||||||
set2.clear();
|
set2.clear();
|
||||||
set2.addAll(Arrays.asList(getOtherElements()));
|
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
|
@Test
|
||||||
public void testSetHashCode() {
|
public void testSetHashCode() {
|
||||||
resetEmpty();
|
resetEmpty();
|
||||||
assertEquals(getSet().hashCode(), getConfirmedSet().hashCode(), "Empty sets have equal hashCodes");
|
assertEquals("Empty sets have equal hashCodes",
|
||||||
|
getSet().hashCode(), getConfirmedSet().hashCode());
|
||||||
|
|
||||||
resetFull();
|
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;
|
package com.twelvemonkeys.util;
|
||||||
|
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
|
||||||
import org.junit.jupiter.api.*;
|
import static org.junit.Assert.*;
|
||||||
import static org.junit.jupiter.api.Assertions.*;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* StringTokenIteratorTestCase
|
* StringTokenIteratorTestCase
|
||||||
@@ -54,88 +56,88 @@ public class StringTokenIteratorTest extends TokenIteratorAbstractTest {
|
|||||||
@Test
|
@Test
|
||||||
public void testEmptyDelimiter() {
|
public void testEmptyDelimiter() {
|
||||||
Iterator iterator = createTokenIterator("", "");
|
Iterator iterator = createTokenIterator("", "");
|
||||||
assertFalse(iterator.hasNext(), "Empty string has elements");
|
assertFalse("Empty string has elements", iterator.hasNext());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSingleToken() {
|
public void testSingleToken() {
|
||||||
Iterator iterator = createTokenIterator("A");
|
Iterator iterator = createTokenIterator("A");
|
||||||
assertTrue(iterator.hasNext(), "String has no elements");
|
assertTrue("String has no elements", iterator.hasNext());
|
||||||
assertEquals("A", iterator.next());
|
assertEquals("A", iterator.next());
|
||||||
assertFalse(iterator.hasNext(), "String has more than one element");
|
assertFalse("String has more than one element", iterator.hasNext());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSingleTokenEmptyDelimiter() {
|
public void testSingleTokenEmptyDelimiter() {
|
||||||
Iterator iterator = createTokenIterator("A", "");
|
Iterator iterator = createTokenIterator("A", "");
|
||||||
assertTrue(iterator.hasNext(), "String has no elements");
|
assertTrue("String has no elements", iterator.hasNext());
|
||||||
assertEquals("A", iterator.next());
|
assertEquals("A", iterator.next());
|
||||||
assertFalse(iterator.hasNext(), "String has more than one element");
|
assertFalse("String has more than one element", iterator.hasNext());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSingleTokenSingleDelimiter() {
|
public void testSingleTokenSingleDelimiter() {
|
||||||
Iterator iterator = createTokenIterator("A", ",");
|
Iterator iterator = createTokenIterator("A", ",");
|
||||||
assertTrue(iterator.hasNext(), "String has no elements");
|
assertTrue("String has no elements", iterator.hasNext());
|
||||||
assertEquals("A", iterator.next());
|
assertEquals("A", iterator.next());
|
||||||
assertFalse(iterator.hasNext(), "String has more than one element");
|
assertFalse("String has more than one element", iterator.hasNext());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSingleSeparatorDefaultDelimiter() {
|
public void testSingleSeparatorDefaultDelimiter() {
|
||||||
Iterator iterator = createTokenIterator("A B C D");
|
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());
|
assertEquals("A", iterator.next());
|
||||||
assertTrue(iterator.hasNext(), "String has no elements");
|
assertTrue("String has no elements", iterator.hasNext());
|
||||||
assertEquals("B", iterator.next());
|
assertEquals("B", iterator.next());
|
||||||
assertTrue(iterator.hasNext(), "String has no elements");
|
assertTrue("String has no elements", iterator.hasNext());
|
||||||
assertEquals("C", iterator.next());
|
assertEquals("C", iterator.next());
|
||||||
assertTrue(iterator.hasNext(), "String has no elements");
|
assertTrue("String has no elements", iterator.hasNext());
|
||||||
assertEquals("D", iterator.next());
|
assertEquals("D", iterator.next());
|
||||||
assertFalse(iterator.hasNext(), "String has more than one element");
|
assertFalse("String has more than one element", iterator.hasNext());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSingleSeparator() {
|
public void testSingleSeparator() {
|
||||||
Iterator iterator = createTokenIterator("A,B,C", ",");
|
Iterator iterator = createTokenIterator("A,B,C", ",");
|
||||||
assertTrue(iterator.hasNext(), "String has no elements");
|
assertTrue("String has no elements", iterator.hasNext());
|
||||||
assertEquals("A", iterator.next());
|
assertEquals("A", iterator.next());
|
||||||
assertTrue(iterator.hasNext(), "String has no elements");
|
assertTrue("String has no elements", iterator.hasNext());
|
||||||
assertEquals("B", iterator.next());
|
assertEquals("B", iterator.next());
|
||||||
assertTrue(iterator.hasNext(), "String has no elements");
|
assertTrue("String has no elements", iterator.hasNext());
|
||||||
assertEquals("C", iterator.next());
|
assertEquals("C", iterator.next());
|
||||||
assertFalse(iterator.hasNext(), "String has more than one element");
|
assertFalse("String has more than one element", iterator.hasNext());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testMultipleSeparatorDefaultDelimiter() {
|
public void testMultipleSeparatorDefaultDelimiter() {
|
||||||
Iterator iterator = createTokenIterator("A B C\nD\t\t \nE");
|
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());
|
assertEquals("A", iterator.next());
|
||||||
assertTrue(iterator.hasNext(), "String has no elements");
|
assertTrue("String has no elements", iterator.hasNext());
|
||||||
assertEquals("B", iterator.next());
|
assertEquals("B", iterator.next());
|
||||||
assertTrue(iterator.hasNext(), "String has no elements");
|
assertTrue("String has no elements", iterator.hasNext());
|
||||||
assertEquals("C", iterator.next());
|
assertEquals("C", iterator.next());
|
||||||
assertTrue(iterator.hasNext(), "String has no elements");
|
assertTrue("String has no elements", iterator.hasNext());
|
||||||
assertEquals("D", iterator.next());
|
assertEquals("D", iterator.next());
|
||||||
assertTrue(iterator.hasNext(), "String has no elements");
|
assertTrue("String has no elements", iterator.hasNext());
|
||||||
assertEquals("E", iterator.next());
|
assertEquals("E", iterator.next());
|
||||||
assertFalse(iterator.hasNext(), "String has more than one element");
|
assertFalse("String has more than one element", iterator.hasNext());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testMultipleSeparator() {
|
public void testMultipleSeparator() {
|
||||||
Iterator iterator = createTokenIterator("A,B,;,C...D, ., ,E", " ,.;:");
|
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());
|
assertEquals("A", iterator.next());
|
||||||
assertTrue(iterator.hasNext(), "String has no elements");
|
assertTrue("String has no elements", iterator.hasNext());
|
||||||
assertEquals("B", iterator.next());
|
assertEquals("B", iterator.next());
|
||||||
assertTrue(iterator.hasNext(), "String has no elements");
|
assertTrue("String has no elements", iterator.hasNext());
|
||||||
assertEquals("C", iterator.next());
|
assertEquals("C", iterator.next());
|
||||||
assertTrue(iterator.hasNext(), "String has no elements");
|
assertTrue("String has no elements", iterator.hasNext());
|
||||||
assertEquals("D", iterator.next());
|
assertEquals("D", iterator.next());
|
||||||
assertTrue(iterator.hasNext(), "String has no elements");
|
assertTrue("String has no elements", iterator.hasNext());
|
||||||
assertEquals("E", iterator.next());
|
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;
|
package com.twelvemonkeys.util;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
import org.junit.jupiter.api.*;
|
import static org.junit.Assert.*;
|
||||||
import static org.junit.jupiter.api.Assertions.*;
|
|
||||||
/**
|
/**
|
||||||
* TimeoutMapTest
|
* TimeoutMapTest
|
||||||
* <p/>
|
* <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);
|
//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);
|
//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);
|
//assertEquals("Elements did not expire as expected.", 1, count);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -628,7 +630,7 @@ public class TimeoutMapTest extends MapAbstractTest {
|
|||||||
Object removedKey = null;
|
Object removedKey = null;
|
||||||
Object otherKey = null;
|
Object otherKey = null;
|
||||||
Iterator iterator = map.entrySet().iterator();
|
Iterator iterator = map.entrySet().iterator();
|
||||||
assertTrue(iterator.hasNext(), "Iterator was empty");
|
assertTrue("Iterator was empty", iterator.hasNext());
|
||||||
try {
|
try {
|
||||||
Map.Entry entry = (Map.Entry) iterator.next();
|
Map.Entry entry = (Map.Entry) iterator.next();
|
||||||
assertNotNull(entry);
|
assertNotNull(entry);
|
||||||
@@ -646,8 +648,8 @@ public class TimeoutMapTest extends MapAbstractTest {
|
|||||||
fail("Elements expired between Interator.hasNext() and Iterator.remove()");
|
fail("Elements expired between Interator.hasNext() and Iterator.remove()");
|
||||||
}
|
}
|
||||||
|
|
||||||
assertTrue(!map.containsKey(removedKey), "Wrong entry removed, keySet().iterator() is broken.");
|
assertTrue("Wrong entry removed, keySet().iterator() is broken.", !map.containsKey(removedKey));
|
||||||
assertTrue(map.containsKey(otherKey), "Wrong entry removed, keySet().iterator() is broken.");
|
assertTrue("Wrong entry removed, keySet().iterator() is broken.", map.containsKey(otherKey));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+5
-3
@@ -30,10 +30,12 @@
|
|||||||
|
|
||||||
package com.twelvemonkeys.util;
|
package com.twelvemonkeys.util;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
|
||||||
import org.junit.jupiter.api.*;
|
import static org.junit.Assert.assertFalse;
|
||||||
import static org.junit.jupiter.api.Assertions.*;
|
import static org.junit.Assert.fail;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TokenIteratorAbstractTestCase
|
* TokenIteratorAbstractTestCase
|
||||||
@@ -78,7 +80,7 @@ public abstract class TokenIteratorAbstractTest {
|
|||||||
@Test
|
@Test
|
||||||
public void testEmptyString() {
|
public void testEmptyString() {
|
||||||
Iterator iterator = createTokenIterator("");
|
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;
|
package com.twelvemonkeys.util.convert;
|
||||||
|
|
||||||
import org.junit.jupiter.api.Disabled;
|
import org.junit.Ignore;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ConverterTest
|
* ConverterTest
|
||||||
@@ -43,7 +43,7 @@ import org.junit.jupiter.api.Test;
|
|||||||
*/
|
*/
|
||||||
public class ConverterTest {
|
public class ConverterTest {
|
||||||
|
|
||||||
@Disabled("Not implemented")
|
@Ignore("Not implemented")
|
||||||
@Test
|
@Test
|
||||||
public void testMe() {
|
public void testMe() {
|
||||||
// TODO: Implement tests
|
// TODO: Implement tests
|
||||||
|
|||||||
+1
-1
@@ -31,7 +31,7 @@
|
|||||||
package com.twelvemonkeys.util.convert;
|
package com.twelvemonkeys.util.convert;
|
||||||
|
|
||||||
import com.twelvemonkeys.lang.DateUtil;
|
import com.twelvemonkeys.lang.DateUtil;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import java.text.DateFormat;
|
import java.text.DateFormat;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|||||||
+4
-4
@@ -31,13 +31,13 @@
|
|||||||
package com.twelvemonkeys.util.convert;
|
package com.twelvemonkeys.util.convert;
|
||||||
|
|
||||||
import com.twelvemonkeys.lang.Validate;
|
import com.twelvemonkeys.lang.Validate;
|
||||||
|
import org.junit.Ignore;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
|
|
||||||
import org.junit.jupiter.api.Disabled;
|
import static org.junit.Assert.*;
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
import static org.junit.jupiter.api.Assertions.*;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* DefaultConverterTest
|
* DefaultConverterTest
|
||||||
@@ -138,7 +138,7 @@ public class DefaultConverterTest extends PropertyConverterAbstractTest {
|
|||||||
assertEquals(-2.3456, (Double) converter.toObject("-2.3456", Double.TYPE, null), 0);
|
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
|
@Test
|
||||||
public void testConvertCharPrimitive() {
|
public void testConvertCharPrimitive() {
|
||||||
PropertyConverter converter = makePropertyConverter();
|
PropertyConverter converter = makePropertyConverter();
|
||||||
|
|||||||
+16
-16
@@ -32,11 +32,11 @@ package com.twelvemonkeys.util.convert;
|
|||||||
|
|
||||||
import com.twelvemonkeys.lang.ObjectAbstractTest;
|
import com.twelvemonkeys.lang.ObjectAbstractTest;
|
||||||
import com.twelvemonkeys.lang.Validate;
|
import com.twelvemonkeys.lang.Validate;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
import static org.junit.Assert.*;
|
||||||
import static org.junit.jupiter.api.Assertions.*;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* PropertyConverterAbstractTest
|
* PropertyConverterAbstractTest
|
||||||
@@ -66,26 +66,26 @@ public abstract class PropertyConverterAbstractTest extends ObjectAbstractTest {
|
|||||||
try {
|
try {
|
||||||
obj = converter.toObject(test.original(), test.type(), test.format());
|
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()) {
|
if (test.type().isArray()) {
|
||||||
assertArrayEquals0(String.format("'%s' not converted", test.original()), test.value(), obj);
|
assertArrayEquals0(String.format("'%s' not converted", test.original()), test.value(), obj);
|
||||||
}
|
}
|
||||||
else {
|
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());
|
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());
|
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()) {
|
if (test.type().isArray()) {
|
||||||
assertArrayEquals0(String.format("'%s' did not survive round trip conversion", test.original()), test.value(), obj);
|
assertArrayEquals0(String.format("'%s' did not survive round trip conversion", test.original()), test.value(), obj);
|
||||||
}
|
}
|
||||||
else {
|
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) {
|
catch (ConversionException e) {
|
||||||
@@ -98,35 +98,35 @@ public abstract class PropertyConverterAbstractTest extends ObjectAbstractTest {
|
|||||||
Class<?> componentType = left.getClass().getComponentType();
|
Class<?> componentType = left.getClass().getComponentType();
|
||||||
if (componentType.isPrimitive()) {
|
if (componentType.isPrimitive()) {
|
||||||
if (int.class == componentType) {
|
if (int.class == componentType) {
|
||||||
assertArrayEquals((int[]) left, (int[]) right, message);
|
assertArrayEquals(message, (int[]) left, (int[]) right);
|
||||||
}
|
}
|
||||||
else if (short.class == componentType) {
|
else if (short.class == componentType) {
|
||||||
assertArrayEquals((short[]) left, (short[]) right, message);
|
assertArrayEquals(message, (short[]) left, (short[]) right);
|
||||||
}
|
}
|
||||||
else if (long.class == componentType) {
|
else if (long.class == componentType) {
|
||||||
assertArrayEquals((long[]) left, (long[]) right, message);
|
assertArrayEquals(message, (long[]) left, (long[]) right);
|
||||||
}
|
}
|
||||||
else if (float.class == componentType) {
|
else if (float.class == componentType) {
|
||||||
assertArrayEquals((float[]) left, (float[]) right, 0f, message);
|
assertArrayEquals(message, (float[]) left, (float[]) right, 0f);
|
||||||
}
|
}
|
||||||
else if (double.class == componentType) {
|
else if (double.class == componentType) {
|
||||||
assertArrayEquals((double[]) left, (double[]) right, 0d, message);
|
assertArrayEquals(message, (double[]) left, (double[]) right, 0d);
|
||||||
}
|
}
|
||||||
else if (boolean.class == componentType) {
|
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) {
|
else if (byte.class == componentType) {
|
||||||
assertArrayEquals((byte[]) left, (byte[]) right, message);
|
assertArrayEquals(message, (byte[]) left, (byte[]) right);
|
||||||
}
|
}
|
||||||
else if (char.class == componentType) {
|
else if (char.class == componentType) {
|
||||||
assertArrayEquals((char[]) left, (char[]) right, message);
|
assertArrayEquals(message, (char[]) left, (char[]) right);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
fail(String.format("Unknown primitive type: %s", componentType));
|
fail(String.format("Unknown primitive type: %s", componentType));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
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.TokenIterator;
|
||||||
import com.twelvemonkeys.util.TokenIteratorAbstractTest;
|
import com.twelvemonkeys.util.TokenIteratorAbstractTest;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
import static org.junit.Assert.*;
|
||||||
import static org.junit.jupiter.api.Assertions.*;
|
|
||||||
/**
|
/**
|
||||||
* StringTokenIteratorTestCase
|
* StringTokenIteratorTestCase
|
||||||
* <p/>
|
* <p/>
|
||||||
@@ -67,9 +68,9 @@ public class RegExTokenIteratorTest extends TokenIteratorAbstractTest {
|
|||||||
@Test
|
@Test
|
||||||
public void testSingleToken() {
|
public void testSingleToken() {
|
||||||
Iterator iterator = createTokenIterator("A");
|
Iterator iterator = createTokenIterator("A");
|
||||||
assertTrue(iterator.hasNext(), "String has no elements");
|
assertTrue("String has no elements", iterator.hasNext());
|
||||||
assertEquals("A", iterator.next());
|
assertEquals("A", iterator.next());
|
||||||
assertFalse(iterator.hasNext(), "String has more than one element");
|
assertFalse("String has more than one element", iterator.hasNext());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -86,67 +87,67 @@ public class RegExTokenIteratorTest extends TokenIteratorAbstractTest {
|
|||||||
@Test
|
@Test
|
||||||
public void testSingleTokenSingleDelimiter() {
|
public void testSingleTokenSingleDelimiter() {
|
||||||
Iterator iterator = createTokenIterator("A", "[^,]+");
|
Iterator iterator = createTokenIterator("A", "[^,]+");
|
||||||
assertTrue(iterator.hasNext(), "String has no elements");
|
assertTrue("String has no elements", iterator.hasNext());
|
||||||
assertEquals("A", iterator.next());
|
assertEquals("A", iterator.next());
|
||||||
assertFalse(iterator.hasNext(), "String has more than one element");
|
assertFalse("String has more than one element", iterator.hasNext());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSingleSeparatorDefaultDelimiter() {
|
public void testSingleSeparatorDefaultDelimiter() {
|
||||||
Iterator iterator = createTokenIterator("A B C D");
|
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());
|
assertEquals("A", iterator.next());
|
||||||
assertTrue(iterator.hasNext(), "String has no elements");
|
assertTrue("String has no elements", iterator.hasNext());
|
||||||
assertEquals("B", iterator.next());
|
assertEquals("B", iterator.next());
|
||||||
assertTrue(iterator.hasNext(), "String has no elements");
|
assertTrue("String has no elements", iterator.hasNext());
|
||||||
assertEquals("C", iterator.next());
|
assertEquals("C", iterator.next());
|
||||||
assertTrue(iterator.hasNext(), "String has no elements");
|
assertTrue("String has no elements", iterator.hasNext());
|
||||||
assertEquals("D", iterator.next());
|
assertEquals("D", iterator.next());
|
||||||
assertFalse(iterator.hasNext(), "String has more than one element");
|
assertFalse("String has more than one element", iterator.hasNext());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSingleSeparator() {
|
public void testSingleSeparator() {
|
||||||
Iterator iterator = createTokenIterator("A,B,C", "[^,]+");
|
Iterator iterator = createTokenIterator("A,B,C", "[^,]+");
|
||||||
assertTrue(iterator.hasNext(), "String has no elements");
|
assertTrue("String has no elements", iterator.hasNext());
|
||||||
assertEquals("A", iterator.next());
|
assertEquals("A", iterator.next());
|
||||||
assertTrue(iterator.hasNext(), "String has no elements");
|
assertTrue("String has no elements", iterator.hasNext());
|
||||||
assertEquals("B", iterator.next());
|
assertEquals("B", iterator.next());
|
||||||
assertTrue(iterator.hasNext(), "String has no elements");
|
assertTrue("String has no elements", iterator.hasNext());
|
||||||
assertEquals("C", iterator.next());
|
assertEquals("C", iterator.next());
|
||||||
assertFalse(iterator.hasNext(), "String has more than one element");
|
assertFalse("String has more than one element", iterator.hasNext());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testMultipleSeparatorDefaultDelimiter() {
|
public void testMultipleSeparatorDefaultDelimiter() {
|
||||||
Iterator iterator = createTokenIterator("A B C\nD\t\t \nE");
|
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());
|
assertEquals("A", iterator.next());
|
||||||
assertTrue(iterator.hasNext(), "String has no elements");
|
assertTrue("String has no elements", iterator.hasNext());
|
||||||
assertEquals("B", iterator.next());
|
assertEquals("B", iterator.next());
|
||||||
assertTrue(iterator.hasNext(), "String has no elements");
|
assertTrue("String has no elements", iterator.hasNext());
|
||||||
assertEquals("C", iterator.next());
|
assertEquals("C", iterator.next());
|
||||||
assertTrue(iterator.hasNext(), "String has no elements");
|
assertTrue("String has no elements", iterator.hasNext());
|
||||||
assertEquals("D", iterator.next());
|
assertEquals("D", iterator.next());
|
||||||
assertTrue(iterator.hasNext(), "String has no elements");
|
assertTrue("String has no elements", iterator.hasNext());
|
||||||
assertEquals("E", iterator.next());
|
assertEquals("E", iterator.next());
|
||||||
assertFalse(iterator.hasNext(), "String has more than one element");
|
assertFalse("String has more than one element", iterator.hasNext());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testMultipleSeparator() {
|
public void testMultipleSeparator() {
|
||||||
Iterator iterator = createTokenIterator("A,B,;,C...D, ., ,E", "[^ ,.;:]+");
|
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();
|
Object o = iterator.next();
|
||||||
assertEquals("A", o);
|
assertEquals("A", o);
|
||||||
assertTrue(iterator.hasNext(), "String has no elements");
|
assertTrue("String has no elements", iterator.hasNext());
|
||||||
assertEquals("B", iterator.next());
|
assertEquals("B", iterator.next());
|
||||||
assertTrue(iterator.hasNext(), "String has no elements");
|
assertTrue("String has no elements", iterator.hasNext());
|
||||||
assertEquals("C", iterator.next());
|
assertEquals("C", iterator.next());
|
||||||
assertTrue(iterator.hasNext(), "String has no elements");
|
assertTrue("String has no elements", iterator.hasNext());
|
||||||
assertEquals("D", iterator.next());
|
assertEquals("D", iterator.next());
|
||||||
assertTrue(iterator.hasNext(), "String has no elements");
|
assertTrue("String has no elements", iterator.hasNext());
|
||||||
assertEquals("E", iterator.next());
|
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;
|
package com.twelvemonkeys.util.service;
|
||||||
|
|
||||||
import com.twelvemonkeys.lang.Validate;
|
|
||||||
import com.twelvemonkeys.util.CollectionUtil;
|
import com.twelvemonkeys.util.CollectionUtil;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
import static org.junit.Assert.*;
|
||||||
import static org.junit.jupiter.api.Assertions.*;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ServiceRegistryTest
|
* ServiceRegistryTest
|
||||||
@@ -49,11 +48,9 @@ public class ServiceRegistryTest {
|
|||||||
|
|
||||||
private final TestRegistry registry = new TestRegistry();
|
private final TestRegistry registry = new TestRegistry();
|
||||||
|
|
||||||
@Test
|
@Test(expected = IllegalArgumentException.class)
|
||||||
public void testCreateNull() {
|
public void testCreateNull() {
|
||||||
assertThrows(IllegalArgumentException.class, () -> {
|
new ServiceRegistry(null);
|
||||||
new ServiceRegistry(null);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -67,12 +64,11 @@ public class ServiceRegistryTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test(expected = ServiceConfigurationError.class)
|
||||||
public void testCreateBadConfig() {
|
public void testCreateBadConfig() {
|
||||||
assertThrows(ServiceConfigurationError.class, () -> {
|
@SuppressWarnings("unchecked")
|
||||||
ServiceRegistry registry = new ServiceRegistry(Arrays.asList(BadSPI.class).iterator());
|
ServiceRegistry registry = new ServiceRegistry(Arrays.asList(BadSPI.class).iterator());
|
||||||
registry.registerApplicationClasspathSPIs();
|
registry.registerApplicationClasspathSPIs();
|
||||||
});
|
|
||||||
|
|
||||||
// DONE: Test non-class
|
// DONE: Test non-class
|
||||||
|
|
||||||
|
|||||||
+4
-15
@@ -4,7 +4,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>com.twelvemonkeys</groupId>
|
<groupId>com.twelvemonkeys</groupId>
|
||||||
<artifactId>twelvemonkeys</artifactId>
|
<artifactId>twelvemonkeys</artifactId>
|
||||||
<version>3.12.1-SNAPSHOT</version>
|
<version>3.7.1</version>
|
||||||
</parent>
|
</parent>
|
||||||
<groupId>com.twelvemonkeys.common</groupId>
|
<groupId>com.twelvemonkeys.common</groupId>
|
||||||
<artifactId>common</artifactId>
|
<artifactId>common</artifactId>
|
||||||
@@ -20,10 +20,6 @@
|
|||||||
<module>common-image</module>
|
<module>common-image</module>
|
||||||
</modules>
|
</modules>
|
||||||
|
|
||||||
<properties>
|
|
||||||
<junit.jupiter.version>5.13.0</junit.jupiter.version>
|
|
||||||
</properties>
|
|
||||||
|
|
||||||
<dependencyManagement>
|
<dependencyManagement>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<dependency>
|
<dependency>
|
||||||
@@ -47,18 +43,11 @@
|
|||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
</dependencyManagement>
|
</dependencyManagement>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.junit.jupiter</groupId>
|
<groupId>junit</groupId>
|
||||||
<artifactId>junit-jupiter-api</artifactId>
|
<artifactId>junit</artifactId>
|
||||||
<version>${junit.jupiter.version}</version>
|
<version>4.13.1</version>
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.junit.jupiter</groupId>
|
|
||||||
<artifactId>junit-jupiter-params</artifactId>
|
|
||||||
<version>${junit.jupiter.version}</version>
|
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|||||||
+6
-25
@@ -4,20 +4,15 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>com.twelvemonkeys</groupId>
|
<groupId>com.twelvemonkeys</groupId>
|
||||||
<artifactId>twelvemonkeys</artifactId>
|
<artifactId>twelvemonkeys</artifactId>
|
||||||
<version>3.12.1-SNAPSHOT</version>
|
<version>3.7.1</version>
|
||||||
</parent>
|
</parent>
|
||||||
<groupId>com.twelvemonkeys.contrib</groupId>
|
<groupId>com.twelvemonkeys.contrib</groupId>
|
||||||
<artifactId>contrib</artifactId>
|
<artifactId>contrib</artifactId>
|
||||||
<name>TwelveMonkeys :: Contrib</name>
|
<name>TwelveMonkeys :: Contrib</name>
|
||||||
<description>
|
<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>
|
</description>
|
||||||
|
|
||||||
<properties>
|
|
||||||
<junit.jupiter.version>5.13.0</junit.jupiter.version>
|
|
||||||
</properties>
|
|
||||||
|
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.twelvemonkeys.common</groupId>
|
<groupId>com.twelvemonkeys.common</groupId>
|
||||||
@@ -66,26 +61,12 @@
|
|||||||
<type>test-jar</type>
|
<type>test-jar</type>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.junit.jupiter</groupId>
|
<groupId>junit</groupId>
|
||||||
<artifactId>junit-jupiter-engine</artifactId>
|
<artifactId>junit</artifactId>
|
||||||
<version>${junit.jupiter.version}</version>
|
<version>4.13.1</version>
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.junit.jupiter</groupId>
|
|
||||||
<artifactId>junit-jupiter-api</artifactId>
|
|
||||||
<version>${junit.jupiter.version}</version>
|
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
|
||||||
<plugins>
|
|
||||||
<plugin>
|
|
||||||
<groupId>org.apache.felix</groupId>
|
|
||||||
<artifactId>maven-bundle-plugin</artifactId>
|
|
||||||
</plugin>
|
|
||||||
</plugins>
|
|
||||||
</build>
|
|
||||||
</project>
|
</project>
|
||||||
|
|||||||
@@ -30,14 +30,9 @@ import static com.twelvemonkeys.contrib.tiff.TIFFUtilities.applyOrientation;
|
|||||||
public class EXIFUtilities {
|
public class EXIFUtilities {
|
||||||
/**
|
/**
|
||||||
* Reads image and metadata, applies Exif orientation to image, and returns everything as an {@code IIOImage}.
|
* Reads image and metadata, applies Exif orientation to image, and returns everything as an {@code IIOImage}.
|
||||||
* The returned {@code IIOImage} will always contain an image and no raster, and
|
|
||||||
* the {@code RenderedImage} may be safely cast to a {@code BufferedImage}.
|
|
||||||
*
|
|
||||||
* If no registered {@code ImageReader} claims to be able to read the input, {@code null} is returned.
|
|
||||||
*
|
*
|
||||||
* @param input a {@code URL}
|
* @param input a {@code URL}
|
||||||
* @return an {@code IIOImage} containing the correctly oriented image and metadata including rotation info, or
|
* @return an {@code IIOImage} containing the correctly oriented image and metadata including rotation info.
|
||||||
* {@code null}.
|
|
||||||
* @throws IOException if an error occurs during reading.
|
* @throws IOException if an error occurs during reading.
|
||||||
*/
|
*/
|
||||||
public static IIOImage readWithOrientation(final URL input) throws IOException {
|
public static IIOImage readWithOrientation(final URL input) throws IOException {
|
||||||
@@ -48,14 +43,9 @@ public class EXIFUtilities {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Reads image and metadata, applies Exif orientation to image, and returns everything as an {@code IIOImage}.
|
* Reads image and metadata, applies Exif orientation to image, and returns everything as an {@code IIOImage}.
|
||||||
* The returned {@code IIOImage} will always contain an image and no raster, and
|
|
||||||
* the {@code RenderedImage} may be safely cast to a {@code BufferedImage}.
|
|
||||||
*
|
|
||||||
* If no registered {@code ImageReader} claims to be able to read the input, {@code null} is returned.
|
|
||||||
*
|
*
|
||||||
* @param input an {@code InputStream}
|
* @param input an {@code InputStream}
|
||||||
* @return an {@code IIOImage} containing the correctly oriented image and metadata including rotation info, or
|
* @return an {@code IIOImage} containing the correctly oriented image and metadata including rotation info.
|
||||||
* {@code null}.
|
|
||||||
* @throws IOException if an error occurs during reading.
|
* @throws IOException if an error occurs during reading.
|
||||||
*/
|
*/
|
||||||
public static IIOImage readWithOrientation(final InputStream input) throws IOException {
|
public static IIOImage readWithOrientation(final InputStream input) throws IOException {
|
||||||
@@ -66,14 +56,9 @@ public class EXIFUtilities {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Reads image and metadata, applies Exif orientation to image, and returns everything as an {@code IIOImage}.
|
* Reads image and metadata, applies Exif orientation to image, and returns everything as an {@code IIOImage}.
|
||||||
* The returned {@code IIOImage} will always contain an image and no raster, and
|
|
||||||
* the {@code RenderedImage} may be safely cast to a {@code BufferedImage}.
|
|
||||||
*
|
|
||||||
* If no registered {@code ImageReader} claims to be able to read the input, {@code null} is returned.
|
|
||||||
*
|
*
|
||||||
* @param input a {@code File}
|
* @param input a {@code File}
|
||||||
* @return an {@code IIOImage} containing the correctly oriented image and metadata including rotation info or
|
* @return an {@code IIOImage} containing the correctly oriented image and metadata including rotation info.
|
||||||
* {@code null}.
|
|
||||||
* @throws IOException if an error occurs during reading.
|
* @throws IOException if an error occurs during reading.
|
||||||
*/
|
*/
|
||||||
public static IIOImage readWithOrientation(final File input) throws IOException {
|
public static IIOImage readWithOrientation(final File input) throws IOException {
|
||||||
@@ -84,14 +69,9 @@ public class EXIFUtilities {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Reads image and metadata, applies Exif orientation to image, and returns everything as an {@code IIOImage}.
|
* Reads image and metadata, applies Exif orientation to image, and returns everything as an {@code IIOImage}.
|
||||||
* The returned {@code IIOImage} will always contain an image and no raster, and
|
|
||||||
* the {@code RenderedImage} may be safely cast to a {@code BufferedImage}.
|
|
||||||
*
|
|
||||||
* If no registered {@code ImageReader} claims to be able to read the input, {@code null} is returned.
|
|
||||||
*
|
*
|
||||||
* @param input an {@code ImageInputStream}
|
* @param input an {@code ImageInputStream}
|
||||||
* @return an {@code IIOImage} containing the correctly oriented image and metadata including rotation info, or
|
* @return an {@code IIOImage} containing the correctly oriented image and metadata including rotation info.
|
||||||
* {@code null}.
|
|
||||||
* @throws IOException if an error occurs during reading.
|
* @throws IOException if an error occurs during reading.
|
||||||
*/
|
*/
|
||||||
public static IIOImage readWithOrientation(final ImageInputStream input) throws IOException {
|
public static IIOImage readWithOrientation(final ImageInputStream input) throws IOException {
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
package com.twelvemonkeys.contrib.exif;
|
package com.twelvemonkeys.contrib.exif;
|
||||||
|
|
||||||
import static com.twelvemonkeys.contrib.exif.Orientation.*;
|
import org.junit.Test;
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
import static com.twelvemonkeys.contrib.exif.Orientation.*;
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* OrientationTest.
|
* OrientationTest.
|
||||||
|
|||||||
@@ -34,6 +34,8 @@ import com.twelvemonkeys.contrib.tiff.TIFFUtilities.TIFFExtension;
|
|||||||
import com.twelvemonkeys.imageio.plugins.tiff.TIFFImageMetadataFormat;
|
import com.twelvemonkeys.imageio.plugins.tiff.TIFFImageMetadataFormat;
|
||||||
import com.twelvemonkeys.io.FileUtil;
|
import com.twelvemonkeys.io.FileUtil;
|
||||||
|
|
||||||
|
import org.junit.Assert;
|
||||||
|
import org.junit.Test;
|
||||||
import org.w3c.dom.Node;
|
import org.w3c.dom.Node;
|
||||||
|
|
||||||
import javax.imageio.ImageIO;
|
import javax.imageio.ImageIO;
|
||||||
@@ -52,9 +54,6 @@ import java.util.ArrayList;
|
|||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
import static org.junit.jupiter.api.Assertions.*;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TIFFUtilitiesTest
|
* TIFFUtilitiesTest
|
||||||
*
|
*
|
||||||
@@ -96,7 +95,7 @@ public class TIFFUtilitiesTest {
|
|||||||
ImageInputStream iis = ImageIO.createImageInputStream(output);
|
ImageInputStream iis = ImageIO.createImageInputStream(output);
|
||||||
ImageReader reader = ImageIO.getImageReaders(iis).next();
|
ImageReader reader = ImageIO.getImageReaders(iis).next();
|
||||||
reader.setInput(iis);
|
reader.setInput(iis);
|
||||||
assertEquals(3, reader.getNumImages(true));
|
Assert.assertEquals(3, reader.getNumImages(true));
|
||||||
|
|
||||||
iis.close();
|
iis.close();
|
||||||
output.delete();
|
output.delete();
|
||||||
@@ -120,11 +119,11 @@ public class TIFFUtilitiesTest {
|
|||||||
ImageReader reader = ImageIO.getImageReadersByFormatName("TIF").next();
|
ImageReader reader = ImageIO.getImageReadersByFormatName("TIF").next();
|
||||||
|
|
||||||
File[] outputFiles = outputDirectory.listFiles();
|
File[] outputFiles = outputDirectory.listFiles();
|
||||||
assertEquals(3, outputFiles.length);
|
Assert.assertEquals(3, outputFiles.length);
|
||||||
for (File outputFile : outputFiles) {
|
for (File outputFile : outputFiles) {
|
||||||
ImageInputStream iis = ImageIO.createImageInputStream(outputFile);
|
ImageInputStream iis = ImageIO.createImageInputStream(outputFile);
|
||||||
reader.setInput(iis);
|
reader.setInput(iis);
|
||||||
assertEquals(1, reader.getNumImages(true));
|
Assert.assertEquals(1, reader.getNumImages(true));
|
||||||
iis.close();
|
iis.close();
|
||||||
outputFile.delete();
|
outputFile.delete();
|
||||||
}
|
}
|
||||||
@@ -158,7 +157,7 @@ public class TIFFUtilitiesTest {
|
|||||||
Node metaData = reader.getImageMetadata(i)
|
Node metaData = reader.getImageMetadata(i)
|
||||||
.getAsTree(TIFFImageMetadataFormat.SUN_NATIVE_IMAGE_METADATA_FORMAT_NAME);
|
.getAsTree(TIFFImageMetadataFormat.SUN_NATIVE_IMAGE_METADATA_FORMAT_NAME);
|
||||||
short orientation = ((Number) expression.evaluate(metaData, XPathConstants.NUMBER)).shortValue();
|
short orientation = ((Number) expression.evaluate(metaData, XPathConstants.NUMBER)).shortValue();
|
||||||
assertEquals(orientation, TIFFExtension.ORIENTATION_RIGHTTOP);
|
Assert.assertEquals(orientation, TIFFExtension.ORIENTATION_RIGHTTOP);
|
||||||
}
|
}
|
||||||
checkTest1.close();
|
checkTest1.close();
|
||||||
|
|
||||||
@@ -175,7 +174,7 @@ public class TIFFUtilitiesTest {
|
|||||||
Node metaData = reader.getImageMetadata(i)
|
Node metaData = reader.getImageMetadata(i)
|
||||||
.getAsTree(TIFFImageMetadataFormat.SUN_NATIVE_IMAGE_METADATA_FORMAT_NAME);
|
.getAsTree(TIFFImageMetadataFormat.SUN_NATIVE_IMAGE_METADATA_FORMAT_NAME);
|
||||||
short orientation = ((Number) expression.evaluate(metaData, XPathConstants.NUMBER)).shortValue();
|
short orientation = ((Number) expression.evaluate(metaData, XPathConstants.NUMBER)).shortValue();
|
||||||
assertEquals(orientation, i == 1
|
Assert.assertEquals(orientation, i == 1
|
||||||
? TIFFExtension.ORIENTATION_BOTRIGHT
|
? TIFFExtension.ORIENTATION_BOTRIGHT
|
||||||
: TIFFExtension.ORIENTATION_RIGHTTOP);
|
: TIFFExtension.ORIENTATION_RIGHTTOP);
|
||||||
}
|
}
|
||||||
@@ -200,7 +199,7 @@ public class TIFFUtilitiesTest {
|
|||||||
byte[] original = ((DataBufferByte) image.getData().getDataBuffer()).getData();
|
byte[] original = ((DataBufferByte) image.getData().getDataBuffer()).getData();
|
||||||
byte[] rotated = ((DataBufferByte) image360.getData().getDataBuffer()).getData();
|
byte[] rotated = ((DataBufferByte) image360.getData().getDataBuffer()).getData();
|
||||||
|
|
||||||
assertArrayEquals(original, rotated);
|
Assert.assertArrayEquals(original, rotated);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>com.twelvemonkeys.imageio</groupId>
|
<groupId>com.twelvemonkeys.imageio</groupId>
|
||||||
<artifactId>imageio</artifactId>
|
<artifactId>imageio</artifactId>
|
||||||
<version>3.12.1-SNAPSHOT</version>
|
<version>3.7.1</version>
|
||||||
</parent>
|
</parent>
|
||||||
<artifactId>imageio-batik</artifactId>
|
<artifactId>imageio-batik</artifactId>
|
||||||
<name>TwelveMonkeys :: ImageIO :: Batik Plugin</name>
|
<name>TwelveMonkeys :: ImageIO :: Batik Plugin</name>
|
||||||
@@ -17,7 +17,7 @@
|
|||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<project.jpms.module.name>com.twelvemonkeys.imageio.batik</project.jpms.module.name>
|
<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>
|
</properties>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
@@ -27,24 +27,12 @@
|
|||||||
<artifactId>maven-surefire-plugin</artifactId>
|
<artifactId>maven-surefire-plugin</artifactId>
|
||||||
<configuration>
|
<configuration>
|
||||||
<systemPropertyVariables>
|
<systemPropertyVariables>
|
||||||
<com.twelvemonkeys.imageio.plugins.svg.allowExternalResources>
|
<com.twelvemonkeys.imageio.plugins.svg.allowexternalresources>
|
||||||
true
|
true
|
||||||
</com.twelvemonkeys.imageio.plugins.svg.allowExternalResources>
|
</com.twelvemonkeys.imageio.plugins.svg.allowexternalresources>
|
||||||
</systemPropertyVariables>
|
</systemPropertyVariables>
|
||||||
</configuration>
|
</configuration>
|
||||||
</plugin>
|
</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>
|
</plugins>
|
||||||
</build>
|
</build>
|
||||||
|
|
||||||
@@ -60,13 +48,6 @@
|
|||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>commons-io</groupId>
|
|
||||||
<artifactId>commons-io</artifactId>
|
|
||||||
<version>2.19.0</version>
|
|
||||||
<scope>provided</scope>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.apache.xmlgraphics</groupId>
|
<groupId>org.apache.xmlgraphics</groupId>
|
||||||
<artifactId>batik-rasterizer-ext</artifactId>
|
<artifactId>batik-rasterizer-ext</artifactId>
|
||||||
|
|||||||
+132
-140
@@ -30,11 +30,21 @@
|
|||||||
|
|
||||||
package com.twelvemonkeys.imageio.plugins.svg;
|
package com.twelvemonkeys.imageio.plugins.svg;
|
||||||
|
|
||||||
import com.twelvemonkeys.image.ImageUtil;
|
import java.awt.*;
|
||||||
import com.twelvemonkeys.imageio.ImageReaderBase;
|
import java.awt.geom.AffineTransform;
|
||||||
import com.twelvemonkeys.imageio.util.IIOUtil;
|
import java.awt.geom.Rectangle2D;
|
||||||
import com.twelvemonkeys.imageio.util.ImageTypeSpecifiers;
|
import java.awt.image.BufferedImage;
|
||||||
import com.twelvemonkeys.lang.StringUtil;
|
import java.io.IOException;
|
||||||
|
import java.net.MalformedURLException;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import javax.imageio.IIOException;
|
||||||
|
import javax.imageio.ImageReadParam;
|
||||||
|
import javax.imageio.ImageTypeSpecifier;
|
||||||
|
import javax.imageio.spi.ImageReaderSpi;
|
||||||
|
|
||||||
import org.apache.batik.anim.dom.SVGDOMImplementation;
|
import org.apache.batik.anim.dom.SVGDOMImplementation;
|
||||||
import org.apache.batik.anim.dom.SVGOMDocument;
|
import org.apache.batik.anim.dom.SVGOMDocument;
|
||||||
@@ -58,19 +68,10 @@ import org.w3c.dom.DOMImplementation;
|
|||||||
import org.w3c.dom.Document;
|
import org.w3c.dom.Document;
|
||||||
import org.w3c.dom.svg.SVGSVGElement;
|
import org.w3c.dom.svg.SVGSVGElement;
|
||||||
|
|
||||||
import javax.imageio.IIOException;
|
import com.twelvemonkeys.image.ImageUtil;
|
||||||
import javax.imageio.ImageReadParam;
|
import com.twelvemonkeys.imageio.ImageReaderBase;
|
||||||
import javax.imageio.ImageTypeSpecifier;
|
import com.twelvemonkeys.imageio.util.IIOUtil;
|
||||||
import javax.imageio.spi.ImageReaderSpi;
|
import com.twelvemonkeys.lang.StringUtil;
|
||||||
import java.awt.*;
|
|
||||||
import java.awt.geom.*;
|
|
||||||
import java.awt.image.*;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.net.MalformedURLException;
|
|
||||||
import java.net.URL;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Image reader for SVG document fragments.
|
* Image reader for SVG document fragments.
|
||||||
@@ -78,13 +79,12 @@ import java.util.Map;
|
|||||||
* @author Harald Kuhr
|
* @author Harald Kuhr
|
||||||
* @author Inpspired by code from the Batik Team
|
* @author Inpspired by code from the Batik Team
|
||||||
* @version $Id: $
|
* @version $Id: $
|
||||||
* @see <a href="http://www.mail-archive.com/batik-dev@xml.apache.org/msg00992.html">batik-dev</a>
|
* @see <A href="http://www.mail-archive.com/batik-dev@xml.apache.org/msg00992.html">batik-dev</A>
|
||||||
*/
|
*/
|
||||||
public class SVGImageReader extends ImageReaderBase {
|
public class SVGImageReader extends ImageReaderBase {
|
||||||
|
|
||||||
final static boolean DEFAULT_ALLOW_EXTERNAL_RESOURCES =
|
final static boolean DEFAULT_ALLOW_EXTERNAL_RESOURCES =
|
||||||
"true".equalsIgnoreCase(System.getProperty("com.twelvemonkeys.imageio.plugins.svg.allowExternalResources",
|
"true".equalsIgnoreCase(System.getProperty("com.twelvemonkeys.imageio.plugins.svg.allowexternalresources"));
|
||||||
System.getProperty("com.twelvemonkeys.imageio.plugins.svg.allowexternalresources")));
|
|
||||||
|
|
||||||
private Rasterizer rasterizer;
|
private Rasterizer rasterizer;
|
||||||
private boolean allowExternalResources = DEFAULT_ALLOW_EXTERNAL_RESOURCES;
|
private boolean allowExternalResources = DEFAULT_ALLOW_EXTERNAL_RESOURCES;
|
||||||
@@ -92,10 +92,10 @@ public class SVGImageReader extends ImageReaderBase {
|
|||||||
/**
|
/**
|
||||||
* Creates an {@code SVGImageReader}.
|
* Creates an {@code SVGImageReader}.
|
||||||
*
|
*
|
||||||
* @param provider the provider
|
* @param pProvider the provider
|
||||||
*/
|
*/
|
||||||
public SVGImageReader(final ImageReaderSpi provider) {
|
public SVGImageReader(final ImageReaderSpi pProvider) {
|
||||||
super(provider);
|
super(pProvider);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void resetMembers() {
|
protected void resetMembers() {
|
||||||
@@ -109,20 +109,20 @@ public class SVGImageReader extends ImageReaderBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setInput(Object input, boolean seekForwardOnly, boolean ignoreMetadata) {
|
public void setInput(Object pInput, boolean seekForwardOnly, boolean ignoreMetadata) {
|
||||||
super.setInput(input, seekForwardOnly, ignoreMetadata);
|
super.setInput(pInput, seekForwardOnly, ignoreMetadata);
|
||||||
|
|
||||||
if (imageInput != null) {
|
if (imageInput != null) {
|
||||||
TranscoderInput transcoderInput = new TranscoderInput(IIOUtil.createStreamAdapter(imageInput));
|
TranscoderInput input = new TranscoderInput(IIOUtil.createStreamAdapter(imageInput));
|
||||||
rasterizer.setInput(transcoderInput);
|
rasterizer.setInput(input);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public BufferedImage read(int imageIndex, ImageReadParam param) throws IOException {
|
public BufferedImage read(int pIndex, ImageReadParam pParam) throws IOException {
|
||||||
checkBounds(imageIndex);
|
checkBounds(pIndex);
|
||||||
|
|
||||||
if (param instanceof SVGReadParam) {
|
if (pParam instanceof SVGReadParam) {
|
||||||
SVGReadParam svgParam = (SVGReadParam) param;
|
SVGReadParam svgParam = (SVGReadParam) pParam;
|
||||||
|
|
||||||
// set the external-resource-resolution preference
|
// set the external-resource-resolution preference
|
||||||
allowExternalResources = svgParam.isAllowExternalResources();
|
allowExternalResources = svgParam.isAllowExternalResources();
|
||||||
@@ -140,33 +140,39 @@ public class SVGImageReader extends ImageReaderBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Dimension size = null;
|
Dimension size = null;
|
||||||
if (param != null) {
|
if (pParam != null) {
|
||||||
size = param.getSourceRenderSize();
|
size = pParam.getSourceRenderSize();
|
||||||
}
|
}
|
||||||
if (size == null) {
|
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
|
// Read in the image, using the Batik Transcoder
|
||||||
processImageStarted(imageIndex);
|
|
||||||
|
|
||||||
BufferedImage image = rasterizer.getImage();
|
|
||||||
|
|
||||||
Graphics2D g = destination.createGraphics();
|
|
||||||
try {
|
try {
|
||||||
g.setComposite(AlphaComposite.Src);
|
processImageStarted(pIndex);
|
||||||
g.setRenderingHint(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_DISABLE);
|
|
||||||
g.drawImage(image, 0, 0, null); // TODO: Dest offset?
|
|
||||||
}
|
|
||||||
finally {
|
|
||||||
g.dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
processImageComplete();
|
BufferedImage image = rasterizer.getImage();
|
||||||
|
|
||||||
return destination;
|
Graphics2D g = destination.createGraphics();
|
||||||
|
try {
|
||||||
|
g.setComposite(AlphaComposite.Src);
|
||||||
|
g.setRenderingHint(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_DISABLE);
|
||||||
|
g.drawImage(image, 0, 0, null); // TODO: Dest offset?
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
g.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
processImageComplete();
|
||||||
|
|
||||||
|
return destination;
|
||||||
|
}
|
||||||
|
catch (TranscoderException e) {
|
||||||
|
Throwable cause = unwrapException(e);
|
||||||
|
throw new IIOException(cause.getMessage(), cause);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Throwable unwrapException(TranscoderException ex) {
|
private static Throwable unwrapException(TranscoderException ex) {
|
||||||
@@ -174,18 +180,18 @@ public class SVGImageReader extends ImageReaderBase {
|
|||||||
return ex.getException() != null ? ex.getException() : ex;
|
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();
|
TranscodingHints hints = new TranscodingHints();
|
||||||
// Note: We must allow generic ImageReadParams, so converting to
|
// Note: We must allow generic ImageReadParams, so converting to
|
||||||
// TanscodingHints should be done outside the SVGReadParam class.
|
// TanscodingHints should be done outside the SVGReadParam class.
|
||||||
|
|
||||||
// Set dimensions
|
// Set dimensions
|
||||||
Dimension size = param.getSourceRenderSize();
|
Dimension size = pParam.getSourceRenderSize();
|
||||||
Rectangle viewBox = rasterizer.getViewBox();
|
Dimension origSize = new Dimension(getWidth(0), getHeight(0));
|
||||||
if (size == null) {
|
if (size == null) {
|
||||||
// SVG is not a pixel based format, but we'll scale it, according to
|
// SVG is not a pixel based format, but we'll scale it, according to
|
||||||
// the subsampling for compatibility
|
// the subsampling for compatibility
|
||||||
size = getSourceRenderSizeFromSubsamping(param, viewBox.getSize());
|
size = getSourceRenderSizeFromSubsamping(pParam, origSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (size != null) {
|
if (size != null) {
|
||||||
@@ -194,7 +200,7 @@ public class SVGImageReader extends ImageReaderBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Set area of interest
|
// Set area of interest
|
||||||
Rectangle region = param.getSourceRegion();
|
Rectangle region = pParam.getSourceRegion();
|
||||||
if (region != null) {
|
if (region != null) {
|
||||||
hints.put(ImageTranscoder.KEY_AOI, region);
|
hints.put(ImageTranscoder.KEY_AOI, region);
|
||||||
|
|
||||||
@@ -205,8 +211,8 @@ public class SVGImageReader extends ImageReaderBase {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// Need to resize here...
|
// Need to resize here...
|
||||||
double xScale = size.getWidth() / viewBox.getWidth();
|
double xScale = size.getWidth() / origSize.getWidth();
|
||||||
double yScale = size.getHeight() / viewBox.getHeight();
|
double yScale = size.getHeight() / origSize.getHeight();
|
||||||
|
|
||||||
hints.put(ImageTranscoder.KEY_WIDTH, (float) (region.getWidth() * xScale));
|
hints.put(ImageTranscoder.KEY_WIDTH, (float) (region.getWidth() * xScale));
|
||||||
hints.put(ImageTranscoder.KEY_HEIGHT, (float) (region.getHeight() * yScale));
|
hints.put(ImageTranscoder.KEY_HEIGHT, (float) (region.getHeight() * yScale));
|
||||||
@@ -214,11 +220,11 @@ public class SVGImageReader extends ImageReaderBase {
|
|||||||
}
|
}
|
||||||
else if (size != null) {
|
else if (size != null) {
|
||||||
// Allow non-uniform scaling
|
// Allow non-uniform scaling
|
||||||
hints.put(ImageTranscoder.KEY_AOI, viewBox);
|
hints.put(ImageTranscoder.KEY_AOI, new Rectangle(origSize));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Background color
|
// Background color
|
||||||
Paint bg = param.getBackgroundColor();
|
Paint bg = pParam.getBackgroundColor();
|
||||||
if (bg != null) {
|
if (bg != null) {
|
||||||
hints.put(ImageTranscoder.KEY_BACKGROUND_COLOR, bg);
|
hints.put(ImageTranscoder.KEY_BACKGROUND_COLOR, bg);
|
||||||
}
|
}
|
||||||
@@ -226,10 +232,10 @@ public class SVGImageReader extends ImageReaderBase {
|
|||||||
return hints;
|
return hints;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Dimension getSourceRenderSizeFromSubsamping(ImageReadParam param, Dimension origSize) {
|
private Dimension getSourceRenderSizeFromSubsamping(ImageReadParam pParam, Dimension pOrigSize) {
|
||||||
if (param.getSourceXSubsampling() > 1 || param.getSourceYSubsampling() > 1) {
|
if (pParam.getSourceXSubsampling() > 1 || pParam.getSourceYSubsampling() > 1) {
|
||||||
return new Dimension((int) (origSize.width / (float) param.getSourceXSubsampling()),
|
return new Dimension((int) (pOrigSize.width / (float) pParam.getSourceXSubsampling()),
|
||||||
(int) (origSize.height / (float) param.getSourceYSubsampling()));
|
(int) (pOrigSize.height / (float) pParam.getSourceYSubsampling()));
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -238,19 +244,28 @@ public class SVGImageReader extends ImageReaderBase {
|
|||||||
return new SVGReadParam();
|
return new SVGReadParam();
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getWidth(int imageIndex) throws IOException {
|
public int getWidth(int pIndex) throws IOException {
|
||||||
checkBounds(imageIndex);
|
checkBounds(pIndex);
|
||||||
|
try {
|
||||||
return rasterizer.getDefaultWidth();
|
return rasterizer.getDefaultWidth();
|
||||||
|
}
|
||||||
|
catch (TranscoderException e) {
|
||||||
|
throw new IIOException(e.getMessage(), e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getHeight(int imageIndex) throws IOException {
|
public int getHeight(int pIndex) throws IOException {
|
||||||
checkBounds(imageIndex);
|
checkBounds(pIndex);
|
||||||
return rasterizer.getDefaultHeight();
|
try {
|
||||||
|
return rasterizer.getDefaultHeight();
|
||||||
|
}
|
||||||
|
catch (TranscoderException e) {
|
||||||
|
throw new IIOException(e.getMessage(), e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Iterator<ImageTypeSpecifier> getImageTypes(int imageIndex) {
|
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();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -260,11 +275,12 @@ public class SVGImageReader extends ImageReaderBase {
|
|||||||
* and needs major refactoring!
|
* and needs major refactoring!
|
||||||
* </p>
|
* </p>
|
||||||
*/
|
*/
|
||||||
private class Rasterizer extends SVGAbstractTranscoder {
|
private class Rasterizer extends SVGAbstractTranscoder /*ImageTranscoder*/ {
|
||||||
|
|
||||||
private BufferedImage image;
|
private BufferedImage image;
|
||||||
private TranscoderInput transcoderInput;
|
private TranscoderInput transcoderInput;
|
||||||
private final Rectangle2D viewBox = new Rectangle2D.Float();
|
private float defaultWidth;
|
||||||
private final Dimension defaultSize = new Dimension();
|
private float defaultHeight;
|
||||||
private boolean initialized = false;
|
private boolean initialized = false;
|
||||||
private SVGOMDocument document;
|
private SVGOMDocument document;
|
||||||
private String uri;
|
private String uri;
|
||||||
@@ -325,66 +341,54 @@ public class SVGImageReader extends ImageReaderBase {
|
|||||||
// ----
|
// ----
|
||||||
SVGSVGElement rootElement = svgDoc.getRootElement();
|
SVGSVGElement rootElement = svgDoc.getRootElement();
|
||||||
|
|
||||||
// Get the viewBox
|
// get the 'width' and 'height' attributes of the SVG document
|
||||||
String viewBoxStr = rootElement.getAttributeNS(null, SVGConstants.SVG_VIEW_BOX_ATTRIBUTE);
|
UnitProcessor.Context uctx
|
||||||
if (viewBoxStr.length() != 0) {
|
= UnitProcessor.createContext(ctx, rootElement);
|
||||||
float[] rect = ViewBox.parseViewBoxAttribute(rootElement, viewBoxStr, null);
|
|
||||||
viewBox.setFrame(rect[0], rect[1], rect[2], rect[3]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the 'width' and 'height' attributes of the SVG document
|
|
||||||
double width = 0;
|
|
||||||
double height = 0;
|
|
||||||
UnitProcessor.Context uctx = UnitProcessor.createContext(ctx, rootElement);
|
|
||||||
String widthStr = rootElement.getAttributeNS(null, SVGConstants.SVG_WIDTH_ATTRIBUTE);
|
String widthStr = rootElement.getAttributeNS(null, SVGConstants.SVG_WIDTH_ATTRIBUTE);
|
||||||
String heightStr = rootElement.getAttributeNS(null, SVGConstants.SVG_HEIGHT_ATTRIBUTE);
|
String heightStr = rootElement.getAttributeNS(null, SVGConstants.SVG_HEIGHT_ATTRIBUTE);
|
||||||
if (!StringUtil.isEmpty(widthStr)) {
|
if (!StringUtil.isEmpty(widthStr)) {
|
||||||
width = UnitProcessor.svgToUserSpace(widthStr, SVGConstants.SVG_WIDTH_ATTRIBUTE, UnitProcessor.HORIZONTAL_LENGTH, uctx);
|
defaultWidth = UnitProcessor.svgToUserSpace(widthStr, SVGConstants.SVG_WIDTH_ATTRIBUTE, UnitProcessor.HORIZONTAL_LENGTH, uctx);
|
||||||
}
|
}
|
||||||
if (!StringUtil.isEmpty(heightStr)) {
|
if(!StringUtil.isEmpty(heightStr)){
|
||||||
height = UnitProcessor.svgToUserSpace(heightStr, SVGConstants.SVG_HEIGHT_ATTRIBUTE, UnitProcessor.VERTICAL_LENGTH, uctx);
|
defaultHeight = UnitProcessor.svgToUserSpace(heightStr, SVGConstants.SVG_HEIGHT_ATTRIBUTE, UnitProcessor.VERTICAL_LENGTH, uctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean hasWidth = width > 0.0;
|
boolean hasWidth = defaultWidth > 0.0;
|
||||||
boolean hasHeight = height > 0.0;
|
boolean hasHeight = defaultHeight > 0.0;
|
||||||
|
|
||||||
if (!hasWidth || !hasHeight) {
|
if (!hasWidth || !hasHeight) {
|
||||||
if (!viewBox.isEmpty()) {
|
String viewBoxStr = rootElement.getAttributeNS
|
||||||
// If one dimension is given, calculate other by aspect ratio in viewBox
|
(null, SVGConstants.SVG_VIEW_BOX_ATTRIBUTE);
|
||||||
|
if (viewBoxStr.length() != 0) {
|
||||||
|
float[] rect = ViewBox.parseViewBoxAttribute(rootElement, viewBoxStr, null);
|
||||||
|
// if one dimension is given, calculate other by aspect ratio in viewBox
|
||||||
|
// or use viewBox if no dimension is given
|
||||||
if (hasWidth) {
|
if (hasWidth) {
|
||||||
height = width * viewBox.getHeight() / viewBox.getWidth();
|
defaultHeight = defaultWidth * rect[3] / rect[2];
|
||||||
}
|
}
|
||||||
else if (hasHeight) {
|
else if (hasHeight) {
|
||||||
width = height * viewBox.getWidth() / viewBox.getHeight();
|
defaultWidth = defaultHeight * rect[2] / rect[3];
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// ...or use viewBox if no dimension is given
|
defaultWidth = rect[2];
|
||||||
width = viewBox.getWidth();
|
defaultHeight = rect[3];
|
||||||
height = viewBox.getHeight();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// No viewBox, just assume square size
|
|
||||||
if (hasHeight) {
|
if (hasHeight) {
|
||||||
width = height;
|
defaultWidth = defaultHeight;
|
||||||
}
|
}
|
||||||
else if (hasWidth) {
|
else if (hasWidth) {
|
||||||
height = width;
|
defaultHeight = defaultWidth;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// ...or finally fall back to Batik default sizes
|
// fallback to batik default sizes
|
||||||
width = 400;
|
defaultWidth = 400;
|
||||||
height = 400;
|
defaultHeight = 400;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// We now have a size, in the rare case we don't have a viewBox; set it to this size
|
|
||||||
defaultSize.setSize(width, height);
|
|
||||||
if (viewBox.isEmpty()) {
|
|
||||||
viewBox.setRect(0, 0, width, height);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Hack to work around exception above
|
// Hack to work around exception above
|
||||||
if (root != null) {
|
if (root != null) {
|
||||||
gvtRoot = root;
|
gvtRoot = root;
|
||||||
@@ -397,7 +401,7 @@ public class SVGImageReader extends ImageReaderBase {
|
|||||||
ctx = null;
|
ctx = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private BufferedImage readImage() throws IOException {
|
private BufferedImage readImage() throws TranscoderException {
|
||||||
init();
|
init();
|
||||||
|
|
||||||
if (abortRequested()) {
|
if (abortRequested()) {
|
||||||
@@ -422,8 +426,7 @@ public class SVGImageReader extends ImageReaderBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (gvtRoot == null) {
|
if (gvtRoot == null) {
|
||||||
Throwable cause = unwrapException(exception);
|
throw exception;
|
||||||
throw new IIOException(cause.getMessage(), cause);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ctx = context;
|
ctx = context;
|
||||||
@@ -441,7 +444,7 @@ public class SVGImageReader extends ImageReaderBase {
|
|||||||
|
|
||||||
|
|
||||||
// ----
|
// ----
|
||||||
setImageSize(defaultSize.width, defaultSize.height);
|
setImageSize(defaultWidth, defaultHeight);
|
||||||
|
|
||||||
if (abortRequested()) {
|
if (abortRequested()) {
|
||||||
processReadAborted();
|
processReadAborted();
|
||||||
@@ -455,17 +458,18 @@ public class SVGImageReader extends ImageReaderBase {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
Px = ViewBox.getViewTransform(ref, root, width, height, null);
|
Px = ViewBox.getViewTransform(ref, root, width, height, null);
|
||||||
|
|
||||||
}
|
}
|
||||||
catch (BridgeException ex) {
|
catch (BridgeException ex) {
|
||||||
throw new IIOException(ex.getMessage(), ex);
|
throw new TranscoderException(ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Px.isIdentity() && (width != defaultSize.width || height != defaultSize.height)) {
|
if (Px.isIdentity() && (width != defaultWidth || height != defaultHeight)) {
|
||||||
// The document has no viewBox, we need to resize it by hand.
|
// The document has no viewBox, we need to resize it by hand.
|
||||||
// we want to keep the document size ratio
|
// we want to keep the document size ratio
|
||||||
float xscale, yscale;
|
float xscale, yscale;
|
||||||
xscale = width / defaultSize.width;
|
xscale = width / defaultWidth;
|
||||||
yscale = height / defaultSize.height;
|
yscale = height / defaultHeight;
|
||||||
float scale = Math.min(xscale, yscale);
|
float scale = Math.min(xscale, yscale);
|
||||||
Px = AffineTransform.getScaleInstance(scale, scale);
|
Px = AffineTransform.getScaleInstance(scale, scale);
|
||||||
}
|
}
|
||||||
@@ -515,7 +519,7 @@ public class SVGImageReader extends ImageReaderBase {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (BridgeException ex) {
|
catch (BridgeException ex) {
|
||||||
throw new IIOException(ex.getMessage(), ex);
|
throw new TranscoderException(ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.root = gvtRoot;
|
this.root = gvtRoot;
|
||||||
@@ -584,7 +588,7 @@ public class SVGImageReader extends ImageReaderBase {
|
|||||||
return dest;
|
return dest;
|
||||||
}
|
}
|
||||||
catch (Exception ex) {
|
catch (Exception ex) {
|
||||||
throw new IIOException(ex.getMessage(), ex);
|
throw new TranscoderException(ex.getMessage(), ex);
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
if (context != null) {
|
if (context != null) {
|
||||||
@@ -593,7 +597,7 @@ public class SVGImageReader extends ImageReaderBase {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private synchronized void init() throws IIOException {
|
private synchronized void init() throws TranscoderException {
|
||||||
if (!initialized) {
|
if (!initialized) {
|
||||||
if (transcoderInput == null) {
|
if (transcoderInput == null) {
|
||||||
throw new IllegalStateException("input == null");
|
throw new IllegalStateException("input == null");
|
||||||
@@ -601,18 +605,11 @@ public class SVGImageReader extends ImageReaderBase {
|
|||||||
|
|
||||||
initialized = true;
|
initialized = true;
|
||||||
|
|
||||||
try {
|
super.transcode(transcoderInput, null);
|
||||||
super.addTranscodingHint(SVGAbstractTranscoder.KEY_ALLOW_EXTERNAL_RESOURCES, allowExternalResources);
|
|
||||||
super.transcode(transcoderInput, null);
|
|
||||||
}
|
|
||||||
catch (TranscoderException e) {
|
|
||||||
Throwable cause = unwrapException(e);
|
|
||||||
throw new IIOException(cause.getMessage(), cause);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private BufferedImage getImage() throws IOException {
|
private BufferedImage getImage() throws TranscoderException {
|
||||||
if (image == null) {
|
if (image == null) {
|
||||||
image = readImage();
|
image = readImage();
|
||||||
}
|
}
|
||||||
@@ -620,23 +617,18 @@ public class SVGImageReader extends ImageReaderBase {
|
|||||||
return image;
|
return image;
|
||||||
}
|
}
|
||||||
|
|
||||||
int getDefaultWidth() throws IOException {
|
int getDefaultWidth() throws TranscoderException {
|
||||||
init();
|
init();
|
||||||
return defaultSize.width;
|
return (int) Math.ceil(defaultWidth);
|
||||||
}
|
}
|
||||||
|
|
||||||
int getDefaultHeight() throws IOException {
|
int getDefaultHeight() throws TranscoderException {
|
||||||
init();
|
init();
|
||||||
return defaultSize.height;
|
return (int) Math.ceil(defaultHeight);
|
||||||
}
|
}
|
||||||
|
|
||||||
Rectangle getViewBox() throws IOException {
|
void setInput(final TranscoderInput pInput) {
|
||||||
init();
|
transcoderInput = pInput;
|
||||||
return viewBox.getBounds();
|
|
||||||
}
|
|
||||||
|
|
||||||
void setInput(final TranscoderInput input) {
|
|
||||||
transcoderInput = input;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
+14
-14
@@ -60,22 +60,22 @@ public final class SVGImageReaderSpi extends ImageReaderSpiBase {
|
|||||||
super(new SVGProviderInfo());
|
super(new SVGProviderInfo());
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean canDecodeInput(final Object source) throws IOException {
|
public boolean canDecodeInput(final Object pSource) throws IOException {
|
||||||
return source instanceof ImageInputStream && canDecode((ImageInputStream) source);
|
return pSource instanceof ImageInputStream && canDecode((ImageInputStream) pSource);
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("StatementWithEmptyBody")
|
@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,
|
// NOTE: This test is quite quick as it does not involve any parsing,
|
||||||
// however it may not recognize all kinds of SVG documents.
|
// however it may not recognize all kinds of SVG documents.
|
||||||
try {
|
try {
|
||||||
input.mark();
|
pInput.mark();
|
||||||
|
|
||||||
// TODO: This is not ok for UTF-16 and other wide encodings
|
// TODO: This is not ok for UTF-16 and other wide encodings
|
||||||
// TODO: Use an XML (encoding) aware Reader instance instead
|
// TODO: Use an XML (encoding) aware Reader instance instead
|
||||||
// Need to figure out pretty fast if this is XML or not
|
// Need to figure out pretty fast if this is XML or not
|
||||||
int b;
|
int b;
|
||||||
while (Character.isWhitespace((char) (b = input.read()))) {
|
while (Character.isWhitespace((char) (b = pInput.read()))) {
|
||||||
// Skip over leading WS
|
// Skip over leading WS
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -95,30 +95,30 @@ public final class SVGImageReaderSpi extends ImageReaderSpiBase {
|
|||||||
|
|
||||||
byte[] buffer = new byte[4];
|
byte[] buffer = new byte[4];
|
||||||
while (true) {
|
while (true) {
|
||||||
input.readFully(buffer);
|
pInput.readFully(buffer);
|
||||||
|
|
||||||
if (buffer[0] == '?') {
|
if (buffer[0] == '?') {
|
||||||
// This is the XML declaration or a processing instruction
|
// 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
|
// Skip until end of XML declaration or processing instruction or EOF
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (buffer[0] == '!') {
|
else if (buffer[0] == '!') {
|
||||||
if (buffer[1] == '-' && buffer[2] == '-') {
|
if (buffer[1] == '-' && buffer[2] == '-') {
|
||||||
// This is a comment
|
// 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
|
// Skip until end of comment or EOF
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (buffer[1] == 'D' && buffer[2] == 'O' && buffer[3] == 'C'
|
else if (buffer[1] == 'D' && buffer[2] == 'O' && buffer[3] == 'C'
|
||||||
&& input.read() == 'T' && input.read() == 'Y'
|
&& pInput.read() == 'T' && pInput.read() == 'Y'
|
||||||
&& input.read() == 'P' && input.read() == 'E') {
|
&& pInput.read() == 'P' && pInput.read() == 'E') {
|
||||||
// This is the DOCTYPE declaration
|
// This is the DOCTYPE declaration
|
||||||
while (Character.isWhitespace((char) (b = input.read()))) {
|
while (Character.isWhitespace((char) (b = pInput.read()))) {
|
||||||
// Skip over WS
|
// 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
|
// It's SVG, identified by DOCTYPE
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -142,7 +142,7 @@ public final class SVGImageReaderSpi extends ImageReaderSpiBase {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
while ((input.readByte() & 0xFF) != '<') {
|
while ((pInput.readByte() & 0xFF) != '<') {
|
||||||
// Skip over, until next begin tag or EOF
|
// Skip over, until next begin tag or EOF
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -153,7 +153,7 @@ public final class SVGImageReaderSpi extends ImageReaderSpiBase {
|
|||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
//noinspection ThrowFromFinallyBlock
|
//noinspection ThrowFromFinallyBlock
|
||||||
input.reset();
|
pInput.reset();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+4
-4
@@ -51,16 +51,16 @@ public class SVGReadParam extends ImageReadParam {
|
|||||||
return background;
|
return background;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setBackgroundColor(Paint color) {
|
public void setBackgroundColor(Paint pColor) {
|
||||||
background = color;
|
background = pColor;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getBaseURI() {
|
public String getBaseURI() {
|
||||||
return baseURI;
|
return baseURI;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setBaseURI(String baseURI) {
|
public void setBaseURI(String pBaseURI) {
|
||||||
this.baseURI = baseURI;
|
baseURI = pBaseURI;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setAllowExternalResources(boolean allow) {
|
public void setAllowExternalResources(boolean allow) {
|
||||||
|
|||||||
+141
-143
@@ -1,143 +1,141 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2008, Harald Kuhr
|
* Copyright (c) 2008, Harald Kuhr
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* modification, are permitted provided that the following conditions are met:
|
* modification, are permitted provided that the following conditions are met:
|
||||||
*
|
*
|
||||||
* * Redistributions of source code must retain the above copyright notice, this
|
* * Redistributions of source code must retain the above copyright notice, this
|
||||||
* list of conditions and the following disclaimer.
|
* list of conditions and the following disclaimer.
|
||||||
*
|
*
|
||||||
* * Redistributions in binary form must reproduce the above copyright notice,
|
* * Redistributions in binary form must reproduce the above copyright notice,
|
||||||
* this list of conditions and the following disclaimer in the documentation
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
* and/or other materials provided with the distribution.
|
* and/or other materials provided with the distribution.
|
||||||
*
|
*
|
||||||
* * Neither the name of the copyright holder nor the names of its
|
* * Neither the name of the copyright holder nor the names of its
|
||||||
* contributors may be used to endorse or promote products derived from
|
* contributors may be used to endorse or promote products derived from
|
||||||
* this software without specific prior written permission.
|
* this software without specific prior written permission.
|
||||||
*
|
*
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
* 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
|
* 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.
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.twelvemonkeys.imageio.plugins.wmf;
|
package com.twelvemonkeys.imageio.plugins.wmf;
|
||||||
|
|
||||||
import com.twelvemonkeys.imageio.ImageReaderBase;
|
import com.twelvemonkeys.imageio.ImageReaderBase;
|
||||||
import com.twelvemonkeys.imageio.plugins.svg.SVGImageReader;
|
import com.twelvemonkeys.imageio.plugins.svg.SVGImageReader;
|
||||||
import com.twelvemonkeys.imageio.plugins.svg.SVGReadParam;
|
import com.twelvemonkeys.imageio.plugins.svg.SVGReadParam;
|
||||||
import com.twelvemonkeys.imageio.stream.ByteArrayImageInputStream;
|
import com.twelvemonkeys.imageio.util.IIOUtil;
|
||||||
import com.twelvemonkeys.imageio.util.IIOUtil;
|
import org.apache.batik.transcoder.TranscoderException;
|
||||||
|
import org.apache.batik.transcoder.TranscoderInput;
|
||||||
import org.apache.batik.transcoder.TranscoderException;
|
import org.apache.batik.transcoder.TranscoderOutput;
|
||||||
import org.apache.batik.transcoder.TranscoderInput;
|
import org.apache.batik.transcoder.wmf.tosvg.WMFTranscoder;
|
||||||
import org.apache.batik.transcoder.TranscoderOutput;
|
|
||||||
import org.apache.batik.transcoder.wmf.tosvg.WMFTranscoder;
|
import javax.imageio.IIOException;
|
||||||
|
import javax.imageio.ImageIO;
|
||||||
import javax.imageio.IIOException;
|
import javax.imageio.ImageReadParam;
|
||||||
import javax.imageio.ImageReadParam;
|
import javax.imageio.ImageTypeSpecifier;
|
||||||
import javax.imageio.ImageTypeSpecifier;
|
import javax.imageio.spi.ImageReaderSpi;
|
||||||
import javax.imageio.spi.ImageReaderSpi;
|
import java.awt.image.BufferedImage;
|
||||||
import java.awt.image.*;
|
import java.io.*;
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.util.Iterator;
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.OutputStreamWriter;
|
/**
|
||||||
import java.io.Writer;
|
* WMFImageReader class description.
|
||||||
import java.nio.charset.StandardCharsets;
|
*
|
||||||
import java.util.Iterator;
|
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||||
|
* @author last modified by $Author: haku $
|
||||||
/**
|
* @version $Id: WMFImageReader.java,v 1.0 29.jul.2004 13:00:59 haku Exp $
|
||||||
* WMFImageReader class description.
|
*/
|
||||||
*
|
// TODO: Probably possible to do less wrapping/unwrapping of data...
|
||||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
// TODO: Consider using temp file instead of in-memory stream
|
||||||
* @author last modified by $Author: haku $
|
public final class WMFImageReader extends ImageReaderBase {
|
||||||
* @version $Id: WMFImageReader.java,v 1.0 29.jul.2004 13:00:59 haku Exp $
|
|
||||||
*/
|
private SVGImageReader reader = null;
|
||||||
// TODO: Probably possible to do less wrapping/unwrapping of data...
|
|
||||||
public final class WMFImageReader extends ImageReaderBase {
|
public WMFImageReader(final ImageReaderSpi pProvider) {
|
||||||
|
super(pProvider);
|
||||||
private SVGImageReader reader = null;
|
}
|
||||||
|
|
||||||
public WMFImageReader(final ImageReaderSpi pProvider) {
|
protected void resetMembers() {
|
||||||
super(pProvider);
|
if (reader != null) {
|
||||||
}
|
reader.dispose();
|
||||||
|
}
|
||||||
protected void resetMembers() {
|
|
||||||
if (reader != null) {
|
reader = null;
|
||||||
reader.dispose();
|
}
|
||||||
}
|
|
||||||
|
public BufferedImage read(int pIndex, ImageReadParam pParam) throws IOException {
|
||||||
reader = null;
|
init();
|
||||||
}
|
|
||||||
|
processImageStarted(pIndex);
|
||||||
public BufferedImage read(int pIndex, ImageReadParam pParam) throws IOException {
|
|
||||||
init();
|
BufferedImage image = reader.read(pIndex, pParam);
|
||||||
|
if (abortRequested()) {
|
||||||
processImageStarted(pIndex);
|
processReadAborted();
|
||||||
|
return image;
|
||||||
BufferedImage image = reader.read(pIndex, pParam);
|
}
|
||||||
if (abortRequested()) {
|
processImageProgress(100f);
|
||||||
processReadAborted();
|
|
||||||
return image;
|
processImageComplete();
|
||||||
}
|
|
||||||
processImageProgress(100f);
|
return image;
|
||||||
|
}
|
||||||
processImageComplete();
|
|
||||||
|
private synchronized void init() throws IOException {
|
||||||
return image;
|
// Need the extra test, to avoid throwing an IOException from the Transcoder
|
||||||
}
|
if (imageInput == null) {
|
||||||
|
throw new IllegalStateException("input == null");
|
||||||
private void init() throws IOException {
|
}
|
||||||
// Need the extra test, to avoid throwing an IOException from the Transcoder
|
|
||||||
if (imageInput == null) {
|
if (reader == null) {
|
||||||
throw new IllegalStateException("input == null");
|
WMFTranscoder transcoder = new WMFTranscoder();
|
||||||
}
|
|
||||||
|
ByteArrayOutputStream output = new ByteArrayOutputStream();
|
||||||
if (reader == null) {
|
Writer writer = new OutputStreamWriter(output, "UTF8");
|
||||||
WMFTranscoder transcoder = new WMFTranscoder();
|
try {
|
||||||
ByteArrayOutputStream output = new ByteArrayOutputStream(8192);
|
TranscoderInput in = new TranscoderInput(IIOUtil.createStreamAdapter(imageInput));
|
||||||
|
TranscoderOutput out = new TranscoderOutput(writer);
|
||||||
try (Writer writer = new OutputStreamWriter(output, StandardCharsets.UTF_8)) {
|
|
||||||
TranscoderInput in = new TranscoderInput(IIOUtil.createStreamAdapter(imageInput));
|
// TODO: Transcodinghints?
|
||||||
TranscoderOutput out = new TranscoderOutput(writer);
|
|
||||||
|
transcoder.transcode(in, out);
|
||||||
// TODO: Transcodinghints?
|
}
|
||||||
|
catch (TranscoderException e) {
|
||||||
transcoder.transcode(in, out);
|
throw new IIOException(e.getMessage(), e);
|
||||||
}
|
}
|
||||||
catch (TranscoderException e) {
|
|
||||||
throw new IIOException(e.getMessage(), e);
|
reader = new SVGImageReader(getOriginatingProvider());
|
||||||
}
|
reader.setInput(ImageIO.createImageInputStream(new ByteArrayInputStream(output.toByteArray())));
|
||||||
|
}
|
||||||
reader = new SVGImageReader(getOriginatingProvider());
|
}
|
||||||
reader.setInput(new ByteArrayImageInputStream(output.toByteArray()));
|
|
||||||
}
|
@Override
|
||||||
}
|
public ImageReadParam getDefaultReadParam() {
|
||||||
|
return new SVGReadParam();
|
||||||
@Override
|
}
|
||||||
public ImageReadParam getDefaultReadParam() {
|
|
||||||
return new SVGReadParam();
|
public int getWidth(int pIndex) throws IOException {
|
||||||
}
|
init();
|
||||||
|
return reader.getWidth(pIndex);
|
||||||
public int getWidth(int pIndex) throws IOException {
|
}
|
||||||
init();
|
|
||||||
return reader.getWidth(pIndex);
|
public int getHeight(int pIndex) throws IOException {
|
||||||
}
|
init();
|
||||||
|
return reader.getHeight(pIndex);
|
||||||
public int getHeight(int pIndex) throws IOException {
|
}
|
||||||
init();
|
|
||||||
return reader.getHeight(pIndex);
|
public Iterator<ImageTypeSpecifier> getImageTypes(final int pImageIndex) throws IOException {
|
||||||
}
|
init();
|
||||||
|
return reader.getImageTypes(pImageIndex);
|
||||||
public Iterator<ImageTypeSpecifier> getImageTypes(final int pImageIndex) throws IOException {
|
}
|
||||||
init();
|
|
||||||
return reader.getImageTypes(pImageIndex);
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
+9
-11
@@ -32,16 +32,16 @@ package com.twelvemonkeys.imageio.plugins.svg;
|
|||||||
|
|
||||||
import com.twelvemonkeys.imageio.stream.ByteArrayImageInputStream;
|
import com.twelvemonkeys.imageio.stream.ByteArrayImageInputStream;
|
||||||
import com.twelvemonkeys.imageio.stream.URLImageInputStreamSpi;
|
import com.twelvemonkeys.imageio.stream.URLImageInputStreamSpi;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
import javax.imageio.ImageIO;
|
import javax.imageio.ImageIO;
|
||||||
import javax.imageio.spi.IIORegistry;
|
import javax.imageio.spi.IIORegistry;
|
||||||
import javax.imageio.spi.ImageReaderSpi;
|
import javax.imageio.spi.ImageReaderSpi;
|
||||||
import javax.imageio.stream.ImageInputStream;
|
import javax.imageio.stream.ImageInputStream;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.time.Duration;
|
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
import static org.junit.Assert.assertFalse;
|
||||||
import static org.junit.jupiter.api.Assertions.*;
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* SVGImageReaderSpiTest.
|
* SVGImageReaderSpiTest.
|
||||||
@@ -83,20 +83,18 @@ public class SVGImageReaderSpiTest {
|
|||||||
public void canDecodeInput() throws Exception {
|
public void canDecodeInput() throws Exception {
|
||||||
for (String validInput : VALID_INPUTS) {
|
for (String validInput : VALID_INPUTS) {
|
||||||
try (ImageInputStream input = ImageIO.createImageInputStream(getClass().getResource(validInput))) {
|
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 will time out, if EOFs are not properly detected, see #275
|
||||||
@Test
|
@Test(timeout = 5000)
|
||||||
public void canDecodeInputInvalid() throws Exception {
|
public void canDecodeInputInvalid() throws Exception {
|
||||||
assertTimeoutPreemptively(Duration.ofMillis(5000), () -> {
|
for (String invalidInput : INVALID_INPUTS) {
|
||||||
for (String invalidInput : INVALID_INPUTS) {
|
try (ImageInputStream input = new ByteArrayImageInputStream(invalidInput.getBytes(StandardCharsets.UTF_8))) {
|
||||||
try (ImageInputStream input = new ByteArrayImageInputStream(invalidInput.getBytes(StandardCharsets.UTF_8))) {
|
assertFalse("Claims to read invalid input:" + invalidInput, provider.canDecodeInput(input));
|
||||||
assertFalse(provider.canDecodeInput(input), "Claims to read invalid input:" + invalidInput);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+16
-81
@@ -32,6 +32,9 @@ package com.twelvemonkeys.imageio.plugins.svg;
|
|||||||
|
|
||||||
import com.twelvemonkeys.imageio.util.ImageReaderAbstractTest;
|
import com.twelvemonkeys.imageio.util.ImageReaderAbstractTest;
|
||||||
|
|
||||||
|
import org.junit.Ignore;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
import javax.imageio.IIOException;
|
import javax.imageio.IIOException;
|
||||||
import javax.imageio.ImageIO;
|
import javax.imageio.ImageIO;
|
||||||
import javax.imageio.ImageReadParam;
|
import javax.imageio.ImageReadParam;
|
||||||
@@ -40,7 +43,8 @@ import javax.imageio.event.IIOReadWarningListener;
|
|||||||
import javax.imageio.spi.ImageReaderSpi;
|
import javax.imageio.spi.ImageReaderSpi;
|
||||||
import javax.imageio.stream.ImageInputStream;
|
import javax.imageio.stream.ImageInputStream;
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.awt.image.*;
|
import java.awt.image.BufferedImage;
|
||||||
|
import java.awt.image.ImagingOpException;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.net.URISyntaxException;
|
import java.net.URISyntaxException;
|
||||||
@@ -49,9 +53,7 @@ import java.util.Arrays;
|
|||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.junit.jupiter.api.Disabled;
|
import static org.junit.Assert.*;
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
import static org.junit.jupiter.api.Assertions.*;
|
|
||||||
import static org.mockito.Mockito.*;
|
import static org.mockito.Mockito.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -124,18 +126,18 @@ public class SVGImageReaderTest extends ImageReaderAbstractTest<SVGImageReader>
|
|||||||
int current = image.getRGB(x, y);
|
int current = image.getRGB(x, y);
|
||||||
if (x < quadPoint) {
|
if (x < quadPoint) {
|
||||||
if (y < quadPoint) {
|
if (y < quadPoint) {
|
||||||
assertEquals( 0xFF0000FF, current, "x=" + x + " y=" + y + " q=" + quadPoint);
|
assertEquals("x=" + x + " y=" + y + " q=" + quadPoint, 0xFF0000FF, current);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
assertEquals(0xFFFF0000, current, "x=" + x + " y=" + y + " q=" + quadPoint);
|
assertEquals("x=" + x + " y=" + y + " q=" + quadPoint, 0xFFFF0000, current);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (y < quadPoint) {
|
if (y < quadPoint) {
|
||||||
assertEquals(0xFF00FF00, current, "x=" + x + " y=" + y + " q=" + quadPoint);
|
assertEquals("x=" + x + " y=" + y + " q=" + quadPoint, 0xFF00FF00, current);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
assertEquals(0xFF000000, current, "x=" + x + " y=" + y + " q=" + quadPoint);
|
assertEquals("x=" + x + " y=" + y + " q=" + quadPoint, 0xFF000000, current);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -167,14 +169,14 @@ public class SVGImageReaderTest extends ImageReaderAbstractTest<SVGImageReader>
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Disabled("Known issue: Source region reading not supported")
|
@Ignore("Known issue: Source region reading not supported")
|
||||||
@Override
|
@Override
|
||||||
public void testReadWithSourceRegionParamEqualImage() throws IOException {
|
public void testReadWithSourceRegionParamEqualImage() throws IOException {
|
||||||
super.testReadWithSourceRegionParamEqualImage();
|
super.testReadWithSourceRegionParamEqualImage();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Disabled("Known issue: Subsampled reading not supported")
|
@Ignore("Known issue: Subsampled reading not supported")
|
||||||
@Override
|
@Override
|
||||||
public void testReadWithSubsampleParamPixels() throws IOException {
|
public void testReadWithSubsampleParamPixels() throws IOException {
|
||||||
super.testReadWithSubsampleParamPixels();
|
super.testReadWithSubsampleParamPixels();
|
||||||
@@ -190,12 +192,12 @@ public class SVGImageReaderTest extends ImageReaderAbstractTest<SVGImageReader>
|
|||||||
TestData redSquare = new TestData(getClassLoaderResource("/svg/red-square.svg"), dim);
|
TestData redSquare = new TestData(getClassLoaderResource("/svg/red-square.svg"), dim);
|
||||||
reader.setInput(redSquare.getInputStream());
|
reader.setInput(redSquare.getInputStream());
|
||||||
BufferedImage imageRed = reader.read(0, param);
|
BufferedImage imageRed = reader.read(0, param);
|
||||||
assertRGBEquals("Expected all red", 0xFF0000, imageRed.getRGB(50, 50) & 0xFFFFFF, 0);
|
assertEquals(0xFF0000, imageRed.getRGB(50, 50) & 0xFFFFFF);
|
||||||
|
|
||||||
TestData blueSquare = new TestData(getClassLoaderResource("/svg/blue-square.svg"), dim);
|
TestData blueSquare = new TestData(getClassLoaderResource("/svg/blue-square.svg"), dim);
|
||||||
reader.setInput(blueSquare.getInputStream());
|
reader.setInput(blueSquare.getInputStream());
|
||||||
BufferedImage imageBlue = reader.read(0, param);
|
BufferedImage imageBlue = reader.read(0, param);
|
||||||
assertRGBEquals("Expected all blue", 0x0000FF, imageBlue.getRGB(50, 50) & 0xFFFFFF, 0);
|
assertEquals(0x0000FF, imageBlue.getRGB(50, 50) & 0xFFFFFF);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -312,7 +314,7 @@ public class SVGImageReaderTest extends ImageReaderAbstractTest<SVGImageReader>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test(expected = SecurityException.class)
|
||||||
public void testDisallowedExternalResources() throws URISyntaxException, IOException {
|
public void testDisallowedExternalResources() throws URISyntaxException, IOException {
|
||||||
// system-property set to true in surefire-plugin-settings in the pom
|
// system-property set to true in surefire-plugin-settings in the pom
|
||||||
URL resource = getClassLoaderResource("/svg/barChart.svg");
|
URL resource = getClassLoaderResource("/svg/barChart.svg");
|
||||||
@@ -329,74 +331,7 @@ public class SVGImageReaderTest extends ImageReaderAbstractTest<SVGImageReader>
|
|||||||
// `reader.read` for `/svg/barChart.svg` should raise
|
// `reader.read` for `/svg/barChart.svg` should raise
|
||||||
// a SecurityException when External Resources are blocked
|
// a SecurityException when External Resources are blocked
|
||||||
// because the API invocation gets preference
|
// because the API invocation gets preference
|
||||||
assertThrows(SecurityException.class, () -> {
|
reader.read(0, param);
|
||||||
reader.read(0, param);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
finally {
|
|
||||||
reader.dispose();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testReadWitSourceRenderSize() throws IOException {
|
|
||||||
URL resource = getClassLoaderResource("/svg/circle.svg");
|
|
||||||
|
|
||||||
SVGImageReader reader = createReader();
|
|
||||||
|
|
||||||
TestData data = new TestData(resource, (Dimension) null);
|
|
||||||
try (ImageInputStream stream = data.getInputStream()) {
|
|
||||||
reader.setInput(stream);
|
|
||||||
|
|
||||||
SVGReadParam param = reader.getDefaultReadParam();
|
|
||||||
param.setSourceRenderSize(new Dimension(100, 100));
|
|
||||||
BufferedImage image = reader.read(0, param);
|
|
||||||
|
|
||||||
assertNotNull(image);
|
|
||||||
assertEquals(100, image.getWidth());
|
|
||||||
assertEquals(100, image.getHeight());
|
|
||||||
|
|
||||||
// Some quick samples
|
|
||||||
assertRGBEquals("Expected transparent corner", 0, image.getRGB(0, 0), 0);
|
|
||||||
assertRGBEquals("Expected transparent corner", 0, image.getRGB(99, 0), 0);
|
|
||||||
assertRGBEquals("Expected transparent corner", 0, image.getRGB(0, 99), 0);
|
|
||||||
assertRGBEquals("Expected transparent corner", 0, image.getRGB(99, 99), 0);
|
|
||||||
assertRGBEquals("Expected red center", 0xffff0000, image.getRGB(50, 50), 0);
|
|
||||||
}
|
|
||||||
finally {
|
|
||||||
reader.dispose();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testReadWitSourceRenderSizeViewBoxNegativeXY() throws IOException {
|
|
||||||
URL resource = getClassLoaderResource("/svg/Android_robot.svg");
|
|
||||||
|
|
||||||
SVGImageReader reader = createReader();
|
|
||||||
|
|
||||||
TestData data = new TestData(resource, (Dimension) null);
|
|
||||||
try (ImageInputStream stream = data.getInputStream()) {
|
|
||||||
reader.setInput(stream);
|
|
||||||
|
|
||||||
SVGReadParam param = reader.getDefaultReadParam();
|
|
||||||
param.setSourceRenderSize(new Dimension(219, 256)); // Aspect scaled to 256 boxed
|
|
||||||
BufferedImage image = reader.read(0, param);
|
|
||||||
|
|
||||||
assertNotNull(image);
|
|
||||||
assertEquals(219, image.getWidth());
|
|
||||||
assertEquals(256, image.getHeight());
|
|
||||||
|
|
||||||
// Some quick samples
|
|
||||||
assertRGBEquals("Expected transparent corner", 0, image.getRGB(0, 0), 0);
|
|
||||||
assertRGBEquals("Expected transparent corner", 0, image.getRGB(218, 0), 0);
|
|
||||||
assertRGBEquals("Expected transparent corner", 0, image.getRGB(0, 255), 0);
|
|
||||||
assertRGBEquals("Expected transparent corner", 0, image.getRGB(218, 255), 0);
|
|
||||||
assertRGBEquals("Expected green head", 0xffa4c639, image.getRGB(109, 20), 25);
|
|
||||||
assertRGBEquals("Expected green center", 0xffa4c639, image.getRGB(109, 128), 25);
|
|
||||||
assertRGBEquals("Expected green feet", 0xffa4c639, image.getRGB(80, 246), 25);
|
|
||||||
assertRGBEquals("Expected green feet", 0xffa4c639, image.getRGB(130, 246), 25);
|
|
||||||
assertRGBEquals("Expected white edge", 0xffffffff, image.getRGB(0, 128), 0);
|
|
||||||
assertRGBEquals("Expected white edge", 0xffffffff, image.getRGB(218, 128), 0);
|
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
reader.dispose();
|
reader.dispose();
|
||||||
|
|||||||
+5
-4
@@ -32,6 +32,9 @@ package com.twelvemonkeys.imageio.plugins.wmf;
|
|||||||
|
|
||||||
import com.twelvemonkeys.imageio.util.ImageReaderAbstractTest;
|
import com.twelvemonkeys.imageio.util.ImageReaderAbstractTest;
|
||||||
|
|
||||||
|
import org.junit.Ignore;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
import javax.imageio.spi.ImageReaderSpi;
|
import javax.imageio.spi.ImageReaderSpi;
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@@ -39,8 +42,6 @@ import java.util.Arrays;
|
|||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.junit.jupiter.api.Disabled;
|
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
/**
|
/**
|
||||||
* WMFImageReaderTest
|
* WMFImageReaderTest
|
||||||
*
|
*
|
||||||
@@ -76,14 +77,14 @@ public class WMFImageReaderTest extends ImageReaderAbstractTest<WMFImageReader>
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Disabled("Known issue: Source region reading not supported")
|
@Ignore("Known issue: Source region reading not supported")
|
||||||
@Override
|
@Override
|
||||||
public void testReadWithSourceRegionParamEqualImage() throws IOException {
|
public void testReadWithSourceRegionParamEqualImage() throws IOException {
|
||||||
super.testReadWithSourceRegionParamEqualImage();
|
super.testReadWithSourceRegionParamEqualImage();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Disabled("Known issue: Subsampled reading not supported")
|
@Ignore("Known issue: Subsampled reading not supported")
|
||||||
@Override
|
@Override
|
||||||
public void testReadWithSubsampleParamPixels() throws IOException {
|
public void testReadWithSubsampleParamPixels() throws IOException {
|
||||||
super.testReadWithSubsampleParamPixels();
|
super.testReadWithSubsampleParamPixels();
|
||||||
|
|||||||
@@ -1,6 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
|
|
||||||
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
|
||||||
<svg width="100%" height="100%" viewBox="0 0 50 50" version="1.1" xmlns="http://www.w3.org/2000/svg"
|
|
||||||
xml:space="preserve"
|
|
||||||
style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2">
|
|
||||||
<circle cx="25" cy="25" r="25" fill="red"/></svg>
|
|
||||||
|
Before Width: | Height: | Size: 436 B |
@@ -4,7 +4,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>com.twelvemonkeys.imageio</groupId>
|
<groupId>com.twelvemonkeys.imageio</groupId>
|
||||||
<artifactId>imageio</artifactId>
|
<artifactId>imageio</artifactId>
|
||||||
<version>3.12.1-SNAPSHOT</version>
|
<version>3.7.1</version>
|
||||||
</parent>
|
</parent>
|
||||||
<artifactId>imageio-bmp</artifactId>
|
<artifactId>imageio-bmp</artifactId>
|
||||||
<name>TwelveMonkeys :: ImageIO :: BMP plugin</name>
|
<name>TwelveMonkeys :: ImageIO :: BMP plugin</name>
|
||||||
@@ -26,23 +26,4 @@
|
|||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</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>
|
</project>
|
||||||
|
|||||||
+21
-29
@@ -39,11 +39,7 @@ import com.twelvemonkeys.io.LittleEndianDataInputStream;
|
|||||||
import com.twelvemonkeys.io.enc.DecoderStream;
|
import com.twelvemonkeys.io.enc.DecoderStream;
|
||||||
import com.twelvemonkeys.xml.XMLSerializer;
|
import com.twelvemonkeys.xml.XMLSerializer;
|
||||||
|
|
||||||
import javax.imageio.IIOException;
|
import javax.imageio.*;
|
||||||
import javax.imageio.ImageIO;
|
|
||||||
import javax.imageio.ImageReadParam;
|
|
||||||
import javax.imageio.ImageReader;
|
|
||||||
import javax.imageio.ImageTypeSpecifier;
|
|
||||||
import javax.imageio.event.IIOReadUpdateListener;
|
import javax.imageio.event.IIOReadUpdateListener;
|
||||||
import javax.imageio.event.IIOReadWarningListener;
|
import javax.imageio.event.IIOReadWarningListener;
|
||||||
import javax.imageio.metadata.IIOMetadata;
|
import javax.imageio.metadata.IIOMetadata;
|
||||||
@@ -51,7 +47,7 @@ import javax.imageio.metadata.IIOMetadataFormatImpl;
|
|||||||
import javax.imageio.spi.ImageReaderSpi;
|
import javax.imageio.spi.ImageReaderSpi;
|
||||||
import javax.imageio.stream.ImageInputStream;
|
import javax.imageio.stream.ImageInputStream;
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.awt.color.*;
|
import java.awt.color.ColorSpace;
|
||||||
import java.awt.image.*;
|
import java.awt.image.*;
|
||||||
import java.io.DataInput;
|
import java.io.DataInput;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
@@ -81,8 +77,8 @@ public final class BMPImageReader extends ImageReaderBase {
|
|||||||
super(new BMPImageReaderSpi());
|
super(new BMPImageReaderSpi());
|
||||||
}
|
}
|
||||||
|
|
||||||
BMPImageReader(final ImageReaderSpi provider) {
|
protected BMPImageReader(final ImageReaderSpi pProvider) {
|
||||||
super(provider);
|
super(pProvider);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -129,7 +125,6 @@ public final class BMPImageReader extends ImageReaderBase {
|
|||||||
|
|
||||||
// Read DIB header
|
// Read DIB header
|
||||||
header = DIBHeader.read(imageInput);
|
header = DIBHeader.read(imageInput);
|
||||||
// System.out.println("header = " + header);
|
|
||||||
|
|
||||||
if (pixelOffset < header.size + DIB.BMP_FILE_HEADER_SIZE) {
|
if (pixelOffset < header.size + DIB.BMP_FILE_HEADER_SIZE) {
|
||||||
throw new IIOException("Invalid pixel offset: " + pixelOffset);
|
throw new IIOException("Invalid pixel offset: " + pixelOffset);
|
||||||
@@ -187,30 +182,30 @@ public final class BMPImageReader extends ImageReaderBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getWidth(int imageIndex) throws IOException {
|
public int getWidth(int pImageIndex) throws IOException {
|
||||||
checkBounds(imageIndex);
|
checkBounds(pImageIndex);
|
||||||
|
|
||||||
return header.getWidth();
|
return header.getWidth();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getHeight(int imageIndex) throws IOException {
|
public int getHeight(int pImageIndex) throws IOException {
|
||||||
checkBounds(imageIndex);
|
checkBounds(pImageIndex);
|
||||||
|
|
||||||
return header.getHeight();
|
return header.getHeight();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Iterator<ImageTypeSpecifier> getImageTypes(int imageIndex) throws IOException {
|
public Iterator<ImageTypeSpecifier> getImageTypes(int pImageIndex) throws IOException {
|
||||||
checkBounds(imageIndex);
|
checkBounds(pImageIndex);
|
||||||
|
|
||||||
// TODO: Better implementation, include INT_RGB types for 3BYTE_BGR and 4BYTE_ABGR for INT_ARGB
|
// 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
|
@Override
|
||||||
public ImageTypeSpecifier getRawImageType(int imageIndex) throws IOException {
|
public ImageTypeSpecifier getRawImageType(int pImageIndex) throws IOException {
|
||||||
checkBounds(imageIndex);
|
checkBounds(pImageIndex);
|
||||||
|
|
||||||
if (header.getPlanes() != 1) {
|
if (header.getPlanes() != 1) {
|
||||||
throw new IIOException("Multiple planes not supported");
|
throw new IIOException("Multiple planes not supported");
|
||||||
@@ -363,18 +358,14 @@ public final class BMPImageReader extends ImageReaderBase {
|
|||||||
|
|
||||||
processImageStarted(imageIndex);
|
processImageStarted(imageIndex);
|
||||||
for (int y = 0; y < height; y++) {
|
for (int y = 0; y < height; y++) {
|
||||||
int bitCount = header.getBitCount();
|
switch (header.getBitCount()) {
|
||||||
switch (bitCount) {
|
|
||||||
case 1:
|
case 1:
|
||||||
case 2:
|
case 2:
|
||||||
case 4:
|
case 4:
|
||||||
case 8:
|
case 8:
|
||||||
case 24:
|
case 24:
|
||||||
byte[] rowDataByte = ((DataBufferByte) rowRaster.getDataBuffer()).getData();
|
byte[] rowDataByte = ((DataBufferByte) rowRaster.getDataBuffer()).getData();
|
||||||
int bitsPerSample = bitCount == 24 ? 8 : bitCount;
|
readRowByte(input, height, srcRegion, xSub, ySub, rowDataByte, destRaster, clippedRow, y);
|
||||||
int samplesPerPixel = bitCount == 24 ? 3 : 1;
|
|
||||||
|
|
||||||
readRowByte(input, height, srcRegion, xSub, ySub, bitsPerSample, samplesPerPixel, rowDataByte, destRaster, clippedRow, y);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 16:
|
case 16:
|
||||||
@@ -388,7 +379,7 @@ public final class BMPImageReader extends ImageReaderBase {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
throw new AssertionError("Unsupported pixel depth: " + bitCount);
|
throw new AssertionError("Unsupported pixel depth: " + header.getBitCount());
|
||||||
}
|
}
|
||||||
|
|
||||||
processImageProgress(100f * y / height);
|
processImageProgress(100f * y / height);
|
||||||
@@ -485,7 +476,6 @@ public final class BMPImageReader extends ImageReaderBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void readRowByte(final DataInput input, final int height, final Rectangle srcRegion, final int xSub, final int ySub,
|
private void readRowByte(final DataInput input, final int height, final Rectangle srcRegion, final int xSub, final int ySub,
|
||||||
int bitsPerSample, int samplesPerPixel,
|
|
||||||
final byte[] rowDataByte, final WritableRaster destChannel, final Raster srcChannel, final int y) throws IOException {
|
final byte[] rowDataByte, final WritableRaster destChannel, final Raster srcChannel, final int y) throws IOException {
|
||||||
// Flip into position?
|
// Flip into position?
|
||||||
int srcY = !header.topDown ? height - 1 - y : y;
|
int srcY = !header.topDown ? height - 1 - y : y;
|
||||||
@@ -502,7 +492,9 @@ public final class BMPImageReader extends ImageReaderBase {
|
|||||||
|
|
||||||
// Subsample horizontal
|
// Subsample horizontal
|
||||||
if (xSub != 1) {
|
if (xSub != 1) {
|
||||||
IIOUtil.subsampleRow(rowDataByte, srcRegion.x, srcRegion.width, rowDataByte, 0, samplesPerPixel, bitsPerSample, xSub);
|
for (int x = 0; x < srcRegion.width / xSub; x++) {
|
||||||
|
rowDataByte[srcRegion.x + x] = rowDataByte[srcRegion.x + x * xSub];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
destChannel.setDataElements(0, dstY, srcChannel);
|
destChannel.setDataElements(0, dstY, srcChannel);
|
||||||
@@ -686,8 +678,8 @@ public final class BMPImageReader extends ImageReaderBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings({ "unchecked", "UnusedDeclaration", "SameParameterValue" })
|
@SuppressWarnings({ "unchecked", "UnusedDeclaration", "SameParameterValue" })
|
||||||
static <T extends Throwable> void throwAs(final Class<T> type, final Throwable throwable) throws T {
|
static <T extends Throwable> void throwAs(final Class<T> pType, final Throwable pThrowable) throws T {
|
||||||
throw (T) throwable;
|
throw (T) pThrowable;
|
||||||
}
|
}
|
||||||
|
|
||||||
private class ListenerDelegator extends ProgressListenerBase implements IIOReadUpdateListener, IIOReadWarningListener {
|
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 {
|
public boolean canDecodeInput(final Object pSource) throws IOException {
|
||||||
return source instanceof ImageInputStream && canDecode((ImageInputStream) source);
|
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)
|
byte[] fileHeader = new byte[18]; // Strictly: file header (14 bytes) + BMP header size field (4 bytes)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
input.mark();
|
pInput.mark();
|
||||||
input.readFully(fileHeader);
|
pInput.readFully(fileHeader);
|
||||||
|
|
||||||
// Magic: BM
|
// Magic: BM
|
||||||
if (fileHeader[0] != 'B' || fileHeader[1] != 'M') {
|
if (fileHeader[0] != 'B' || fileHeader[1] != 'M') {
|
||||||
@@ -112,15 +112,15 @@ public final class BMPImageReaderSpi extends ImageReaderSpiBase {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
input.reset();
|
pInput.reset();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public ImageReader createReaderInstance(final Object extension) {
|
public ImageReader createReaderInstance(final Object pExtension) throws IOException {
|
||||||
return new BMPImageReader(this);
|
return new BMPImageReader(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getDescription(final Locale locale) {
|
public String getDescription(final Locale pLocale) {
|
||||||
return "Windows Device Independent Bitmap Format (BMP) Reader";
|
return "Windows Device Independent Bitmap Format (BMP) Reader";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -47,7 +47,7 @@ import java.nio.ByteOrder;
|
|||||||
* BMPImageWriter
|
* BMPImageWriter
|
||||||
*/
|
*/
|
||||||
public final class BMPImageWriter extends DIBImageWriter {
|
public final class BMPImageWriter extends DIBImageWriter {
|
||||||
BMPImageWriter(ImageWriterSpi provider) {
|
protected BMPImageWriter(ImageWriterSpi provider) {
|
||||||
super(provider);
|
super(provider);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-2
@@ -32,7 +32,6 @@ package com.twelvemonkeys.imageio.plugins.bmp;
|
|||||||
|
|
||||||
import com.twelvemonkeys.imageio.AbstractMetadata;
|
import com.twelvemonkeys.imageio.AbstractMetadata;
|
||||||
import com.twelvemonkeys.lang.Validate;
|
import com.twelvemonkeys.lang.Validate;
|
||||||
|
|
||||||
import org.w3c.dom.Node;
|
import org.w3c.dom.Node;
|
||||||
|
|
||||||
import javax.imageio.metadata.IIOMetadataNode;
|
import javax.imageio.metadata.IIOMetadataNode;
|
||||||
@@ -142,7 +141,7 @@ final class BMPMetadata extends AbstractMetadata {
|
|||||||
@Override
|
@Override
|
||||||
protected IIOMetadataNode getStandardChromaNode() {
|
protected IIOMetadataNode getStandardChromaNode() {
|
||||||
// NOTE: BMP files may contain a color map, even if true color...
|
// 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...
|
// as it might be unexpected... Then again...
|
||||||
if (colorMap != null) {
|
if (colorMap != null) {
|
||||||
IIOMetadataNode chroma = new IIOMetadataNode("Chroma");
|
IIOMetadataNode chroma = new IIOMetadataNode("Chroma");
|
||||||
|
|||||||
+7
-7
@@ -29,11 +29,11 @@
|
|||||||
*/
|
*/
|
||||||
package com.twelvemonkeys.imageio.plugins.bmp;
|
package com.twelvemonkeys.imageio.plugins.bmp;
|
||||||
|
|
||||||
import java.awt.image.*;
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
import static com.twelvemonkeys.lang.Validate.notNull;
|
import static com.twelvemonkeys.lang.Validate.notNull;
|
||||||
|
|
||||||
|
import java.awt.image.BufferedImage;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Describes a bitmap structure.
|
* Describes a bitmap structure.
|
||||||
*
|
*
|
||||||
@@ -47,9 +47,9 @@ abstract class BitmapDescriptor {
|
|||||||
protected BufferedImage image;
|
protected BufferedImage image;
|
||||||
protected BitmapMask mask;
|
protected BitmapMask mask;
|
||||||
|
|
||||||
public BitmapDescriptor(final DirectoryEntry entry, final DIBHeader header) {
|
public BitmapDescriptor(final DirectoryEntry pEntry, final DIBHeader pHeader) {
|
||||||
this.entry = notNull(entry, "entry");
|
entry = notNull(pEntry, "entry");;
|
||||||
this.header = notNull(header, "header");
|
header = notNull(pHeader, "header");
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract public BufferedImage getImage() throws IOException;
|
abstract public BufferedImage getImage() throws IOException;
|
||||||
@@ -75,7 +75,7 @@ abstract class BitmapDescriptor {
|
|||||||
return getClass().getSimpleName() + "[" + entry + ", " + header + "]";
|
return getClass().getSimpleName() + "[" + entry + ", " + header + "]";
|
||||||
}
|
}
|
||||||
|
|
||||||
final void setMask(final BitmapMask mask) {
|
public final void setMask(final BitmapMask mask) {
|
||||||
this.mask = mask;
|
this.mask = mask;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+22
-14
@@ -29,7 +29,10 @@
|
|||||||
*/
|
*/
|
||||||
package com.twelvemonkeys.imageio.plugins.bmp;
|
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;
|
import java.util.Hashtable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -38,13 +41,12 @@ import java.util.Hashtable;
|
|||||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
* @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$
|
* @version $Id: BitmapIndexed.java,v 1.0 25.feb.2006 00:29:44 haku Exp$
|
||||||
*/
|
*/
|
||||||
final class BitmapIndexed extends BitmapDescriptor {
|
class BitmapIndexed extends BitmapDescriptor {
|
||||||
final int[] bits;
|
protected final int[] bits;
|
||||||
final int[] colors;
|
protected final int[] colors;
|
||||||
|
|
||||||
public BitmapIndexed(final DirectoryEntry entry, final DIBHeader header) {
|
|
||||||
super(entry, header);
|
|
||||||
|
|
||||||
|
public BitmapIndexed(final DirectoryEntry pEntry, final DIBHeader pHeader) {
|
||||||
|
super(pEntry, pHeader);
|
||||||
bits = new int[getWidth() * getHeight()];
|
bits = new int[getWidth() * getHeight()];
|
||||||
|
|
||||||
// NOTE: We're adding space for one extra color, for transparency
|
// NOTE: We're adding space for one extra color, for transparency
|
||||||
@@ -57,16 +59,20 @@ final class BitmapIndexed extends BitmapDescriptor {
|
|||||||
|
|
||||||
IndexColorModel icm = createColorModel();
|
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;
|
Hashtable<String, Object> properties = null;
|
||||||
if (entry instanceof DirectoryEntry.CUREntry) {
|
if (entry instanceof DirectoryEntry.CUREntry) {
|
||||||
properties = new Hashtable<>(1);
|
properties = new Hashtable<>(1);
|
||||||
properties.put("cursor_hotspot", ((DirectoryEntry.CUREntry) this.entry).getHotspot());
|
properties.put("cursor_hotspot", ((DirectoryEntry.CUREntry) this.entry).getHotspot());
|
||||||
}
|
}
|
||||||
|
|
||||||
WritableRaster raster = icm.createCompatibleWritableRaster(getWidth(), getHeight());
|
BufferedImage image = new BufferedImage(
|
||||||
BufferedImage image = new BufferedImage(icm, raster, icm.isAlphaPremultiplied(), properties);
|
icm,
|
||||||
|
icm.createCompatibleWritableRaster(getWidth(), getHeight()),
|
||||||
|
icm.isAlphaPremultiplied(), properties
|
||||||
|
);
|
||||||
|
|
||||||
|
WritableRaster raster = image.getRaster();
|
||||||
|
|
||||||
// Make pixels transparent according to mask
|
// Make pixels transparent according to mask
|
||||||
final int trans = icm.getTransparentPixel();
|
final int trans = icm.getTransparentPixel();
|
||||||
@@ -99,7 +105,7 @@ final class BitmapIndexed extends BitmapDescriptor {
|
|||||||
int index = findTransparentIndexMaybeRemap(this.colors, this.bits);
|
int index = findTransparentIndexMaybeRemap(this.colors, this.bits);
|
||||||
|
|
||||||
if (index == -1) {
|
if (index == -1) {
|
||||||
// No duplicate found, increase bit count
|
// No duplicate found, increase bitcount
|
||||||
bits++;
|
bits++;
|
||||||
transparent = this.colors.length - 1;
|
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
|
// NOTE: Setting hasAlpha to true, makes things work on 1.2
|
||||||
return new IndexColorModel(bits, colors, this.colors, 0, true, transparent,
|
return new IndexColorModel(
|
||||||
bits <= 8 ? DataBuffer.TYPE_BYTE : DataBuffer.TYPE_USHORT);
|
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) {
|
private static int findTransparentIndexMaybeRemap(final int[] colors, final int[] bits) {
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user