mirror of
https://github.com/haraldk/TwelveMonkeys.git
synced 2026-05-27 00:00:02 -04:00
Compare commits
21 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| dbb7c07695 | |||
| 6840f31fa3 | |||
| debf7d0207 | |||
| 0538db7103 | |||
| 1e981242ad | |||
| 135a631bcc | |||
| f2624d5193 | |||
| ada3a84bec | |||
| 7e7aaa293e | |||
| 5d623cce9f | |||
| 055838aaaf | |||
| a8327c3c67 | |||
| 36c91f67e4 | |||
| 4cc53d822f | |||
| 9875de0383 | |||
| 6ed858a4ca | |||
| 38192ae835 | |||
| b5e8853e6b | |||
| a98224e652 | |||
| 73a58266be | |||
| edd523534c |
@@ -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"
|
|
||||||
+14
-26
@@ -1,14 +1,6 @@
|
|||||||
name: CI
|
name: CI
|
||||||
|
|
||||||
on:
|
on: [ push, pull_request ]
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- '**'
|
|
||||||
- '!dependabot/**'
|
|
||||||
pull_request:
|
|
||||||
branches: [ 'master' ]
|
|
||||||
|
|
||||||
permissions: read-all
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
test:
|
test:
|
||||||
@@ -17,22 +9,20 @@ jobs:
|
|||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
os: [ ubuntu-latest, windows-latest, macos-latest ]
|
os: [ ubuntu-latest, windows-latest, macos-latest ]
|
||||||
java: [ 8, 11, 17, 21 ]
|
java: [ 8, 11, 17, 18 ]
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
permissions:
|
|
||||||
checks: write
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
- uses: actions/checkout@v3
|
||||||
- uses: actions/setup-java@0ab4596768b603586c0de567f2430c30f5b0d2b0 # v3.13.0
|
- uses: actions/setup-java@v3
|
||||||
with:
|
with:
|
||||||
distribution: 'temurin'
|
distribution: 'temurin'
|
||||||
java-version: ${{ matrix.java }}
|
java-version: ${{ matrix.java }}
|
||||||
java-package: jdk
|
java-package: jdk
|
||||||
cache: 'maven'
|
cache: 'maven'
|
||||||
- name: Run Tests
|
- name: Run Tests
|
||||||
run: mvn --batch-mode --no-transfer-progress test
|
run: mvn test
|
||||||
- name: Publish Test Report
|
- name: Publish Test Report
|
||||||
uses: mikepenz/action-junit-report@0831a82caad2465c31c6dd929978f640cb42556c # v4.0.3
|
uses: mikepenz/action-junit-report@v3
|
||||||
if: ${{ !cancelled() }}
|
if: ${{ !cancelled() }}
|
||||||
with:
|
with:
|
||||||
report_paths: "**/target/surefire-reports/TEST*.xml"
|
report_paths: "**/target/surefire-reports/TEST*.xml"
|
||||||
@@ -41,17 +31,15 @@ jobs:
|
|||||||
test_oracle:
|
test_oracle:
|
||||||
name: Test Oracle JDK 8 with KCMS=${{ matrix.kcms }}
|
name: Test Oracle JDK 8 with KCMS=${{ matrix.kcms }}
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
permissions:
|
|
||||||
checks: write
|
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
kcms: [ true, false ]
|
kcms: [ true, false ]
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
- uses: actions/checkout@v3
|
||||||
- run: |
|
- run: |
|
||||||
download_url="https://javadl.oracle.com/webapps/download/AutoDL?BundleId=245038_d3c52aa6bfa54d3ca74e617f18309292"
|
download_url="https://javadl.oracle.com/webapps/download/AutoDL?BundleId=245038_d3c52aa6bfa54d3ca74e617f18309292"
|
||||||
wget -O $RUNNER_TEMP/java_package.tar.gz $download_url
|
wget -O $RUNNER_TEMP/java_package.tar.gz $download_url
|
||||||
- uses: actions/setup-java@0ab4596768b603586c0de567f2430c30f5b0d2b0 # v3.13.0
|
- uses: actions/setup-java@v3
|
||||||
with:
|
with:
|
||||||
distribution: 'jdkfile'
|
distribution: 'jdkfile'
|
||||||
jdkFile: ${{ runner.temp }}/java_package.tar.gz
|
jdkFile: ${{ runner.temp }}/java_package.tar.gz
|
||||||
@@ -64,9 +52,9 @@ jobs:
|
|||||||
- name: Display Java version
|
- name: Display Java version
|
||||||
run: java -version
|
run: java -version
|
||||||
- name: Run Tests
|
- name: Run Tests
|
||||||
run: mvn --batch-mode --no-transfer-progress test
|
run: mvn test
|
||||||
- name: Publish Test Report
|
- name: Publish Test Report
|
||||||
uses: mikepenz/action-junit-report@0831a82caad2465c31c6dd929978f640cb42556c # v4.0.3
|
uses: mikepenz/action-junit-report@v3
|
||||||
if: ${{ !cancelled() }}
|
if: ${{ !cancelled() }}
|
||||||
with:
|
with:
|
||||||
report_paths: "**/target/surefire-reports/TEST*.xml"
|
report_paths: "**/target/surefire-reports/TEST*.xml"
|
||||||
@@ -78,9 +66,9 @@ jobs:
|
|||||||
if: github.ref == 'refs/heads/master' # only perform on latest master
|
if: github.ref == 'refs/heads/master' # only perform on latest master
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
- uses: actions/checkout@v3
|
||||||
- name: Set up Maven Central
|
- name: Set up Maven Central
|
||||||
uses: actions/setup-java@0ab4596768b603586c0de567f2430c30f5b0d2b0 # v3.13.0
|
uses: actions/setup-java@v3
|
||||||
with: # running setup-java again overwrites the settings.xml
|
with: # running setup-java again overwrites the settings.xml
|
||||||
distribution: 'temurin'
|
distribution: 'temurin'
|
||||||
java-version: '8'
|
java-version: '8'
|
||||||
@@ -92,10 +80,10 @@ jobs:
|
|||||||
gpg-passphrase: MAVEN_CENTRAL_GPG_PASSPHRASE # env variable for GPG private key passphrase (3)
|
gpg-passphrase: MAVEN_CENTRAL_GPG_PASSPHRASE # env variable for GPG private key passphrase (3)
|
||||||
- name: Get Project Version
|
- name: Get Project Version
|
||||||
run: |
|
run: |
|
||||||
echo "PROJECT_VERSION=$(mvn --batch-mode help:evaluate -Dexpression=project.version -q -DforceStdout)" >> $GITHUB_ENV
|
echo "PROJECT_VERSION=$(mvn help:evaluate -Dexpression=project.version -q -DforceStdout)" >> $GITHUB_ENV
|
||||||
- name: Publish to Maven Central
|
- name: Publish to Maven Central
|
||||||
if: ${{ endsWith(env.PROJECT_VERSION, '-SNAPSHOT') }}
|
if: ${{ endsWith(env.PROJECT_VERSION, '-SNAPSHOT') }}
|
||||||
run: mvn --batch-mode --no-transfer-progress deploy -P release -DskipTests
|
run: mvn deploy -P release -DskipTests
|
||||||
env:
|
env:
|
||||||
MAVEN_CENTRAL_USERNAME: ${{ secrets.SONATYPE_USERNAME }} # must be the same env variable name as (1)
|
MAVEN_CENTRAL_USERNAME: ${{ secrets.SONATYPE_USERNAME }} # must be the same env variable name as (1)
|
||||||
MAVEN_CENTRAL_PASSWORD: ${{ secrets.SONATYPE_PASSWORD }} # must be the same env variable name as (2)
|
MAVEN_CENTRAL_PASSWORD: ${{ secrets.SONATYPE_PASSWORD }} # must be the same env variable name as (2)
|
||||||
|
|||||||
@@ -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@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
|
||||||
|
|
||||||
# Initializes the CodeQL tools for scanning.
|
|
||||||
- name: Initialize CodeQL
|
|
||||||
uses: github/codeql-action/init@74483a38d39275f33fcff5f35b679b5ca4a26a99 # v2.22.5
|
|
||||||
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@74483a38d39275f33fcff5f35b679b5ca4a26a99 # v2.22.5
|
|
||||||
|
|
||||||
# ℹ️ 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@74483a38d39275f33fcff5f35b679b5ca4a26a99 # v2.22.5
|
|
||||||
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@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
|
||||||
with:
|
|
||||||
persist-credentials: false
|
|
||||||
|
|
||||||
- name: "Run analysis"
|
|
||||||
uses: ossf/scorecard-action@0864cf19026789058feabb7e87baa5f140aac736 # v2.3.1
|
|
||||||
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@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
|
|
||||||
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@74483a38d39275f33fcff5f35b679b5ca4a26a99 # v2.22.5
|
|
||||||
with:
|
|
||||||
sarif_file: results.sarif
|
|
||||||
@@ -15,4 +15,3 @@ private
|
|||||||
profiles.xml
|
profiles.xml
|
||||||
Thumbs.db
|
Thumbs.db
|
||||||
.DS_Store
|
.DS_Store
|
||||||
/.metadata/
|
|
||||||
|
|||||||
@@ -1,15 +1,9 @@
|
|||||||
[](https://github.com/haraldk/TwelveMonkeys/actions/workflows/ci.yml)
|
[](https://github.com/haraldk/TwelveMonkeys/actions/workflows/ci.yml)
|
||||||
[](https://github.com/haraldk/TwelveMonkeys/actions/workflows/codeql.yml)
|
|
||||||
[](https://securityscorecards.dev/viewer/?uri=github.com/haraldk/TwelveMonkeys)
|
|
||||||
[](https://www.bestpractices.dev/projects/7900)
|
|
||||||
|
|
||||||
[](https://search.maven.org/search?q=g:com.twelvemonkeys.imageio)
|
[](https://search.maven.org/search?q=g:com.twelvemonkeys.imageio)
|
||||||
[](https://oss.sonatype.org/content/repositories/snapshots/com/twelvemonkeys/)
|
[](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.
|
||||||
@@ -278,12 +272,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.10.1</version>
|
<version>3.8.1</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.twelvemonkeys.imageio</groupId>
|
<groupId>com.twelvemonkeys.imageio</groupId>
|
||||||
<artifactId>imageio-tiff</artifactId>
|
<artifactId>imageio-tiff</artifactId>
|
||||||
<version>3.10.1</version>
|
<version>3.8.1</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
@@ -293,7 +287,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.10.1</version>
|
<version>3.8.1</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
@@ -302,7 +296,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.10.1</version>
|
<version>3.8.1</version>
|
||||||
<classifier>jakarta</classifier>
|
<classifier>jakarta</classifier>
|
||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
@@ -312,13 +306,13 @@ 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.10.1.jar
|
twelvemonkeys-common-lang-3.8.1.jar
|
||||||
twelvemonkeys-common-io-3.10.1.jar
|
twelvemonkeys-common-io-3.8.1.jar
|
||||||
twelvemonkeys-common-image-3.10.1.jar
|
twelvemonkeys-common-image-3.8.1.jar
|
||||||
twelvemonkeys-imageio-core-3.10.1.jar
|
twelvemonkeys-imageio-core-3.8.1.jar
|
||||||
twelvemonkeys-imageio-metadata-3.10.1.jar
|
twelvemonkeys-imageio-metadata-3.8.1.jar
|
||||||
twelvemonkeys-imageio-jpeg-3.10.1.jar
|
twelvemonkeys-imageio-jpeg-3.8.1.jar
|
||||||
twelvemonkeys-imageio-tiff-3.10.1.jar
|
twelvemonkeys-imageio-tiff-3.8.1.jar
|
||||||
|
|
||||||
#### Deploying the plugins in a web app
|
#### Deploying the plugins in a web app
|
||||||
|
|
||||||
@@ -384,50 +378,81 @@ Other "fat" JAR bundlers will probably have similar mechanisms to merge entries
|
|||||||
|
|
||||||
### Links to prebuilt binaries
|
### Links to prebuilt binaries
|
||||||
|
|
||||||
##### Latest version (3.10.1)
|
##### Latest version (3.8.1)
|
||||||
|
|
||||||
The latest version that will run on Java 7 is 3.9.4. Later versions will require Java 8 or later.
|
Requires Java 7 or later.
|
||||||
|
|
||||||
Common dependencies
|
Common dependencies
|
||||||
* [common-lang-3.10.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/common/common-lang/3.10.1/common-lang-3.10.1.jar)
|
* [common-lang-3.8.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/common/common-lang/3.8.1/common-lang-3.8.1.jar)
|
||||||
* [common-io-3.10.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/common/common-io/3.10.1/common-io-3.10.1.jar)
|
* [common-io-3.8.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/common/common-io/3.8.1/common-io-3.8.1.jar)
|
||||||
* [common-image-3.10.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/common/common-image/3.10.1/common-image-3.10.1.jar)
|
* [common-image-3.8.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/common/common-image/3.8.1/common-image-3.8.1.jar)
|
||||||
|
|
||||||
ImageIO dependencies
|
ImageIO dependencies
|
||||||
* [imageio-core-3.10.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-core/3.10.1/imageio-core-3.10.1.jar)
|
* [imageio-core-3.8.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-core/3.8.1/imageio-core-3.8.1.jar)
|
||||||
* [imageio-metadata-3.10.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-metadata/3.10.1/imageio-metadata-3.10.1.jar)
|
* [imageio-metadata-3.8.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-metadata/3.8.1/imageio-metadata-3.8.1.jar)
|
||||||
|
|
||||||
ImageIO plugins
|
ImageIO plugins
|
||||||
* [imageio-bmp-3.10.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-bmp/3.10.1/imageio-bmp-3.10.1.jar)
|
* [imageio-bmp-3.8.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-bmp/3.8.1/imageio-bmp-3.8.1.jar)
|
||||||
* [imageio-hdr-3.10.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-hdr/3.10.1/imageio-hdr-3.10.1.jar)
|
* [imageio-hdr-3.8.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-hdr/3.8.1/imageio-hdr-3.8.1.jar)
|
||||||
* [imageio-icns-3.10.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-icns/3.10.1/imageio-icns-3.10.1.jar)
|
* [imageio-icns-3.8.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-icns/3.8.1/imageio-icns-3.8.1.jar)
|
||||||
* [imageio-iff-3.10.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-iff/3.10.1/imageio-iff-3.10.1.jar)
|
* [imageio-iff-3.8.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-iff/3.8.1/imageio-iff-3.8.1.jar)
|
||||||
* [imageio-jpeg-3.10.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-jpeg/3.10.1/imageio-jpeg-3.10.1.jar)
|
* [imageio-jpeg-3.8.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-jpeg/3.8.1/imageio-jpeg-3.8.1.jar)
|
||||||
* [imageio-pcx-3.10.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-pcx/3.10.1/imageio-pcx-3.10.1.jar)
|
* [imageio-pcx-3.8.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-pcx/3.8.1/imageio-pcx-3.8.1.jar)
|
||||||
* [imageio-pict-3.10.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-pict/3.10.1/imageio-pict-3.10.1.jar)
|
* [imageio-pict-3.8.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-pict/3.8.1/imageio-pict-3.8.1.jar)
|
||||||
* [imageio-pnm-3.10.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-pnm/3.10.1/imageio-pnm-3.10.1.jar)
|
* [imageio-pnm-3.8.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-pnm/3.8.1/imageio-pnm-3.8.1.jar)
|
||||||
* [imageio-psd-3.10.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-psd/3.10.1/imageio-psd-3.10.1.jar)
|
* [imageio-psd-3.8.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-psd/3.8.1/imageio-psd-3.8.1.jar)
|
||||||
* [imageio-sgi-3.10.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-sgi/3.10.1/imageio-sgi-3.10.1.jar)
|
* [imageio-sgi-3.8.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-sgi/3.8.1/imageio-sgi-3.8.1.jar)
|
||||||
* [imageio-tga-3.10.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-tga/3.10.1/imageio-tga-3.10.1.jar)
|
* [imageio-tga-3.8.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-tga/3.8.1/imageio-tga-3.8.1.jar)
|
||||||
* [imageio-thumbsdb-3.10.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-thumbsdb/3.10.1/imageio-thumbsdb-3.10.1.jar)
|
* [imageio-thumbsdb-3.8.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-thumbsdb/3.8.1/imageio-thumbsdb-3.8.1.jar)
|
||||||
* [imageio-tiff-3.10.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-tiff/3.10.1/imageio-tiff-3.10.1.jar)
|
* [imageio-tiff-3.8.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-tiff/3.8.1/imageio-tiff-3.8.1.jar)
|
||||||
* [imageio-webp-3.10.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-webp/3.10.1/imageio-webp-3.10.1.jar)
|
* [imageio-webp-3.8.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-webp/3.8.1/imageio-webp-3.8.1.jar)
|
||||||
* [imageio-xwd-3.10.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-xwd/3.10.1/imageio-xwd-3.10.1.jar)
|
* [imageio-xwd-3.8.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-xwd/3.8.1/imageio-xwd-3.8.1.jar)
|
||||||
|
|
||||||
ImageIO plugins requiring 3rd party libs
|
ImageIO plugins requiring 3rd party libs
|
||||||
* [imageio-batik-3.10.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-batik/3.10.1/imageio-batik-3.10.1.jar)
|
* [imageio-batik-3.8.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-batik/3.8.1/imageio-batik-3.8.1.jar)
|
||||||
|
|
||||||
Photoshop Path support for ImageIO
|
Photoshop Path support for ImageIO
|
||||||
* [imageio-clippath-3.10.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-clippath/3.10.1/imageio-clippath-3.10.1.jar)
|
* [imageio-clippath-3.8.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-clippath/3.8.1/imageio-clippath-3.8.1.jar)
|
||||||
|
|
||||||
Servlet support
|
Servlet support
|
||||||
* [servlet-3.10.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/servlet/servlet/3.10.1/servlet-3.10.1.jar)
|
* [servlet-3.8.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/servlet/servlet/3.8.1/servlet-3.8.1.jar)
|
||||||
|
|
||||||
|
##### Old version (3.0.x)
|
||||||
|
|
||||||
|
Use this version for projects that requires Java 6 or need the JMagick support. *Does not support Java 8 or later*.
|
||||||
|
|
||||||
|
Common dependencies
|
||||||
|
* [common-lang-3.0.2.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/common/common-lang/3.0.2/common-lang-3.0.2.jar)
|
||||||
|
* [common-io-3.0.2.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/common/common-io/3.0.2/common-io-3.0.2.jar)
|
||||||
|
* [common-image-3.0.2.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/common/common-image/3.0.2/common-image-3.0.2.jar)
|
||||||
|
|
||||||
|
ImageIO dependencies
|
||||||
|
* [imageio-core-3.0.2.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-core/3.0.2/imageio-core-3.0.2.jar)
|
||||||
|
* [imageio-metadata-3.0.2.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-metadata/3.0.2/imageio-metadata-3.0.2.jar)
|
||||||
|
|
||||||
|
ImageIO plugins
|
||||||
|
* [imageio-jpeg-3.0.2.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-jpeg/3.0.2/imageio-jpeg-3.0.2.jar)
|
||||||
|
* [imageio-tiff-3.0.2.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-tiff/3.0.2/imageio-tiff-3.0.2.jar)
|
||||||
|
* [imageio-psd-3.0.2.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-psd/3.0.2/imageio-psd-3.0.2.jar)
|
||||||
|
* [imageio-pict-3.0.2.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-pict/3.0.2/imageio-pict-3.0.2.jar)
|
||||||
|
* [imageio-iff-3.0.2.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-iff/3.0.2/imageio-iff-3.0.2.jar)
|
||||||
|
* [imageio-icns-3.0.2.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-icns/3.0.2/imageio-icns-3.0.2.jar)
|
||||||
|
* [imageio-ico-3.0.2.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-ico/3.0.2/imageio-ico-3.0.2.jar)
|
||||||
|
* [imageio-thumbsdb-3.0.2.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-thumbsdb/3.0.2/imageio-thumbsdb-3.0.2.jar)
|
||||||
|
|
||||||
|
ImageIO plugins requiring 3rd party libs
|
||||||
|
* [imageio-batik-3.0.2.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-batik/3.0.2/imageio-batik-3.0.2.jar)
|
||||||
|
* [imageio-jmagick-3.0.2.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-jmagick/3.0.2/imageio-jmagick-3.0.2.jar)
|
||||||
|
|
||||||
|
Servlet support
|
||||||
|
* [servlet-3.0.2.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/servlet/servlet/3.0.2/servlet-3.0.2.jar)
|
||||||
|
|
||||||
|
|
||||||
## License
|
## 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
|
||||||
@@ -459,9 +484,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?
|
||||||
@@ -479,36 +503,22 @@ 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.
|
||||||
|
|||||||
@@ -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
-1
@@ -5,7 +5,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>com.twelvemonkeys</groupId>
|
<groupId>com.twelvemonkeys</groupId>
|
||||||
<artifactId>twelvemonkeys</artifactId>
|
<artifactId>twelvemonkeys</artifactId>
|
||||||
<version>3.11.0-SNAPSHOT</version>
|
<version>3.9.4</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<groupId>com.twelvemonkeys.bom</groupId>
|
<groupId>com.twelvemonkeys.bom</groupId>
|
||||||
|
|||||||
@@ -4,13 +4,13 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>com.twelvemonkeys.common</groupId>
|
<groupId>com.twelvemonkeys.common</groupId>
|
||||||
<artifactId>common</artifactId>
|
<artifactId>common</artifactId>
|
||||||
<version>3.11.0-SNAPSHOT</version>
|
<version>3.9.4</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>
|
||||||
@@ -36,13 +36,4 @@
|
|||||||
<scope>provided</scope>
|
<scope>provided</scope>
|
||||||
</dependency>
|
</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;
|
||||||
}
|
}
|
||||||
|
|||||||
+14
-13
@@ -34,13 +34,14 @@ import org.junit.Ignore;
|
|||||||
import org.junit.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 static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.*;
|
||||||
import static org.junit.Assert.assertNotNull;
|
|
||||||
import static org.junit.Assert.assertTrue;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* BufferedImageFactoryTestCase
|
* BufferedImageFactoryTestCase
|
||||||
@@ -259,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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -342,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();
|
||||||
@@ -379,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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -4,13 +4,13 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>com.twelvemonkeys.common</groupId>
|
<groupId>com.twelvemonkeys.common</groupId>
|
||||||
<artifactId>common</artifactId>
|
<artifactId>common</artifactId>
|
||||||
<version>3.11.0-SNAPSHOT</version>
|
<version>3.9.4</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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,114 +0,0 @@
|
|||||||
package com.twelvemonkeys.io;
|
|
||||||
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Random;
|
|
||||||
|
|
||||||
import static org.junit.Assert.assertArrayEquals;
|
|
||||||
import static org.junit.Assert.assertEquals;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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(expected = IllegalArgumentException.class)
|
|
||||||
public void testCreateNullStream() {
|
|
||||||
new SubStream(null, 42);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test(expected = IllegalArgumentException.class)
|
|
||||||
public void testCreateNegativeLength() {
|
|
||||||
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(timeout = 500L)
|
|
||||||
public void testCloseConsumesAllShortStream() throws IOException {
|
|
||||||
ByteArrayInputStream stream = new ByteArrayInputStream(new byte[13]);
|
|
||||||
|
|
||||||
try (InputStream ignore = new SubStream(stream, 42)) {
|
|
||||||
// Nothing here...
|
|
||||||
}
|
|
||||||
|
|
||||||
assertEquals(0, stream.available());
|
|
||||||
assertEquals(-1, stream.read());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -4,25 +4,17 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>com.twelvemonkeys.common</groupId>
|
<groupId>com.twelvemonkeys.common</groupId>
|
||||||
<artifactId>common</artifactId>
|
<artifactId>common</artifactId>
|
||||||
<version>3.11.0-SNAPSHOT</version>
|
<version>3.9.4</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());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -593,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);
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -4,7 +4,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>com.twelvemonkeys</groupId>
|
<groupId>com.twelvemonkeys</groupId>
|
||||||
<artifactId>twelvemonkeys</artifactId>
|
<artifactId>twelvemonkeys</artifactId>
|
||||||
<version>3.11.0-SNAPSHOT</version>
|
<version>3.9.4</version>
|
||||||
</parent>
|
</parent>
|
||||||
<groupId>com.twelvemonkeys.common</groupId>
|
<groupId>com.twelvemonkeys.common</groupId>
|
||||||
<artifactId>common</artifactId>
|
<artifactId>common</artifactId>
|
||||||
@@ -47,7 +47,7 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>junit</groupId>
|
<groupId>junit</groupId>
|
||||||
<artifactId>junit</artifactId>
|
<artifactId>junit</artifactId>
|
||||||
<version>4.13.2</version>
|
<version>4.13.1</version>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|||||||
+3
-12
@@ -4,13 +4,13 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>com.twelvemonkeys</groupId>
|
<groupId>com.twelvemonkeys</groupId>
|
||||||
<artifactId>twelvemonkeys</artifactId>
|
<artifactId>twelvemonkeys</artifactId>
|
||||||
<version>3.11.0-SNAPSHOT</version>
|
<version>3.9.4</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>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
@@ -65,17 +65,8 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>junit</groupId>
|
<groupId>junit</groupId>
|
||||||
<artifactId>junit</artifactId>
|
<artifactId>junit</artifactId>
|
||||||
<version>4.13.2</version>
|
<version>4.13.1</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>
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>com.twelvemonkeys.imageio</groupId>
|
<groupId>com.twelvemonkeys.imageio</groupId>
|
||||||
<artifactId>imageio</artifactId>
|
<artifactId>imageio</artifactId>
|
||||||
<version>3.11.0-SNAPSHOT</version>
|
<version>3.9.4</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.17</batik.version>
|
<batik.version>1.16</batik.version>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
@@ -33,18 +33,6 @@
|
|||||||
</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>
|
||||||
|
|
||||||
@@ -63,7 +51,7 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>commons-io</groupId>
|
<groupId>commons-io</groupId>
|
||||||
<artifactId>commons-io</artifactId>
|
<artifactId>commons-io</artifactId>
|
||||||
<version>2.15.0</version>
|
<version>2.11.0</version>
|
||||||
<scope>provided</scope>
|
<scope>provided</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
|||||||
+32
-34
@@ -33,7 +33,6 @@ package com.twelvemonkeys.imageio.plugins.svg;
|
|||||||
import com.twelvemonkeys.image.ImageUtil;
|
import com.twelvemonkeys.image.ImageUtil;
|
||||||
import com.twelvemonkeys.imageio.ImageReaderBase;
|
import com.twelvemonkeys.imageio.ImageReaderBase;
|
||||||
import com.twelvemonkeys.imageio.util.IIOUtil;
|
import com.twelvemonkeys.imageio.util.IIOUtil;
|
||||||
import com.twelvemonkeys.imageio.util.ImageTypeSpecifiers;
|
|
||||||
import com.twelvemonkeys.lang.StringUtil;
|
import com.twelvemonkeys.lang.StringUtil;
|
||||||
|
|
||||||
import org.apache.batik.anim.dom.SVGDOMImplementation;
|
import org.apache.batik.anim.dom.SVGDOMImplementation;
|
||||||
@@ -92,10 +91,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 +108,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,17 +139,17 @@ 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);
|
processImageStarted(pIndex);
|
||||||
|
|
||||||
BufferedImage image = rasterizer.getImage();
|
BufferedImage image = rasterizer.getImage();
|
||||||
|
|
||||||
@@ -174,18 +173,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();
|
Rectangle viewBox = rasterizer.getViewBox();
|
||||||
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, viewBox.getSize());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (size != null) {
|
if (size != null) {
|
||||||
@@ -194,7 +193,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);
|
||||||
|
|
||||||
@@ -218,7 +217,7 @@ public class SVGImageReader extends ImageReaderBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 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 +225,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 +237,19 @@ 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);
|
||||||
|
|
||||||
return rasterizer.getDefaultWidth();
|
return rasterizer.getDefaultWidth();
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getHeight(int imageIndex) throws IOException {
|
public int getHeight(int pIndex) throws IOException {
|
||||||
checkBounds(imageIndex);
|
checkBounds(pIndex);
|
||||||
return rasterizer.getDefaultHeight();
|
return rasterizer.getDefaultHeight();
|
||||||
}
|
}
|
||||||
|
|
||||||
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();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -602,7 +601,6 @@ public class SVGImageReader extends ImageReaderBase {
|
|||||||
initialized = true;
|
initialized = true;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
super.addTranscodingHint(SVGAbstractTranscoder.KEY_ALLOW_EXTERNAL_RESOURCES, allowExternalResources);
|
|
||||||
super.transcode(transcoderInput, null);
|
super.transcode(transcoderInput, null);
|
||||||
}
|
}
|
||||||
catch (TranscoderException e) {
|
catch (TranscoderException e) {
|
||||||
@@ -635,8 +633,8 @@ public class SVGImageReader extends ImageReaderBase {
|
|||||||
return viewBox.getBounds();
|
return viewBox.getBounds();
|
||||||
}
|
}
|
||||||
|
|
||||||
void setInput(final TranscoderInput input) {
|
void setInput(final TranscoderInput pInput) {
|
||||||
transcoderInput = input;
|
transcoderInput = pInput;
|
||||||
}
|
}
|
||||||
|
|
||||||
@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) {
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>com.twelvemonkeys.imageio</groupId>
|
<groupId>com.twelvemonkeys.imageio</groupId>
|
||||||
<artifactId>imageio</artifactId>
|
<artifactId>imageio</artifactId>
|
||||||
<version>3.11.0-SNAPSHOT</version>
|
<version>3.9.4</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>
|
||||||
|
|||||||
+13
-14
@@ -81,8 +81,8 @@ public final class BMPImageReader extends ImageReaderBase {
|
|||||||
super(new BMPImageReaderSpi());
|
super(new BMPImageReaderSpi());
|
||||||
}
|
}
|
||||||
|
|
||||||
BMPImageReader(final ImageReaderSpi provider) {
|
BMPImageReader(final ImageReaderSpi pProvider) {
|
||||||
super(provider);
|
super(pProvider);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -129,7 +129,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 +186,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");
|
||||||
@@ -686,8 +685,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) {
|
||||||
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) {
|
||||||
|
|||||||
+8
-8
@@ -30,7 +30,7 @@
|
|||||||
|
|
||||||
package com.twelvemonkeys.imageio.plugins.bmp;
|
package com.twelvemonkeys.imageio.plugins.bmp;
|
||||||
|
|
||||||
import java.awt.image.*;
|
import java.awt.image.BufferedImage;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -39,17 +39,17 @@ import java.awt.image.*;
|
|||||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||||
* @version $Id: BitmapMask.java,v 1.0 25.feb.2006 00:29:44 haku Exp$
|
* @version $Id: BitmapMask.java,v 1.0 25.feb.2006 00:29:44 haku Exp$
|
||||||
*/
|
*/
|
||||||
final class BitmapMask extends BitmapDescriptor {
|
class BitmapMask extends BitmapDescriptor {
|
||||||
final BitmapIndexed bitMask;
|
protected final BitmapIndexed bitMask;
|
||||||
|
|
||||||
public BitmapMask(final DirectoryEntry parent, final DIBHeader header) {
|
public BitmapMask(final DirectoryEntry pParent, final DIBHeader pHeader) {
|
||||||
super(parent, header);
|
super(pParent, pHeader);
|
||||||
bitMask = new BitmapIndexed(parent, header);
|
bitMask = new BitmapIndexed(pParent, pHeader);
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean isTransparent(final int x, final int y) {
|
boolean isTransparent(final int pX, final int pY) {
|
||||||
// NOTE: 1: Fully transparent, 0: Opaque...
|
// NOTE: 1: Fully transparent, 0: Opaque...
|
||||||
return bitMask.bits[x + y * getWidth()] != 0;
|
return bitMask.bits[pX + pY * getWidth()] != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public BufferedImage getImage() {
|
public BufferedImage getImage() {
|
||||||
|
|||||||
+6
-5
@@ -31,7 +31,8 @@
|
|||||||
package com.twelvemonkeys.imageio.plugins.bmp;
|
package com.twelvemonkeys.imageio.plugins.bmp;
|
||||||
|
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.awt.image.*;
|
import java.awt.image.BufferedImage;
|
||||||
|
import java.awt.image.WritableRaster;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Describes an RGB/true color bitmap structure (16, 24 and 32 bits per pixel).
|
* Describes an RGB/true color bitmap structure (16, 24 and 32 bits per pixel).
|
||||||
@@ -39,10 +40,10 @@ import java.awt.image.*;
|
|||||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||||
* @version $Id: BitmapRGB.java,v 1.0 25.feb.2006 00:29:44 haku Exp$
|
* @version $Id: BitmapRGB.java,v 1.0 25.feb.2006 00:29:44 haku Exp$
|
||||||
*/
|
*/
|
||||||
final class BitmapRGB extends BitmapDescriptor {
|
class BitmapRGB extends BitmapDescriptor {
|
||||||
|
|
||||||
public BitmapRGB(final DirectoryEntry entry, final DIBHeader header) {
|
public BitmapRGB(final DirectoryEntry pEntry, final DIBHeader pHeader) {
|
||||||
super(entry, header);
|
super(pEntry, pHeader);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -70,7 +71,7 @@ final class BitmapRGB extends BitmapDescriptor {
|
|||||||
|
|
||||||
WritableRaster alphaRaster = masked.getAlphaRaster();
|
WritableRaster alphaRaster = masked.getAlphaRaster();
|
||||||
|
|
||||||
byte[] trans = {0x00};
|
byte[] trans = {0x0};
|
||||||
for (int y = 0; y < getHeight(); y++) {
|
for (int y = 0; y < getHeight(); y++) {
|
||||||
for (int x = 0; x < getWidth(); x++) {
|
for (int x = 0; x < getWidth(); x++) {
|
||||||
if (mask.isTransparent(x, y)) {
|
if (mask.isTransparent(x, y)) {
|
||||||
|
|||||||
+8
-7
@@ -30,10 +30,11 @@
|
|||||||
|
|
||||||
package com.twelvemonkeys.imageio.plugins.bmp;
|
package com.twelvemonkeys.imageio.plugins.bmp;
|
||||||
|
|
||||||
import javax.imageio.IIOException;
|
import java.awt.image.BufferedImage;
|
||||||
import java.awt.image.*;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import javax.imageio.IIOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents bitmap structures we can't read.
|
* Represents bitmap structures we can't read.
|
||||||
* Allows for deferred exception handling, and allowing clients to read all images that can be read.
|
* Allows for deferred exception handling, and allowing clients to read all images that can be read.
|
||||||
@@ -41,13 +42,13 @@ import java.io.IOException;
|
|||||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||||
* @version $Id: BitmapUnsupported.java,v 1.0 25.feb.2006 00:29:44 haku Exp$
|
* @version $Id: BitmapUnsupported.java,v 1.0 25.feb.2006 00:29:44 haku Exp$
|
||||||
*/
|
*/
|
||||||
final class BitmapUnsupported extends BitmapDescriptor {
|
class BitmapUnsupported extends BitmapDescriptor {
|
||||||
private final String message;
|
private String message;
|
||||||
|
|
||||||
public BitmapUnsupported(final DirectoryEntry entry, DIBHeader header, final String message) {
|
public BitmapUnsupported(final DirectoryEntry pEntry, DIBHeader header, final String pMessage) {
|
||||||
super(entry, header);
|
super(pEntry, header);
|
||||||
|
|
||||||
this.message = message;
|
message = pMessage;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
+5
-5
@@ -48,22 +48,22 @@ public final class CURImageReader extends DIBImageReader {
|
|||||||
super(new CURImageReaderSpi());
|
super(new CURImageReaderSpi());
|
||||||
}
|
}
|
||||||
|
|
||||||
CURImageReader(final ImageReaderSpi provider) {
|
protected CURImageReader(final ImageReaderSpi pProvider) {
|
||||||
super(provider);
|
super(pProvider);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the hot spot location for the cursor.
|
* Returns the hot spot location for the cursor.
|
||||||
*
|
*
|
||||||
* @param imageIndex the index of the cursor in the current input.
|
* @param pImageIndex the index of the cursor in the current input.
|
||||||
* @return the hot spot location for the cursor
|
* @return the hot spot location for the cursor
|
||||||
*
|
*
|
||||||
* @throws java.io.IOException if an I/O exception occurs during reading of image meta data
|
* @throws java.io.IOException if an I/O exception occurs during reading of image meta data
|
||||||
* @throws IndexOutOfBoundsException if {@code pImageIndex} is less than {@code 0} or greater than/equal to
|
* @throws IndexOutOfBoundsException if {@code pImageIndex} is less than {@code 0} or greater than/equal to
|
||||||
* the number of cursors in the file
|
* the number of cursors in the file
|
||||||
*/
|
*/
|
||||||
public Point getHotSpot(final int imageIndex) throws IOException {
|
public final Point getHotSpot(final int pImageIndex) throws IOException {
|
||||||
DirectoryEntry.CUREntry entry = (DirectoryEntry.CUREntry) getEntry(imageIndex);
|
DirectoryEntry.CUREntry entry = (DirectoryEntry.CUREntry) getEntry(pImageIndex);
|
||||||
return entry.getHotspot();
|
return entry.getHotspot();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+5
-4
@@ -32,6 +32,7 @@ package com.twelvemonkeys.imageio.plugins.bmp;
|
|||||||
|
|
||||||
import com.twelvemonkeys.imageio.spi.ImageReaderSpiBase;
|
import com.twelvemonkeys.imageio.spi.ImageReaderSpiBase;
|
||||||
|
|
||||||
|
import javax.imageio.ImageReader;
|
||||||
import javax.imageio.stream.ImageInputStream;
|
import javax.imageio.stream.ImageInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
@@ -48,15 +49,15 @@ public final class CURImageReaderSpi extends ImageReaderSpiBase {
|
|||||||
super(new CURProviderInfo());
|
super(new CURProviderInfo());
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean canDecodeInput(final Object source) throws IOException {
|
public boolean canDecodeInput(final Object pSource) throws IOException {
|
||||||
return source instanceof ImageInputStream && ICOImageReaderSpi.canDecode((ImageInputStream) source, DIB.TYPE_CUR);
|
return pSource instanceof ImageInputStream && ICOImageReaderSpi.canDecode((ImageInputStream) pSource, DIB.TYPE_CUR);
|
||||||
}
|
}
|
||||||
|
|
||||||
public CURImageReader createReaderInstance(final Object extension) {
|
public ImageReader createReaderInstance(final Object pExtension) throws IOException {
|
||||||
return new CURImageReader(this);
|
return new CURImageReader(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getDescription(final Locale locale) {
|
public String getDescription(final Locale pLocale) {
|
||||||
return "Windows Cursor Format (CUR) Reader";
|
return "Windows Cursor Format (CUR) Reader";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+103
-171
@@ -30,11 +30,12 @@
|
|||||||
|
|
||||||
package com.twelvemonkeys.imageio.plugins.bmp;
|
package com.twelvemonkeys.imageio.plugins.bmp;
|
||||||
|
|
||||||
import javax.imageio.IIOException;
|
|
||||||
import java.io.DataInput;
|
import java.io.DataInput;
|
||||||
import java.io.DataOutput;
|
import java.io.DataOutput;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import javax.imageio.IIOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents the DIB (Device Independent Bitmap) Information header structure.
|
* Represents the DIB (Device Independent Bitmap) Information header structure.
|
||||||
*
|
*
|
||||||
@@ -90,17 +91,17 @@ abstract class DIBHeader {
|
|||||||
protected DIBHeader() {
|
protected DIBHeader() {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static DIBHeader read(final DataInput stream) throws IOException {
|
public static DIBHeader read(final DataInput pStream) throws IOException {
|
||||||
int size = stream.readInt();
|
int size = pStream.readInt();
|
||||||
|
|
||||||
DIBHeader header = createHeader(size);
|
DIBHeader header = createHeader(size);
|
||||||
header.read(size, stream);
|
header.read(size, pStream);
|
||||||
|
|
||||||
return header;
|
return header;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static DIBHeader createHeader(final int size) throws IOException {
|
private static DIBHeader createHeader(final int pSize) throws IOException {
|
||||||
switch (size) {
|
switch (pSize) {
|
||||||
case DIB.BITMAP_CORE_HEADER_SIZE:
|
case DIB.BITMAP_CORE_HEADER_SIZE:
|
||||||
return new BitmapCoreHeader();
|
return new BitmapCoreHeader();
|
||||||
case DIB.OS2_V2_HEADER_16_SIZE:
|
case DIB.OS2_V2_HEADER_16_SIZE:
|
||||||
@@ -117,12 +118,11 @@ abstract class DIBHeader {
|
|||||||
case DIB.BITMAP_V5_INFO_HEADER_SIZE:
|
case DIB.BITMAP_V5_INFO_HEADER_SIZE:
|
||||||
return new BitmapV5InfoHeader();
|
return new BitmapV5InfoHeader();
|
||||||
default:
|
default:
|
||||||
throw new IIOException(String.format("Unknown Bitmap Information Header (size: %s)", size));
|
throw new IIOException(String.format("Unknown Bitmap Information Header (size: %s)", pSize));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract void read(int size, DataInput stream) throws IOException;
|
protected abstract void read(int pSize, DataInput pStream) throws IOException;
|
||||||
protected abstract void write(final DataOutput stream) throws IOException;
|
|
||||||
|
|
||||||
public final int getSize() {
|
public final int getSize() {
|
||||||
return size;
|
return size;
|
||||||
@@ -189,12 +189,12 @@ abstract class DIBHeader {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int[] readMasks(final DataInput stream, final boolean hasAlphaMask) throws IOException {
|
private static int[] readMasks(final DataInput pStream, final boolean hasAlphaMask) throws IOException {
|
||||||
int maskCount = hasAlphaMask ? 4 : 3;
|
int maskCount = hasAlphaMask ? 4 : 3;
|
||||||
int[] masks = new int[4];
|
int[] masks = new int[4];
|
||||||
|
|
||||||
for (int i = 0; i < maskCount; i++) {
|
for (int i = 0; i < maskCount; i++) {
|
||||||
masks[i] = stream.readInt();
|
masks[i] = pStream.readInt();
|
||||||
}
|
}
|
||||||
|
|
||||||
return masks;
|
return masks;
|
||||||
@@ -205,30 +205,24 @@ abstract class DIBHeader {
|
|||||||
// TODO: Get rid of code duplication below...
|
// TODO: Get rid of code duplication below...
|
||||||
|
|
||||||
static final class BitmapCoreHeader extends DIBHeader {
|
static final class BitmapCoreHeader extends DIBHeader {
|
||||||
@Override
|
protected void read(final int pSize, final DataInput pStream) throws IOException {
|
||||||
protected void read(final int size, final DataInput stream) throws IOException {
|
if (pSize != DIB.BITMAP_CORE_HEADER_SIZE) {
|
||||||
if (size != DIB.BITMAP_CORE_HEADER_SIZE) {
|
throw new IIOException(String.format("Size: %s !=: %s", pSize, DIB.BITMAP_CORE_HEADER_SIZE));
|
||||||
throw new IIOException(String.format("Size: %s !=: %s", size, DIB.BITMAP_CORE_HEADER_SIZE));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.size = size;
|
size = pSize;
|
||||||
|
|
||||||
// NOTE: Unlike all other headers, width and height are unsigned SHORT values (16 bit)!
|
// NOTE: Unlike all other headers, width and height are unsigned SHORT values (16 bit)!
|
||||||
width = stream.readUnsignedShort();
|
width = pStream.readUnsignedShort();
|
||||||
height = stream.readShort();
|
height = pStream.readShort();
|
||||||
|
|
||||||
if (height < 0) {
|
if (height < 0) {
|
||||||
height = -height;
|
height = -height;
|
||||||
topDown = true;
|
topDown = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
planes = stream.readUnsignedShort();
|
planes = pStream.readUnsignedShort();
|
||||||
bitCount = stream.readUnsignedShort();
|
bitCount = pStream.readUnsignedShort();
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void write(DataOutput stream) {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getBMPVersion() {
|
public String getBMPVersion() {
|
||||||
@@ -248,51 +242,45 @@ abstract class DIBHeader {
|
|||||||
*/
|
*/
|
||||||
static final class BitmapCoreHeaderV2 extends DIBHeader {
|
static final class BitmapCoreHeaderV2 extends DIBHeader {
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
@Override
|
protected void read(final int pSize, final DataInput pStream) throws IOException {
|
||||||
protected void read(final int size, final DataInput stream) throws IOException {
|
if (pSize != DIB.OS2_V2_HEADER_SIZE && pSize != DIB.OS2_V2_HEADER_16_SIZE) {
|
||||||
if (size != DIB.OS2_V2_HEADER_SIZE && size != DIB.OS2_V2_HEADER_16_SIZE) {
|
throw new IIOException(String.format("Size: %s !=: %s", pSize, DIB.OS2_V2_HEADER_SIZE));
|
||||||
throw new IIOException(String.format("Size: %s !=: %s", size, DIB.OS2_V2_HEADER_SIZE));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.size = size;
|
size = pSize;
|
||||||
|
|
||||||
width = stream.readInt();
|
width = pStream.readInt();
|
||||||
height = stream.readInt();
|
height = pStream.readInt();
|
||||||
|
|
||||||
if (height < 0) {
|
if (height < 0) {
|
||||||
height = -height;
|
height = -height;
|
||||||
topDown = true;
|
topDown = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
planes = stream.readUnsignedShort();
|
planes = pStream.readUnsignedShort();
|
||||||
bitCount = stream.readUnsignedShort();
|
bitCount = pStream.readUnsignedShort();
|
||||||
|
|
||||||
if (size != DIB.OS2_V2_HEADER_16_SIZE) {
|
if (pSize != DIB.OS2_V2_HEADER_16_SIZE) {
|
||||||
compression = stream.readInt();
|
compression = pStream.readInt();
|
||||||
|
|
||||||
imageSize = stream.readInt();
|
imageSize = pStream.readInt();
|
||||||
|
|
||||||
xPixelsPerMeter = stream.readInt();
|
xPixelsPerMeter = pStream.readInt();
|
||||||
yPixelsPerMeter = stream.readInt();
|
yPixelsPerMeter = pStream.readInt();
|
||||||
|
|
||||||
colorsUsed = stream.readInt();
|
colorsUsed = pStream.readInt();
|
||||||
colorsImportant = stream.readInt();
|
colorsImportant = pStream.readInt();
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Use? These fields are not reflected in metadata as per now...
|
// TODO: Use? These fields are not reflected in metadata as per now...
|
||||||
int units = stream.readShort();
|
int units = pStream.readShort();
|
||||||
int reserved = stream.readShort();
|
int reserved = pStream.readShort();
|
||||||
int recording = stream.readShort(); // Recording algorithm
|
int recording = pStream.readShort(); // Recording algorithm
|
||||||
int rendering = stream.readShort(); // Halftoning algorithm
|
int rendering = pStream.readShort(); // Halftoning algorithm
|
||||||
int size1 = stream.readInt(); // Reserved for halftoning use
|
int size1 = pStream.readInt(); // Reserved for halftoning use
|
||||||
int size2 = stream.readInt(); // Reserved for halftoning use
|
int size2 = pStream.readInt(); // Reserved for halftoning use
|
||||||
int colorEncoding = stream.readInt(); // Color model used in bitmap
|
int colorEncoding = pStream.readInt(); // Color model used in bitmap
|
||||||
int identifier = stream.readInt(); // Reserved for application use
|
int identifier = pStream.readInt(); // Reserved for application use
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void write(DataOutput stream) {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getBMPVersion() {
|
public String getBMPVersion() {
|
||||||
@@ -300,6 +288,7 @@ abstract class DIBHeader {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents the DIB (Device Independent Bitmap) Windows 3.0 Bitmap Information header structure.
|
* Represents the DIB (Device Independent Bitmap) Windows 3.0 Bitmap Information header structure.
|
||||||
* This is the common format for persistent DIB structures, even if Windows
|
* This is the common format for persistent DIB structures, even if Windows
|
||||||
@@ -315,46 +304,44 @@ abstract class DIBHeader {
|
|||||||
* @see <a href="https://forums.adobe.com/message/3272950#3272950">BITMAPV3INFOHEADER</a>.
|
* @see <a href="https://forums.adobe.com/message/3272950#3272950">BITMAPV3INFOHEADER</a>.
|
||||||
*/
|
*/
|
||||||
static final class BitmapInfoHeader extends DIBHeader {
|
static final class BitmapInfoHeader extends DIBHeader {
|
||||||
@Override
|
protected void read(final int pSize, final DataInput pStream) throws IOException {
|
||||||
protected void read(final int size, final DataInput stream) throws IOException {
|
if (!(pSize == DIB.BITMAP_INFO_HEADER_SIZE || pSize == DIB.BITMAP_V2_INFO_HEADER_SIZE || pSize == DIB.BITMAP_V3_INFO_HEADER_SIZE)) {
|
||||||
if (!(size == DIB.BITMAP_INFO_HEADER_SIZE || size == DIB.BITMAP_V2_INFO_HEADER_SIZE || size == DIB.BITMAP_V3_INFO_HEADER_SIZE)) {
|
throw new IIOException(String.format("Size: %s !=: %s", pSize, DIB.BITMAP_INFO_HEADER_SIZE));
|
||||||
throw new IIOException(String.format("Size: %s !=: %s", size, DIB.BITMAP_INFO_HEADER_SIZE));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.size = size;
|
size = pSize;
|
||||||
|
|
||||||
width = stream.readInt();
|
width = pStream.readInt();
|
||||||
height = stream.readInt();
|
height = pStream.readInt();
|
||||||
|
|
||||||
if (height < 0) {
|
if (height < 0) {
|
||||||
height = -height;
|
height = -height;
|
||||||
topDown = true;
|
topDown = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
planes = stream.readUnsignedShort();
|
planes = pStream.readUnsignedShort();
|
||||||
bitCount = stream.readUnsignedShort();
|
bitCount = pStream.readUnsignedShort();
|
||||||
compression = stream.readInt();
|
compression = pStream.readInt();
|
||||||
|
|
||||||
imageSize = stream.readInt();
|
imageSize = pStream.readInt();
|
||||||
|
|
||||||
xPixelsPerMeter = stream.readInt();
|
xPixelsPerMeter = pStream.readInt();
|
||||||
yPixelsPerMeter = stream.readInt();
|
yPixelsPerMeter = pStream.readInt();
|
||||||
|
|
||||||
colorsUsed = stream.readInt();
|
colorsUsed = pStream.readInt();
|
||||||
colorsImportant = stream.readInt();
|
colorsImportant = pStream.readInt();
|
||||||
|
|
||||||
// Read masks if we have V2 or V3
|
// Read masks if we have V2 or V3
|
||||||
// or if we have compression BITFIELDS or ALPHA_BITFIELDS
|
// or if we have compression BITFIELDS or ALPHA_BITFIELDS
|
||||||
if (this.size == DIB.BITMAP_V2_INFO_HEADER_SIZE || compression == DIB.COMPRESSION_BITFIELDS) {
|
if (size == DIB.BITMAP_V2_INFO_HEADER_SIZE || compression == DIB.COMPRESSION_BITFIELDS) {
|
||||||
masks = readMasks(stream, false);
|
masks = readMasks(pStream, false);
|
||||||
}
|
}
|
||||||
else if (this.size == DIB.BITMAP_V3_INFO_HEADER_SIZE || compression == DIB.COMPRESSION_ALPHA_BITFIELDS) {
|
else if (size == DIB.BITMAP_V3_INFO_HEADER_SIZE || compression == DIB.COMPRESSION_ALPHA_BITFIELDS) {
|
||||||
masks = readMasks(stream, true);
|
masks = readMasks(pStream, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
void write(final DataOutput stream) throws IOException {
|
||||||
protected void write(final DataOutput stream) throws IOException {
|
|
||||||
stream.writeInt(DIB.BITMAP_INFO_HEADER_SIZE);
|
stream.writeInt(DIB.BITMAP_INFO_HEADER_SIZE);
|
||||||
|
|
||||||
stream.writeInt(width);
|
stream.writeInt(width);
|
||||||
@@ -372,7 +359,7 @@ abstract class DIBHeader {
|
|||||||
stream.writeInt(colorsUsed);
|
stream.writeInt(colorsUsed);
|
||||||
stream.writeInt(colorsImportant);
|
stream.writeInt(colorsImportant);
|
||||||
|
|
||||||
// TODO: Write masks, if COMPRESSION_BITFIELDS/COMPRESSION_ALPHA_BITFIELDS
|
// TODO: Write masks, if bitfields
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getBMPVersion() {
|
public String getBMPVersion() {
|
||||||
@@ -389,160 +376,105 @@ abstract class DIBHeader {
|
|||||||
* Represents the BITMAPV4INFOHEADER structure.
|
* Represents the BITMAPV4INFOHEADER structure.
|
||||||
*/
|
*/
|
||||||
static final class BitmapV4InfoHeader extends DIBHeader {
|
static final class BitmapV4InfoHeader extends DIBHeader {
|
||||||
@Override
|
protected void read(final int pSize, final DataInput pStream) throws IOException {
|
||||||
protected void read(final int size, final DataInput stream) throws IOException {
|
if (pSize != DIB.BITMAP_V4_INFO_HEADER_SIZE) {
|
||||||
if (size != DIB.BITMAP_V4_INFO_HEADER_SIZE) {
|
throw new IIOException(String.format("Size: %s !=: %s", pSize, DIB.BITMAP_V4_INFO_HEADER_SIZE));
|
||||||
throw new IIOException(String.format("Size: %s !=: %s", size, DIB.BITMAP_V4_INFO_HEADER_SIZE));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.size = size;
|
size = pSize;
|
||||||
|
|
||||||
width = stream.readInt();
|
width = pStream.readInt();
|
||||||
height = stream.readInt();
|
height = pStream.readInt();
|
||||||
|
|
||||||
if (height < 0) {
|
if (height < 0) {
|
||||||
height = -height;
|
height = -height;
|
||||||
topDown = true;
|
topDown = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
planes = stream.readUnsignedShort();
|
planes = pStream.readUnsignedShort();
|
||||||
bitCount = stream.readUnsignedShort();
|
bitCount = pStream.readUnsignedShort();
|
||||||
compression = stream.readInt();
|
compression = pStream.readInt();
|
||||||
|
|
||||||
imageSize = stream.readInt();
|
imageSize = pStream.readInt();
|
||||||
|
|
||||||
xPixelsPerMeter = stream.readInt();
|
xPixelsPerMeter = pStream.readInt();
|
||||||
yPixelsPerMeter = stream.readInt();
|
yPixelsPerMeter = pStream.readInt();
|
||||||
|
|
||||||
colorsUsed = stream.readInt();
|
colorsUsed = pStream.readInt();
|
||||||
colorsImportant = stream.readInt();
|
colorsImportant = pStream.readInt();
|
||||||
|
|
||||||
masks = readMasks(stream, true);
|
masks = readMasks(pStream, true);
|
||||||
|
|
||||||
colorSpaceType = stream.readInt(); // Should be 0 for V4
|
colorSpaceType = pStream.readInt(); // Should be 0 for V4
|
||||||
cieXYZEndpoints = new double[9];
|
cieXYZEndpoints = new double[9];
|
||||||
|
|
||||||
for (int i = 0; i < cieXYZEndpoints.length; i++) {
|
for (int i = 0; i < cieXYZEndpoints.length; i++) {
|
||||||
cieXYZEndpoints[i] = stream.readInt(); // TODO: Hmmm...?
|
cieXYZEndpoints[i] = pStream.readInt(); // TODO: Hmmm...?
|
||||||
}
|
}
|
||||||
|
|
||||||
gamma = new int[3];
|
gamma = new int[3];
|
||||||
|
|
||||||
for (int i = 0; i < gamma.length; i++) {
|
for (int i = 0; i < gamma.length; i++) {
|
||||||
gamma[i] = stream.readInt();
|
gamma[i] = pStream.readInt();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getBMPVersion() {
|
public String getBMPVersion() {
|
||||||
return "BMP v. 4.x";
|
return "BMP v. 4.x";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void write(DataOutput stream) throws IOException {
|
|
||||||
stream.writeInt(DIB.BITMAP_V4_INFO_HEADER_SIZE);
|
|
||||||
|
|
||||||
stream.writeInt(width);
|
|
||||||
stream.writeInt(topDown ? -height : height);
|
|
||||||
|
|
||||||
stream.writeShort(planes);
|
|
||||||
stream.writeShort(bitCount);
|
|
||||||
stream.writeInt(compression);
|
|
||||||
|
|
||||||
stream.writeInt(imageSize);
|
|
||||||
|
|
||||||
stream.writeInt(xPixelsPerMeter);
|
|
||||||
stream.writeInt(yPixelsPerMeter);
|
|
||||||
|
|
||||||
stream.writeInt(colorsUsed);
|
|
||||||
stream.writeInt(colorsImportant);
|
|
||||||
|
|
||||||
// Red, Green, Blue, Alpha masks
|
|
||||||
stream.writeInt(masks[0]);
|
|
||||||
stream.writeInt(masks[1]);
|
|
||||||
stream.writeInt(masks[2]);
|
|
||||||
stream.writeInt(masks[3]);
|
|
||||||
|
|
||||||
// color space ("sRGB" LITTLE endian)
|
|
||||||
stream.writeInt(DIB.LCS_sRGB);
|
|
||||||
|
|
||||||
// 36 bytes CIE XYZ triples, unused for sRGB
|
|
||||||
stream.writeInt(0);
|
|
||||||
stream.writeInt(0);
|
|
||||||
stream.writeInt(0);
|
|
||||||
|
|
||||||
stream.writeInt(0);
|
|
||||||
stream.writeInt(0);
|
|
||||||
stream.writeInt(0);
|
|
||||||
|
|
||||||
stream.writeInt(0);
|
|
||||||
stream.writeInt(0);
|
|
||||||
stream.writeInt(0);
|
|
||||||
|
|
||||||
// Red gamma, unused for sRGB
|
|
||||||
// Green gamma, unused for sRGB
|
|
||||||
// Blue gamma, unused for sRGB
|
|
||||||
stream.writeInt(0);
|
|
||||||
stream.writeInt(0);
|
|
||||||
stream.writeInt(0);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents the BITMAPV5INFOHEADER structure.
|
* Represents the BITMAPV5INFOHEADER structure.
|
||||||
*/
|
*/
|
||||||
static final class BitmapV5InfoHeader extends DIBHeader {
|
static final class BitmapV5InfoHeader extends DIBHeader {
|
||||||
protected void read(final int size, final DataInput stream) throws IOException {
|
protected void read(final int pSize, final DataInput pStream) throws IOException {
|
||||||
if (size != DIB.BITMAP_V5_INFO_HEADER_SIZE) {
|
if (pSize != DIB.BITMAP_V5_INFO_HEADER_SIZE) {
|
||||||
throw new IIOException(String.format("Size: %s !=: %s", size, DIB.BITMAP_V5_INFO_HEADER_SIZE));
|
throw new IIOException(String.format("Size: %s !=: %s", pSize, DIB.BITMAP_V5_INFO_HEADER_SIZE));
|
||||||
}
|
}
|
||||||
|
|
||||||
this.size = size;
|
size = pSize;
|
||||||
|
|
||||||
width = stream.readInt();
|
width = pStream.readInt();
|
||||||
height = stream.readInt();
|
height = pStream.readInt();
|
||||||
|
|
||||||
if (height < 0) {
|
if (height < 0) {
|
||||||
height = -height;
|
height = -height;
|
||||||
topDown = true;
|
topDown = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
planes = stream.readUnsignedShort();
|
planes = pStream.readUnsignedShort();
|
||||||
bitCount = stream.readUnsignedShort();
|
bitCount = pStream.readUnsignedShort();
|
||||||
compression = stream.readInt();
|
compression = pStream.readInt();
|
||||||
|
|
||||||
imageSize = stream.readInt();
|
imageSize = pStream.readInt();
|
||||||
|
|
||||||
xPixelsPerMeter = stream.readInt();
|
xPixelsPerMeter = pStream.readInt();
|
||||||
yPixelsPerMeter = stream.readInt();
|
yPixelsPerMeter = pStream.readInt();
|
||||||
|
|
||||||
colorsUsed = stream.readInt();
|
colorsUsed = pStream.readInt();
|
||||||
colorsImportant = stream.readInt();
|
colorsImportant = pStream.readInt();
|
||||||
|
|
||||||
masks = readMasks(stream, true);
|
masks = readMasks(pStream, true);
|
||||||
|
|
||||||
colorSpaceType = stream.readInt();
|
colorSpaceType = pStream.readInt();
|
||||||
|
|
||||||
cieXYZEndpoints = new double[9];
|
cieXYZEndpoints = new double[9];
|
||||||
|
|
||||||
for (int i = 0; i < cieXYZEndpoints.length; i++) {
|
for (int i = 0; i < cieXYZEndpoints.length; i++) {
|
||||||
cieXYZEndpoints[i] = stream.readInt(); // TODO: Hmmm...?
|
cieXYZEndpoints[i] = pStream.readInt(); // TODO: Hmmm...?
|
||||||
}
|
}
|
||||||
|
|
||||||
gamma = new int[3];
|
gamma = new int[3];
|
||||||
|
|
||||||
for (int i = 0; i < gamma.length; i++) {
|
for (int i = 0; i < gamma.length; i++) {
|
||||||
gamma[i] = stream.readInt();
|
gamma[i] = pStream.readInt();
|
||||||
}
|
}
|
||||||
|
|
||||||
intent = stream.readInt(); // TODO: Verify if this is same as ICC intent
|
intent = pStream.readInt(); // TODO: Verify if this is same as ICC intent
|
||||||
profileData = stream.readInt() & 0xffffffffL;
|
profileData = pStream.readInt() & 0xffffffffL;
|
||||||
profileSize = stream.readInt() & 0xffffffffL;
|
profileSize = pStream.readInt() & 0xffffffffL;
|
||||||
stream.readInt(); // Reserved
|
pStream.readInt(); // Reserved
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void write(DataOutput stream) {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getBMPVersion() {
|
public String getBMPVersion() {
|
||||||
|
|||||||
+155
-152
@@ -30,23 +30,10 @@
|
|||||||
|
|
||||||
package com.twelvemonkeys.imageio.plugins.bmp;
|
package com.twelvemonkeys.imageio.plugins.bmp;
|
||||||
|
|
||||||
import com.twelvemonkeys.image.ImageUtil;
|
|
||||||
import com.twelvemonkeys.imageio.ImageReaderBase;
|
|
||||||
import com.twelvemonkeys.imageio.stream.SubImageInputStream;
|
|
||||||
import com.twelvemonkeys.imageio.util.ImageTypeSpecifiers;
|
|
||||||
import com.twelvemonkeys.util.WeakWeakMap;
|
|
||||||
|
|
||||||
import javax.imageio.IIOException;
|
|
||||||
import javax.imageio.ImageIO;
|
|
||||||
import javax.imageio.ImageReadParam;
|
|
||||||
import javax.imageio.ImageReader;
|
|
||||||
import javax.imageio.ImageTypeSpecifier;
|
|
||||||
import javax.imageio.spi.ImageReaderSpi;
|
|
||||||
import javax.imageio.stream.ImageInputStream;
|
|
||||||
import javax.swing.*;
|
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.awt.color.*;
|
import java.awt.color.ColorSpace;
|
||||||
import java.awt.event.*;
|
import java.awt.event.WindowAdapter;
|
||||||
|
import java.awt.event.WindowEvent;
|
||||||
import java.awt.image.*;
|
import java.awt.image.*;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@@ -57,6 +44,21 @@ import java.util.List;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.WeakHashMap;
|
import java.util.WeakHashMap;
|
||||||
|
|
||||||
|
import javax.imageio.IIOException;
|
||||||
|
import javax.imageio.ImageIO;
|
||||||
|
import javax.imageio.ImageReadParam;
|
||||||
|
import javax.imageio.ImageReader;
|
||||||
|
import javax.imageio.ImageTypeSpecifier;
|
||||||
|
import javax.imageio.spi.ImageReaderSpi;
|
||||||
|
import javax.imageio.stream.ImageInputStream;
|
||||||
|
import javax.swing.*;
|
||||||
|
|
||||||
|
import com.twelvemonkeys.image.ImageUtil;
|
||||||
|
import com.twelvemonkeys.imageio.ImageReaderBase;
|
||||||
|
import com.twelvemonkeys.imageio.stream.SubImageInputStream;
|
||||||
|
import com.twelvemonkeys.imageio.util.ImageTypeSpecifiers;
|
||||||
|
import com.twelvemonkeys.util.WeakWeakMap;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ImageReader for Microsoft Windows ICO (icon) format.
|
* ImageReader for Microsoft Windows ICO (icon) format.
|
||||||
* 1, 4, 8 bit palette support with bitmask transparency, and 16, 24 and 32 bit
|
* 1, 4, 8 bit palette support with bitmask transparency, and 16, 24 and 32 bit
|
||||||
@@ -79,13 +81,13 @@ abstract class DIBImageReader extends ImageReaderBase {
|
|||||||
private Directory directory;
|
private Directory directory;
|
||||||
|
|
||||||
// TODO: Review these, make sure we don't have a memory leak
|
// TODO: Review these, make sure we don't have a memory leak
|
||||||
private final Map<DirectoryEntry, DIBHeader> headers = new WeakHashMap<>();
|
private Map<DirectoryEntry, DIBHeader> headers = new WeakHashMap<>();
|
||||||
private final Map<DirectoryEntry, BitmapDescriptor> descriptors = new WeakWeakMap<>();
|
private Map<DirectoryEntry, BitmapDescriptor> descriptors = new WeakWeakMap<>();
|
||||||
|
|
||||||
private ImageReader pngImageReader;
|
private ImageReader pngImageReader;
|
||||||
|
|
||||||
protected DIBImageReader(final ImageReaderSpi provider) {
|
protected DIBImageReader(final ImageReaderSpi pProvider) {
|
||||||
super(provider);
|
super(pProvider);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void resetMembers() {
|
protected void resetMembers() {
|
||||||
@@ -100,8 +102,8 @@ abstract class DIBImageReader extends ImageReaderBase {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Iterator<ImageTypeSpecifier> getImageTypes(final int imageIndex) throws IOException {
|
public Iterator<ImageTypeSpecifier> getImageTypes(final int pImageIndex) throws IOException {
|
||||||
DirectoryEntry entry = getEntry(imageIndex);
|
DirectoryEntry entry = getEntry(pImageIndex);
|
||||||
|
|
||||||
// NOTE: Delegate to PNG reader
|
// NOTE: Delegate to PNG reader
|
||||||
if (isPNG(entry)) {
|
if (isPNG(entry)) {
|
||||||
@@ -153,39 +155,39 @@ abstract class DIBImageReader extends ImageReaderBase {
|
|||||||
return getDirectory().count();
|
return getDirectory().count();
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getWidth(final int imageIndex) throws IOException {
|
public int getWidth(final int pImageIndex) throws IOException {
|
||||||
return getEntry(imageIndex).getWidth();
|
return getEntry(pImageIndex).getWidth();
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getHeight(final int imageIndex) throws IOException {
|
public int getHeight(final int pImageIndex) throws IOException {
|
||||||
return getEntry(imageIndex).getHeight();
|
return getEntry(pImageIndex).getHeight();
|
||||||
}
|
}
|
||||||
|
|
||||||
public BufferedImage read(final int imageIndex, final ImageReadParam param) throws IOException {
|
public BufferedImage read(final int pImageIndex, final ImageReadParam pParam) throws IOException {
|
||||||
checkBounds(imageIndex);
|
checkBounds(pImageIndex);
|
||||||
|
|
||||||
processImageStarted(imageIndex);
|
processImageStarted(pImageIndex);
|
||||||
|
|
||||||
DirectoryEntry entry = getEntry(imageIndex);
|
DirectoryEntry entry = getEntry(pImageIndex);
|
||||||
|
|
||||||
BufferedImage destination;
|
BufferedImage destination;
|
||||||
|
|
||||||
if (isPNG(entry)) {
|
if (isPNG(entry)) {
|
||||||
// NOTE: Special case for Windows Vista, 256x256 PNG encoded images, with no DIB header...
|
// NOTE: Special case for Windows Vista, 256x256 PNG encoded images, with no DIB header...
|
||||||
destination = readPNG(entry, param);
|
destination = readPNG(entry, pParam);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// NOTE: If param does not have explicit destination, we'll try to create a BufferedImage later,
|
// NOTE: If param does not have explicit destination, we'll try to create a BufferedImage later,
|
||||||
// to allow for storing the cursor hotspot for CUR images
|
// to allow for storing the cursor hotspot for CUR images
|
||||||
destination = hasExplicitDestination(param) ?
|
destination = hasExplicitDestination(pParam) ?
|
||||||
getDestination(param, getImageTypes(imageIndex), getWidth(imageIndex), getHeight(imageIndex)) : null;
|
getDestination(pParam, getImageTypes(pImageIndex), getWidth(pImageIndex), getHeight(pImageIndex)) : null;
|
||||||
|
|
||||||
BufferedImage image = readBitmap(entry);
|
BufferedImage image = readBitmap(entry);
|
||||||
|
|
||||||
// TODO: Handle AOI and subsampling inline, probably not of big importance...
|
// TODO: Handle AOI and subsampling inline, probably not of big importance...
|
||||||
if (param != null) {
|
if (pParam != null) {
|
||||||
image = fakeAOI(image, param);
|
image = fakeAOI(image, pParam);
|
||||||
image = ImageUtil.toBuffered(fakeSubsampling(image, param));
|
image = ImageUtil.toBuffered(fakeSubsampling(image, pParam));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (destination == null) {
|
if (destination == null) {
|
||||||
@@ -211,10 +213,10 @@ abstract class DIBImageReader extends ImageReaderBase {
|
|||||||
return destination;
|
return destination;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isPNG(final DirectoryEntry entry) throws IOException {
|
private boolean isPNG(final DirectoryEntry pEntry) throws IOException {
|
||||||
long magic;
|
long magic;
|
||||||
|
|
||||||
imageInput.seek(entry.getOffset());
|
imageInput.seek(pEntry.getOffset());
|
||||||
imageInput.setByteOrder(ByteOrder.BIG_ENDIAN);
|
imageInput.setByteOrder(ByteOrder.BIG_ENDIAN);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -227,20 +229,22 @@ abstract class DIBImageReader extends ImageReaderBase {
|
|||||||
return magic == DIB.PNG_MAGIC;
|
return magic == DIB.PNG_MAGIC;
|
||||||
}
|
}
|
||||||
|
|
||||||
private BufferedImage readPNG(final DirectoryEntry entry, final ImageReadParam param) throws IOException {
|
private BufferedImage readPNG(final DirectoryEntry pEntry, final ImageReadParam pParam) throws IOException {
|
||||||
// TODO: Consider delegating listener calls
|
// TODO: Consider delegating listener calls
|
||||||
return initPNGReader(entry).read(0, param);
|
return initPNGReader(pEntry).read(0, pParam);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Iterator<ImageTypeSpecifier> getImageTypesPNG(final DirectoryEntry entry) throws IOException {
|
private Iterator<ImageTypeSpecifier> getImageTypesPNG(final DirectoryEntry pEntry) throws IOException {
|
||||||
return initPNGReader(entry).getImageTypes(0);
|
return initPNGReader(pEntry).getImageTypes(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
private ImageReader initPNGReader(final DirectoryEntry entry) throws IOException {
|
private ImageReader initPNGReader(final DirectoryEntry pEntry) throws IOException {
|
||||||
ImageReader pngReader = getPNGReader();
|
ImageReader pngReader = getPNGReader();
|
||||||
|
|
||||||
imageInput.seek(entry.getOffset());
|
imageInput.seek(pEntry.getOffset());
|
||||||
ImageInputStream stream = new SubImageInputStream(imageInput, entry.getSize());
|
// InputStream inputStream = IIOUtil.createStreamAdapter(imageInput, pEntry.getSize());
|
||||||
|
// ImageInputStream stream = ImageIO.createImageInputStream(inputStream);
|
||||||
|
ImageInputStream stream = new SubImageInputStream(imageInput, pEntry.getSize());
|
||||||
|
|
||||||
// NOTE: Will throw IOException on later reads if input is not PNG
|
// NOTE: Will throw IOException on later reads if input is not PNG
|
||||||
pngReader.setInput(stream);
|
pngReader.setInput(stream);
|
||||||
@@ -267,31 +271,31 @@ abstract class DIBImageReader extends ImageReaderBase {
|
|||||||
return pngImageReader;
|
return pngImageReader;
|
||||||
}
|
}
|
||||||
|
|
||||||
private DIBHeader getHeader(final DirectoryEntry entry) throws IOException {
|
private DIBHeader getHeader(final DirectoryEntry pEntry) throws IOException {
|
||||||
if (!headers.containsKey(entry)) {
|
if (!headers.containsKey(pEntry)) {
|
||||||
imageInput.seek(entry.getOffset());
|
imageInput.seek(pEntry.getOffset());
|
||||||
DIBHeader header = DIBHeader.read(imageInput);
|
DIBHeader header = DIBHeader.read(imageInput);
|
||||||
headers.put(entry, header);
|
headers.put(pEntry, header);
|
||||||
}
|
}
|
||||||
|
|
||||||
return headers.get(entry);
|
return headers.get(pEntry);
|
||||||
}
|
}
|
||||||
|
|
||||||
private BufferedImage readBitmap(final DirectoryEntry entry) throws IOException {
|
private BufferedImage readBitmap(final DirectoryEntry pEntry) throws IOException {
|
||||||
// TODO: Get rid of the caching, as the images are mutable
|
// TODO: Get rid of the caching, as the images are mutable
|
||||||
BitmapDescriptor descriptor = descriptors.get(entry);
|
BitmapDescriptor descriptor = descriptors.get(pEntry);
|
||||||
|
|
||||||
if (descriptor == null || !descriptors.containsKey(entry)) {
|
if (descriptor == null || !descriptors.containsKey(pEntry)) {
|
||||||
DIBHeader header = getHeader(entry);
|
DIBHeader header = getHeader(pEntry);
|
||||||
|
|
||||||
int offset = entry.getOffset() + header.getSize();
|
int offset = pEntry.getOffset() + header.getSize();
|
||||||
if (offset != imageInput.getStreamPosition()) {
|
if (offset != imageInput.getStreamPosition()) {
|
||||||
imageInput.seek(offset);
|
imageInput.seek(offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Support this, it's already in the BMP reader, spec allows RLE4 and RLE8
|
// TODO: Support this, it's already in the BMP reader, spec allows RLE4 and RLE8
|
||||||
if (header.getCompression() != DIB.COMPRESSION_RGB) {
|
if (header.getCompression() != DIB.COMPRESSION_RGB) {
|
||||||
descriptor = new BitmapUnsupported(entry, header, String.format("Unsupported compression: %d", header.getCompression()));
|
descriptor = new BitmapUnsupported(pEntry, header, String.format("Unsupported compression: %d", header.getCompression()));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
int bitCount = header.getBitCount();
|
int bitCount = header.getBitCount();
|
||||||
@@ -301,75 +305,75 @@ abstract class DIBImageReader extends ImageReaderBase {
|
|||||||
case 1:
|
case 1:
|
||||||
case 4:
|
case 4:
|
||||||
case 8: // TODO: Gray!
|
case 8: // TODO: Gray!
|
||||||
descriptor = new BitmapIndexed(entry, header);
|
descriptor = new BitmapIndexed(pEntry, header);
|
||||||
readBitmapIndexed((BitmapIndexed) descriptor);
|
readBitmapIndexed((BitmapIndexed) descriptor);
|
||||||
break;
|
break;
|
||||||
// RGB style
|
// RGB style
|
||||||
case 16:
|
case 16:
|
||||||
descriptor = new BitmapRGB(entry, header);
|
descriptor = new BitmapRGB(pEntry, header);
|
||||||
readBitmap16(descriptor);
|
readBitmap16(descriptor);
|
||||||
break;
|
break;
|
||||||
case 24:
|
case 24:
|
||||||
descriptor = new BitmapRGB(entry, header);
|
descriptor = new BitmapRGB(pEntry, header);
|
||||||
readBitmap24(descriptor);
|
readBitmap24(descriptor);
|
||||||
break;
|
break;
|
||||||
case 32:
|
case 32:
|
||||||
descriptor = new BitmapRGB(entry, header);
|
descriptor = new BitmapRGB(pEntry, header);
|
||||||
readBitmap32(descriptor);
|
readBitmap32(descriptor);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
descriptor = new BitmapUnsupported(entry, header, String.format("Unsupported bit count %d", bitCount));
|
descriptor = new BitmapUnsupported(pEntry, header, String.format("Unsupported bit count %d", bitCount));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
descriptors.put(entry, descriptor);
|
descriptors.put(pEntry, descriptor);
|
||||||
}
|
}
|
||||||
|
|
||||||
return descriptor.getImage();
|
return descriptor.getImage();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void readBitmapIndexed(final BitmapIndexed bitmap) throws IOException {
|
private void readBitmapIndexed(final BitmapIndexed pBitmap) throws IOException {
|
||||||
readColorMap(bitmap);
|
readColorMap(pBitmap);
|
||||||
|
|
||||||
switch (bitmap.getBitCount()) {
|
switch (pBitmap.getBitCount()) {
|
||||||
case 1:
|
case 1:
|
||||||
readBitmapIndexed1(bitmap, false);
|
readBitmapIndexed1(pBitmap, false);
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
readBitmapIndexed4(bitmap);
|
readBitmapIndexed4(pBitmap);
|
||||||
break;
|
break;
|
||||||
case 8:
|
case 8:
|
||||||
readBitmapIndexed8(bitmap);
|
readBitmapIndexed8(pBitmap);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
BitmapMask mask = new BitmapMask(bitmap.entry, bitmap.header);
|
BitmapMask mask = new BitmapMask(pBitmap.entry, pBitmap.header);
|
||||||
readBitmapIndexed1(mask.bitMask, true);
|
readBitmapIndexed1(mask.bitMask, true);
|
||||||
bitmap.setMask(mask);
|
pBitmap.setMask(mask);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void readColorMap(final BitmapIndexed bitmap) throws IOException {
|
private void readColorMap(final BitmapIndexed pBitmap) throws IOException {
|
||||||
int colorCount = bitmap.getColorCount();
|
int colorCount = pBitmap.getColorCount();
|
||||||
|
|
||||||
for (int i = 0; i < colorCount; i++) {
|
for (int i = 0; i < colorCount; i++) {
|
||||||
// aRGB (a is "Reserved")
|
// aRGB (a is "Reserved")
|
||||||
bitmap.colors[i] = (imageInput.readInt() & 0xffffff) | 0xff000000;
|
pBitmap.colors[i] = (imageInput.readInt() & 0xffffff) | 0xff000000;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void readBitmapIndexed1(final BitmapIndexed bitmap, final boolean asMask) throws IOException {
|
private void readBitmapIndexed1(final BitmapIndexed pBitmap, final boolean pAsMask) throws IOException {
|
||||||
int width = adjustToPadding((bitmap.getWidth() + 7) >> 3);
|
int width = adjustToPadding((pBitmap.getWidth() + 7) >> 3);
|
||||||
byte[] row = new byte[width];
|
byte[] row = new byte[width];
|
||||||
|
|
||||||
for (int y = 0; y < bitmap.getHeight(); y++) {
|
for (int y = 0; y < pBitmap.getHeight(); y++) {
|
||||||
imageInput.readFully(row, 0, width);
|
imageInput.readFully(row, 0, width);
|
||||||
int rowPos = 0;
|
int rowPos = 0;
|
||||||
int xOrVal = 0x80;
|
int xOrVal = 0x80;
|
||||||
int pos = (bitmap.getHeight() - y - 1) * bitmap.getWidth();
|
int pos = (pBitmap.getHeight() - y - 1) * pBitmap.getWidth();
|
||||||
|
|
||||||
for (int x = 0; x < bitmap.getWidth(); x++) {
|
for (int x = 0; x < pBitmap.getWidth(); x++) {
|
||||||
bitmap.bits[pos++] = ((row[rowPos] & xOrVal) / xOrVal) & 0xFF;
|
pBitmap.bits[pos++] = ((row[rowPos] & xOrVal) / xOrVal) & 0xFF;
|
||||||
|
|
||||||
if (xOrVal == 1) {
|
if (xOrVal == 1) {
|
||||||
xOrVal = 0x80;
|
xOrVal = 0x80;
|
||||||
@@ -380,29 +384,29 @@ abstract class DIBImageReader extends ImageReaderBase {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE: If we are reading the mask, we can't abort or report progress
|
// NOTE: If we are reading the mask, we don't abort or report progress
|
||||||
if (!asMask) {
|
if (!pAsMask) {
|
||||||
if (abortRequested()) {
|
if (abortRequested()) {
|
||||||
processReadAborted();
|
processReadAborted();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
processImageProgress(100 * y / (float) bitmap.getHeight());
|
processImageProgress(100 * y / (float) pBitmap.getHeight());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void readBitmapIndexed4(final BitmapIndexed bitmap) throws IOException {
|
private void readBitmapIndexed4(final BitmapIndexed pBitmap) throws IOException {
|
||||||
int width = adjustToPadding((bitmap.getWidth() + 1) >> 1);
|
int width = adjustToPadding((pBitmap.getWidth() + 1) >> 1);
|
||||||
byte[] row = new byte[width];
|
byte[] row = new byte[width];
|
||||||
|
|
||||||
for (int y = 0; y < bitmap.getHeight(); y++) {
|
for (int y = 0; y < pBitmap.getHeight(); y++) {
|
||||||
imageInput.readFully(row, 0, width);
|
imageInput.readFully(row, 0, width);
|
||||||
int rowPos = 0;
|
int rowPos = 0;
|
||||||
boolean high4 = true;
|
boolean high4 = true;
|
||||||
int pos = (bitmap.getHeight() - y - 1) * bitmap.getWidth();
|
int pos = (pBitmap.getHeight() - y - 1) * pBitmap.getWidth();
|
||||||
|
|
||||||
for (int x = 0; x < bitmap.getWidth(); x++) {
|
for (int x = 0; x < pBitmap.getWidth(); x++) {
|
||||||
int value;
|
int value;
|
||||||
|
|
||||||
if (high4) {
|
if (high4) {
|
||||||
@@ -413,7 +417,7 @@ abstract class DIBImageReader extends ImageReaderBase {
|
|||||||
rowPos++;
|
rowPos++;
|
||||||
}
|
}
|
||||||
|
|
||||||
bitmap.bits[pos++] = value & 0xFF;
|
pBitmap.bits[pos++] = value & 0xFF;
|
||||||
high4 = !high4;
|
high4 = !high4;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -422,22 +426,22 @@ abstract class DIBImageReader extends ImageReaderBase {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
processImageProgress(100 * y / (float) bitmap.getHeight());
|
processImageProgress(100 * y / (float) pBitmap.getHeight());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void readBitmapIndexed8(final BitmapIndexed bitmap) throws IOException {
|
private void readBitmapIndexed8(final BitmapIndexed pBitmap) throws IOException {
|
||||||
int width = adjustToPadding(bitmap.getWidth());
|
int width = adjustToPadding(pBitmap.getWidth());
|
||||||
|
|
||||||
byte[] row = new byte[width];
|
byte[] row = new byte[width];
|
||||||
|
|
||||||
for (int y = 0; y < bitmap.getHeight(); y++) {
|
for (int y = 0; y < pBitmap.getHeight(); y++) {
|
||||||
imageInput.readFully(row, 0, width);
|
imageInput.readFully(row, 0, width);
|
||||||
int rowPos = 0;
|
int rowPos = 0;
|
||||||
int pos = (bitmap.getHeight() - y - 1) * bitmap.getWidth();
|
int pos = (pBitmap.getHeight() - y - 1) * pBitmap.getWidth();
|
||||||
|
|
||||||
for (int x = 0; x < bitmap.getWidth(); x++) {
|
for (int x = 0; x < pBitmap.getWidth(); x++) {
|
||||||
bitmap.bits[pos++] = row[rowPos++] & 0xFF;
|
pBitmap.bits[pos++] = row[rowPos++] & 0xFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (abortRequested()) {
|
if (abortRequested()) {
|
||||||
@@ -445,41 +449,40 @@ abstract class DIBImageReader extends ImageReaderBase {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
processImageProgress(100 * y / (float) bitmap.getHeight());
|
processImageProgress(100 * y / (float) pBitmap.getHeight());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param width Bytes per scan line (i.e., 1BPP, width = 9 -> bytes = 2)
|
* @param pWidth Bytes per scan line (i.e., 1BPP, width = 9 -> bytes = 1)
|
||||||
* @return padded width
|
* @return padded width
|
||||||
*/
|
*/
|
||||||
private static int adjustToPadding(final int width) {
|
private static int adjustToPadding(final int pWidth) {
|
||||||
if ((width & 0x03) != 0) {
|
if ((pWidth & 0x03) != 0) {
|
||||||
return (width & ~0x03) + 4;
|
return (pWidth & ~0x03) + 4;
|
||||||
}
|
}
|
||||||
|
return pWidth;
|
||||||
return width;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void readBitmap16(final BitmapDescriptor bitmap) throws IOException {
|
private void readBitmap16(final BitmapDescriptor pBitmap) throws IOException {
|
||||||
short[] pixels = new short[bitmap.getWidth() * bitmap.getHeight()];
|
short[] pixels = new short[pBitmap.getWidth() * pBitmap.getHeight()];
|
||||||
|
|
||||||
// TODO: Support TYPE_USHORT_565 and the RGB 444/ARGB 4444 layouts
|
// TODO: Support TYPE_USHORT_565 and the RGB 444/ARGB 4444 layouts
|
||||||
// Will create TYPE_USHORT_555
|
// Will create TYPE_USHORT_555
|
||||||
DirectColorModel cm = new DirectColorModel(16, 0x7C00, 0x03E0, 0x001F);
|
DirectColorModel cm = new DirectColorModel(16, 0x7C00, 0x03E0, 0x001F);
|
||||||
DataBuffer buffer = new DataBufferUShort(pixels, pixels.length);
|
DataBuffer buffer = new DataBufferUShort(pixels, pixels.length);
|
||||||
WritableRaster raster = Raster.createPackedRaster(
|
WritableRaster raster = Raster.createPackedRaster(
|
||||||
buffer, bitmap.getWidth(), bitmap.getHeight(), bitmap.getWidth(), cm.getMasks(), null
|
buffer, pBitmap.getWidth(), pBitmap.getHeight(), pBitmap.getWidth(), cm.getMasks(), null
|
||||||
);
|
);
|
||||||
bitmap.image = new BufferedImage(cm, raster, cm.isAlphaPremultiplied(), null);
|
pBitmap.image = new BufferedImage(cm, raster, cm.isAlphaPremultiplied(), null);
|
||||||
|
|
||||||
for (int y = 0; y < bitmap.getHeight(); y++) {
|
for (int y = 0; y < pBitmap.getHeight(); y++) {
|
||||||
int offset = (bitmap.getHeight() - y - 1) * bitmap.getWidth();
|
int offset = (pBitmap.getHeight() - y - 1) * pBitmap.getWidth();
|
||||||
imageInput.readFully(pixels, offset, bitmap.getWidth());
|
imageInput.readFully(pixels, offset, pBitmap.getWidth());
|
||||||
|
|
||||||
|
|
||||||
// Skip to 32 bit boundary
|
// Skip to 32 bit boundary
|
||||||
if (bitmap.getWidth() % 2 != 0) {
|
if (pBitmap.getWidth() % 2 != 0) {
|
||||||
imageInput.readShort();
|
imageInput.readShort();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -488,14 +491,14 @@ abstract class DIBImageReader extends ImageReaderBase {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
processImageProgress(100 * y / (float) bitmap.getHeight());
|
processImageProgress(100 * y / (float) pBitmap.getHeight());
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Might be mask!?
|
// TODO: Might be mask!?
|
||||||
}
|
}
|
||||||
|
|
||||||
private void readBitmap24(final BitmapDescriptor bitmap) throws IOException {
|
private void readBitmap24(final BitmapDescriptor pBitmap) throws IOException {
|
||||||
byte[] pixels = new byte[bitmap.getWidth() * bitmap.getHeight() * 3];
|
byte[] pixels = new byte[pBitmap.getWidth() * pBitmap.getHeight() * 3];
|
||||||
|
|
||||||
// Create TYPE_3BYTE_BGR
|
// Create TYPE_3BYTE_BGR
|
||||||
DataBuffer buffer = new DataBufferByte(pixels, pixels.length);
|
DataBuffer buffer = new DataBufferByte(pixels, pixels.length);
|
||||||
@@ -506,17 +509,17 @@ abstract class DIBImageReader extends ImageReaderBase {
|
|||||||
cs, nBits, false, false, Transparency.OPAQUE, DataBuffer.TYPE_BYTE
|
cs, nBits, false, false, Transparency.OPAQUE, DataBuffer.TYPE_BYTE
|
||||||
);
|
);
|
||||||
|
|
||||||
int scanlineStride = bitmap.getWidth() * 3;
|
int scanlineStride = pBitmap.getWidth() * 3;
|
||||||
// BMP rows are padded to 4 byte boundary
|
// BMP rows are padded to 4 byte boundary
|
||||||
int rowSizeBytes = ((8 * scanlineStride + 31) / 32) * 4;
|
int rowSizeBytes = ((8 * scanlineStride + 31) / 32) * 4;
|
||||||
|
|
||||||
WritableRaster raster = Raster.createInterleavedRaster(
|
WritableRaster raster = Raster.createInterleavedRaster(
|
||||||
buffer, bitmap.getWidth(), bitmap.getHeight(), scanlineStride, 3, bOffs, null
|
buffer, pBitmap.getWidth(), pBitmap.getHeight(), scanlineStride, 3, bOffs, null
|
||||||
);
|
);
|
||||||
bitmap.image = new BufferedImage(cm, raster, cm.isAlphaPremultiplied(), null);
|
pBitmap.image = new BufferedImage(cm, raster, cm.isAlphaPremultiplied(), null);
|
||||||
|
|
||||||
for (int y = 0; y < bitmap.getHeight(); y++) {
|
for (int y = 0; y < pBitmap.getHeight(); y++) {
|
||||||
int offset = (bitmap.getHeight() - y - 1) * scanlineStride;
|
int offset = (pBitmap.getHeight() - y - 1) * scanlineStride;
|
||||||
imageInput.readFully(pixels, offset, scanlineStride);
|
imageInput.readFully(pixels, offset, scanlineStride);
|
||||||
imageInput.skipBytes(rowSizeBytes - scanlineStride);
|
imageInput.skipBytes(rowSizeBytes - scanlineStride);
|
||||||
|
|
||||||
@@ -525,38 +528,38 @@ abstract class DIBImageReader extends ImageReaderBase {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
processImageProgress(100 * y / (float) bitmap.getHeight());
|
processImageProgress(100 * y / (float) pBitmap.getHeight());
|
||||||
}
|
}
|
||||||
|
|
||||||
// 24 bit icons usually have a bit mask
|
// 24 bit icons usually have a bit mask
|
||||||
if (bitmap.hasMask()) {
|
if (pBitmap.hasMask()) {
|
||||||
BitmapMask mask = new BitmapMask(bitmap.entry, bitmap.header);
|
BitmapMask mask = new BitmapMask(pBitmap.entry, pBitmap.header);
|
||||||
readBitmapIndexed1(mask.bitMask, true);
|
readBitmapIndexed1(mask.bitMask, true);
|
||||||
|
|
||||||
bitmap.setMask(mask);
|
pBitmap.setMask(mask);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void readBitmap32(final BitmapDescriptor bitmap) throws IOException {
|
private void readBitmap32(final BitmapDescriptor pBitmap) throws IOException {
|
||||||
int[] pixels = new int[bitmap.getWidth() * bitmap.getHeight()];
|
int[] pixels = new int[pBitmap.getWidth() * pBitmap.getHeight()];
|
||||||
|
|
||||||
// Will create TYPE_INT_ARGB
|
// Will create TYPE_INT_ARGB
|
||||||
DirectColorModel cm = (DirectColorModel) ColorModel.getRGBdefault();
|
DirectColorModel cm = (DirectColorModel) ColorModel.getRGBdefault();
|
||||||
DataBuffer buffer = new DataBufferInt(pixels, pixels.length);
|
DataBuffer buffer = new DataBufferInt(pixels, pixels.length);
|
||||||
WritableRaster raster = Raster.createPackedRaster(
|
WritableRaster raster = Raster.createPackedRaster(
|
||||||
buffer, bitmap.getWidth(), bitmap.getHeight(), bitmap.getWidth(), cm.getMasks(), null
|
buffer, pBitmap.getWidth(), pBitmap.getHeight(), pBitmap.getWidth(), cm.getMasks(), null
|
||||||
);
|
);
|
||||||
bitmap.image = new BufferedImage(cm, raster, cm.isAlphaPremultiplied(), null);
|
pBitmap.image = new BufferedImage(cm, raster, cm.isAlphaPremultiplied(), null);
|
||||||
|
|
||||||
for (int y = 0; y < bitmap.getHeight(); y++) {
|
for (int y = 0; y < pBitmap.getHeight(); y++) {
|
||||||
int offset = (bitmap.getHeight() - y - 1) * bitmap.getWidth();
|
int offset = (pBitmap.getHeight() - y - 1) * pBitmap.getWidth();
|
||||||
imageInput.readFully(pixels, offset, bitmap.getWidth());
|
imageInput.readFully(pixels, offset, pBitmap.getWidth());
|
||||||
|
|
||||||
if (abortRequested()) {
|
if (abortRequested()) {
|
||||||
processReadAborted();
|
processReadAborted();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
processImageProgress(100 * y / (float) bitmap.getHeight());
|
processImageProgress(100 * y / (float) pBitmap.getHeight());
|
||||||
}
|
}
|
||||||
|
|
||||||
// There might be a mask here as well, but we'll ignore it,
|
// There might be a mask here as well, but we'll ignore it,
|
||||||
@@ -587,18 +590,18 @@ abstract class DIBImageReader extends ImageReaderBase {
|
|||||||
directory = Directory.read(type, imageCount, imageInput);
|
directory = Directory.read(type, imageCount, imageInput);
|
||||||
}
|
}
|
||||||
|
|
||||||
final DirectoryEntry getEntry(final int imageIndex) throws IOException {
|
final DirectoryEntry getEntry(final int pImageIndex) throws IOException {
|
||||||
Directory directory = getDirectory();
|
Directory directory = getDirectory();
|
||||||
if (imageIndex < 0 || imageIndex >= directory.count()) {
|
if (pImageIndex < 0 || pImageIndex >= directory.count()) {
|
||||||
throw new IndexOutOfBoundsException(String.format("Index: %d, ImageCount: %d", imageIndex, directory.count()));
|
throw new IndexOutOfBoundsException(String.format("Index: %d, ImageCount: %d", pImageIndex, directory.count()));
|
||||||
}
|
}
|
||||||
|
|
||||||
return directory.getEntry(imageIndex);
|
return directory.getEntry(pImageIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Test code below, ignore.. :-)
|
/// Test code below, ignore.. :-)
|
||||||
public static void main(final String[] args) throws IOException {
|
public static void main(final String[] pArgs) throws IOException {
|
||||||
if (args.length == 0) {
|
if (pArgs.length == 0) {
|
||||||
System.err.println("Please specify the icon file name");
|
System.err.println("Please specify the icon file name");
|
||||||
System.exit(1);
|
System.exit(1);
|
||||||
}
|
}
|
||||||
@@ -610,7 +613,7 @@ abstract class DIBImageReader extends ImageReaderBase {
|
|||||||
// Ignore
|
// Ignore
|
||||||
}
|
}
|
||||||
|
|
||||||
String title = new File(args[0]).getName();
|
String title = new File(pArgs[0]).getName();
|
||||||
JFrame frame = createWindow(title);
|
JFrame frame = createWindow(title);
|
||||||
JPanel root = new JPanel(new FlowLayout());
|
JPanel root = new JPanel(new FlowLayout());
|
||||||
JScrollPane scroll =
|
JScrollPane scroll =
|
||||||
@@ -626,7 +629,7 @@ abstract class DIBImageReader extends ImageReaderBase {
|
|||||||
|
|
||||||
ImageReader reader = readers.next();
|
ImageReader reader = readers.next();
|
||||||
|
|
||||||
for (String arg : args) {
|
for (String arg : pArgs) {
|
||||||
JPanel panel = new JPanel(null);
|
JPanel panel = new JPanel(null);
|
||||||
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
|
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
|
||||||
readImagesInFile(arg, reader, panel);
|
readImagesInFile(arg, reader, panel);
|
||||||
@@ -637,28 +640,28 @@ abstract class DIBImageReader extends ImageReaderBase {
|
|||||||
frame.setVisible(true);
|
frame.setVisible(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void readImagesInFile(String fileName, ImageReader reader, final Container container) throws IOException {
|
private static void readImagesInFile(String pFileName, ImageReader pReader, final Container pContainer) throws IOException {
|
||||||
File file = new File(fileName);
|
File file = new File(pFileName);
|
||||||
if (!file.isFile()) {
|
if (!file.isFile()) {
|
||||||
System.err.println(fileName + " not found, or is no file");
|
System.err.println(pFileName + " not found, or is no file");
|
||||||
}
|
}
|
||||||
|
|
||||||
reader.setInput(ImageIO.createImageInputStream(file));
|
pReader.setInput(ImageIO.createImageInputStream(file));
|
||||||
int imageCount = reader.getNumImages(true);
|
int imageCount = pReader.getNumImages(true);
|
||||||
for (int i = 0; i < imageCount; i++) {
|
for (int i = 0; i < imageCount; i++) {
|
||||||
try {
|
try {
|
||||||
addImage(container, reader, i);
|
addImage(pContainer, pReader, i);
|
||||||
}
|
}
|
||||||
catch (Exception e) {
|
catch (Exception e) {
|
||||||
System.err.println("FileName: " + fileName);
|
System.err.println("FileName: " + pFileName);
|
||||||
System.err.println("Icon: " + i);
|
System.err.println("Icon: " + i);
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static JFrame createWindow(final String title) {
|
private static JFrame createWindow(final String pTitle) {
|
||||||
JFrame frame = new JFrame(title);
|
JFrame frame = new JFrame(pTitle);
|
||||||
frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
|
frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
|
||||||
frame.addWindowListener(new WindowAdapter() {
|
frame.addWindowListener(new WindowAdapter() {
|
||||||
public void windowClosed(WindowEvent e) {
|
public void windowClosed(WindowEvent e) {
|
||||||
@@ -668,15 +671,15 @@ abstract class DIBImageReader extends ImageReaderBase {
|
|||||||
return frame;
|
return frame;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void addImage(final Container parent, final ImageReader reader, final int imageNo) throws IOException {
|
private static void addImage(final Container pParent, final ImageReader pReader, final int pImageNo) throws IOException {
|
||||||
final JButton button = new JButton();
|
final JButton button = new JButton();
|
||||||
|
|
||||||
BufferedImage image = reader.read(imageNo);
|
BufferedImage image = pReader.read(pImageNo);
|
||||||
button.setIcon(new ImageIcon(image) {
|
button.setIcon(new ImageIcon(image) {
|
||||||
TexturePaint texture;
|
TexturePaint texture;
|
||||||
|
|
||||||
private void createTexture(final GraphicsConfiguration graphicsConfiguration) {
|
private void createTexture(final GraphicsConfiguration pGraphicsConfiguration) {
|
||||||
BufferedImage pattern = graphicsConfiguration.createCompatibleImage(20, 20);
|
BufferedImage pattern = pGraphicsConfiguration.createCompatibleImage(20, 20);
|
||||||
Graphics2D g = pattern.createGraphics();
|
Graphics2D g = pattern.createGraphics();
|
||||||
try {
|
try {
|
||||||
g.setColor(Color.LIGHT_GRAY);
|
g.setColor(Color.LIGHT_GRAY);
|
||||||
@@ -711,6 +714,6 @@ abstract class DIBImageReader extends ImageReaderBase {
|
|||||||
String.valueOf(((IndexColorModel) image.getColorModel()).getMapSize()) :
|
String.valueOf(((IndexColorModel) image.getColorModel()).getMapSize()) :
|
||||||
"TrueColor"));
|
"TrueColor"));
|
||||||
|
|
||||||
parent.add(button);
|
pParent.add(button);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+9
-10
@@ -44,25 +44,24 @@ import java.util.List;
|
|||||||
class Directory {
|
class Directory {
|
||||||
private final List<DirectoryEntry> entries;
|
private final List<DirectoryEntry> entries;
|
||||||
|
|
||||||
private Directory(int imageCount) {
|
private Directory(int pImageCount) {
|
||||||
entries = Arrays.asList(new DirectoryEntry[imageCount]);
|
entries = Arrays.asList(new DirectoryEntry[pImageCount]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Directory read(final int type, final int imageCount, final DataInput stream) throws IOException {
|
public static Directory read(final int pType, final int pImageCount, final DataInput pStream) throws IOException {
|
||||||
Directory directory = new Directory(imageCount);
|
Directory directory = new Directory(pImageCount);
|
||||||
directory.readEntries(type, stream);
|
directory.readEntries(pType, pStream);
|
||||||
|
|
||||||
return directory;
|
return directory;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void readEntries(final int type, final DataInput stream) throws IOException {
|
private void readEntries(final int pType, final DataInput pStream) throws IOException {
|
||||||
for (int i = 0; i < entries.size(); i++) {
|
for (int i = 0; i < entries.size(); i++) {
|
||||||
entries.set(i, DirectoryEntry.read(type, stream));
|
entries.set(i, DirectoryEntry.read(pType, pStream));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public DirectoryEntry getEntry(final int entryIndex) {
|
public DirectoryEntry getEntry(final int pEntryIndex) {
|
||||||
return entries.get(entryIndex);
|
return entries.get(pEntryIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int count() {
|
public int count() {
|
||||||
|
|||||||
+24
-19
@@ -32,7 +32,8 @@ package com.twelvemonkeys.imageio.plugins.bmp;
|
|||||||
|
|
||||||
import javax.imageio.IIOException;
|
import javax.imageio.IIOException;
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.awt.image.*;
|
import java.awt.image.ColorModel;
|
||||||
|
import java.awt.image.IndexColorModel;
|
||||||
import java.io.DataInput;
|
import java.io.DataInput;
|
||||||
import java.io.DataOutput;
|
import java.io.DataOutput;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@@ -57,43 +58,47 @@ abstract class DirectoryEntry {
|
|||||||
DirectoryEntry() {
|
DirectoryEntry() {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static DirectoryEntry read(final int type, final DataInput stream) throws IOException {
|
public static DirectoryEntry read(final int pType, final DataInput pStream) throws IOException {
|
||||||
DirectoryEntry entry = createEntry(type);
|
DirectoryEntry entry = createEntry(pType);
|
||||||
entry.read(stream);
|
entry.read(pStream);
|
||||||
|
|
||||||
return entry;
|
return entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static DirectoryEntry createEntry(int type) throws IIOException {
|
private static DirectoryEntry createEntry(int pType) throws IIOException {
|
||||||
switch (type) {
|
switch (pType) {
|
||||||
case DIB.TYPE_ICO:
|
case DIB.TYPE_ICO:
|
||||||
return new ICOEntry();
|
return new ICOEntry();
|
||||||
case DIB.TYPE_CUR:
|
case DIB.TYPE_CUR:
|
||||||
return new CUREntry();
|
return new CUREntry();
|
||||||
default:
|
default:
|
||||||
throw new IIOException(String.format("Unknown DIB type: %s, expected: %s (ICO) or %s (CUR)", type, DIB.TYPE_ICO, DIB.TYPE_CUR));
|
throw new IIOException(
|
||||||
|
String.format(
|
||||||
|
"Unknown DIB type: %s, expected: %s (ICO) or %s (CUR)",
|
||||||
|
pType, DIB.TYPE_ICO, DIB.TYPE_CUR
|
||||||
|
)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void read(final DataInput stream) throws IOException {
|
protected void read(final DataInput pStream) throws IOException {
|
||||||
// Width/height = 0, means 256
|
// Width/height = 0, means 256
|
||||||
int w = stream.readUnsignedByte();
|
int w = pStream.readUnsignedByte();
|
||||||
width = w == 0 ? 256 : w;
|
width = w == 0 ? 256 : w;
|
||||||
int h = stream.readUnsignedByte();
|
int h = pStream.readUnsignedByte();
|
||||||
height = h == 0 ? 256 : h;
|
height = h == 0 ? 256 : h;
|
||||||
|
|
||||||
// Color count = 0, means 256 or more colors
|
// Color count = 0, means 256 or more colors
|
||||||
colorCount = stream.readUnsignedByte();
|
colorCount = pStream.readUnsignedByte();
|
||||||
|
|
||||||
// Ignore. Should be 0, but .NET (System.Drawing.Icon.Save) sets this value to 255, according to Wikipedia
|
// Ignore. Should be 0, but .NET (System.Drawing.Icon.Save) sets this value to 255, according to Wikipedia
|
||||||
stream.readUnsignedByte();
|
pStream.readUnsignedByte();
|
||||||
|
|
||||||
planes = stream.readUnsignedShort(); // Should be 0 or 1 for ICO, x hotspot for CUR
|
planes = pStream.readUnsignedShort(); // Should be 0 or 1 for ICO, x hotspot for CUR
|
||||||
bitCount = stream.readUnsignedShort(); // bit count for ICO, y hotspot for CUR
|
bitCount = pStream.readUnsignedShort(); // bit count for ICO, y hotspot for CUR
|
||||||
|
|
||||||
// Size of bitmap in bytes
|
// Size of bitmap in bytes
|
||||||
size = stream.readInt();
|
size = pStream.readInt();
|
||||||
offset = stream.readInt();
|
offset = pStream.readInt();
|
||||||
}
|
}
|
||||||
|
|
||||||
void write(final DataOutput output) throws IOException {
|
void write(final DataOutput output) throws IOException {
|
||||||
@@ -152,8 +157,8 @@ abstract class DirectoryEntry {
|
|||||||
private int yHotspot;
|
private int yHotspot;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void read(final DataInput stream) throws IOException {
|
protected void read(final DataInput pStream) throws IOException {
|
||||||
super.read(stream);
|
super.read(pStream);
|
||||||
|
|
||||||
// NOTE: This is a hack...
|
// NOTE: This is a hack...
|
||||||
xHotspot = planes;
|
xHotspot = planes;
|
||||||
|
|||||||
+2
-2
@@ -46,7 +46,7 @@ public final class ICOImageReader extends DIBImageReader {
|
|||||||
super(new ICOImageReaderSpi());
|
super(new ICOImageReaderSpi());
|
||||||
}
|
}
|
||||||
|
|
||||||
ICOImageReader(final ImageReaderSpi provider) {
|
protected ICOImageReader(final ImageReaderSpi pProvider) {
|
||||||
super(provider);
|
super(pProvider);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+11
-10
@@ -32,6 +32,7 @@ package com.twelvemonkeys.imageio.plugins.bmp;
|
|||||||
|
|
||||||
import com.twelvemonkeys.imageio.spi.ImageReaderSpiBase;
|
import com.twelvemonkeys.imageio.spi.ImageReaderSpiBase;
|
||||||
|
|
||||||
|
import javax.imageio.ImageReader;
|
||||||
import javax.imageio.stream.ImageInputStream;
|
import javax.imageio.stream.ImageInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
@@ -48,32 +49,32 @@ public final class ICOImageReaderSpi extends ImageReaderSpiBase {
|
|||||||
super(new ICOProviderInfo());
|
super(new ICOProviderInfo());
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean canDecodeInput(final Object source) throws IOException {
|
public boolean canDecodeInput(final Object pSource) throws IOException {
|
||||||
return source instanceof ImageInputStream && canDecode((ImageInputStream) source, DIB.TYPE_ICO);
|
return pSource instanceof ImageInputStream && canDecode((ImageInputStream) pSource, DIB.TYPE_ICO);
|
||||||
}
|
}
|
||||||
|
|
||||||
static boolean canDecode(final ImageInputStream input, final int type) throws IOException {
|
static boolean canDecode(final ImageInputStream pInput, final int pType) throws IOException {
|
||||||
byte[] signature = new byte[4];
|
byte[] signature = new byte[4];
|
||||||
|
|
||||||
try {
|
try {
|
||||||
input.mark();
|
pInput.mark();
|
||||||
input.readFully(signature);
|
pInput.readFully(signature);
|
||||||
|
|
||||||
int count = input.readByte() + (input.readByte() << 8);
|
int count = pInput.readByte() + (pInput.readByte() << 8);
|
||||||
|
|
||||||
return (signature[0] == 0x0 && signature[1] == 0x0 && signature[2] == type
|
return (signature[0] == 0x0 && signature[1] == 0x0 && signature[2] == pType
|
||||||
&& signature[3] == 0x0 && count > 0);
|
&& signature[3] == 0x0 && count > 0);
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
input.reset();
|
pInput.reset();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public ICOImageReader createReaderInstance(final Object extension) {
|
public ImageReader createReaderInstance(final Object pExtension) throws IOException {
|
||||||
return new ICOImageReader(this);
|
return new ICOImageReader(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getDescription(final Locale locale) {
|
public String getDescription(final Locale pLocale) {
|
||||||
return "Windows Icon Format (ICO) Reader";
|
return "Windows Icon Format (ICO) Reader";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+6
-10
@@ -33,19 +33,15 @@ package com.twelvemonkeys.imageio.plugins.bmp;
|
|||||||
import com.twelvemonkeys.imageio.stream.SubImageOutputStream;
|
import com.twelvemonkeys.imageio.stream.SubImageOutputStream;
|
||||||
import com.twelvemonkeys.imageio.util.ProgressListenerBase;
|
import com.twelvemonkeys.imageio.util.ProgressListenerBase;
|
||||||
|
|
||||||
import javax.imageio.IIOException;
|
import javax.imageio.*;
|
||||||
import javax.imageio.IIOImage;
|
|
||||||
import javax.imageio.ImageIO;
|
|
||||||
import javax.imageio.ImageReader;
|
|
||||||
import javax.imageio.ImageTypeSpecifier;
|
|
||||||
import javax.imageio.ImageWriteParam;
|
|
||||||
import javax.imageio.ImageWriter;
|
|
||||||
import javax.imageio.event.IIOWriteWarningListener;
|
import javax.imageio.event.IIOWriteWarningListener;
|
||||||
import javax.imageio.metadata.IIOMetadata;
|
import javax.imageio.metadata.IIOMetadata;
|
||||||
import javax.imageio.spi.ImageWriterSpi;
|
import javax.imageio.spi.ImageWriterSpi;
|
||||||
import javax.imageio.stream.ImageInputStream;
|
import javax.imageio.stream.ImageInputStream;
|
||||||
import javax.imageio.stream.ImageOutputStream;
|
import javax.imageio.stream.ImageOutputStream;
|
||||||
import java.awt.image.*;
|
import java.awt.image.BufferedImage;
|
||||||
|
import java.awt.image.ColorModel;
|
||||||
|
import java.awt.image.RenderedImage;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
@@ -68,7 +64,7 @@ public final class ICOImageWriter extends DIBImageWriter {
|
|||||||
|
|
||||||
private ImageWriter pngDelegate;
|
private ImageWriter pngDelegate;
|
||||||
|
|
||||||
ICOImageWriter(final ImageWriterSpi provider) {
|
protected ICOImageWriter(final ImageWriterSpi provider) {
|
||||||
super(provider);
|
super(provider);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -128,7 +124,7 @@ public final class ICOImageWriter extends DIBImageWriter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void endWriteSequence() {
|
public void endWriteSequence() throws IOException {
|
||||||
assertOutput();
|
assertOutput();
|
||||||
|
|
||||||
if (sequenceIndex < 0) {
|
if (sequenceIndex < 0) {
|
||||||
|
|||||||
+29
-26
@@ -30,14 +30,24 @@
|
|||||||
|
|
||||||
package com.twelvemonkeys.imageio.plugins.bmp;
|
package com.twelvemonkeys.imageio.plugins.bmp;
|
||||||
|
|
||||||
import com.twelvemonkeys.imageio.util.ImageReaderAbstractTest;
|
import static org.junit.Assert.*;
|
||||||
import com.twelvemonkeys.xml.XMLSerializer;
|
import static org.junit.Assume.assumeNoException;
|
||||||
|
import static org.mockito.ArgumentMatchers.anyFloat;
|
||||||
|
import static org.mockito.ArgumentMatchers.eq;
|
||||||
|
import static org.mockito.Mockito.atLeastOnce;
|
||||||
|
import static org.mockito.Mockito.inOrder;
|
||||||
|
import static org.mockito.Mockito.mock;
|
||||||
|
|
||||||
import org.junit.Ignore;
|
import java.awt.*;
|
||||||
import org.junit.Test;
|
import java.awt.image.BufferedImage;
|
||||||
import org.mockito.InOrder;
|
import java.io.ByteArrayOutputStream;
|
||||||
import org.w3c.dom.Node;
|
import java.io.IOException;
|
||||||
import org.w3c.dom.NodeList;
|
import java.lang.reflect.Constructor;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import javax.imageio.IIOException;
|
import javax.imageio.IIOException;
|
||||||
import javax.imageio.ImageIO;
|
import javax.imageio.ImageIO;
|
||||||
@@ -47,25 +57,16 @@ import javax.imageio.ImageTypeSpecifier;
|
|||||||
import javax.imageio.event.IIOReadProgressListener;
|
import javax.imageio.event.IIOReadProgressListener;
|
||||||
import javax.imageio.metadata.IIOMetadata;
|
import javax.imageio.metadata.IIOMetadata;
|
||||||
import javax.imageio.metadata.IIOMetadataNode;
|
import javax.imageio.metadata.IIOMetadataNode;
|
||||||
import javax.imageio.spi.IIORegistry;
|
|
||||||
import javax.imageio.spi.ImageReaderSpi;
|
import javax.imageio.spi.ImageReaderSpi;
|
||||||
import java.awt.*;
|
|
||||||
import java.awt.image.*;
|
|
||||||
import java.io.ByteArrayOutputStream;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.nio.charset.StandardCharsets;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import static org.junit.Assert.*;
|
import org.junit.Ignore;
|
||||||
import static org.junit.Assume.assumeNoException;
|
import org.junit.Test;
|
||||||
import static org.mockito.ArgumentMatchers.anyFloat;
|
import org.mockito.InOrder;
|
||||||
import static org.mockito.ArgumentMatchers.eq;
|
import org.w3c.dom.Node;
|
||||||
import static org.mockito.Mockito.atLeastOnce;
|
import org.w3c.dom.NodeList;
|
||||||
import static org.mockito.Mockito.inOrder;
|
|
||||||
import static org.mockito.Mockito.mock;
|
import com.twelvemonkeys.imageio.util.ImageReaderAbstractTest;
|
||||||
|
import com.twelvemonkeys.xml.XMLSerializer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* BMPImageReaderTest
|
* BMPImageReaderTest
|
||||||
@@ -325,8 +326,10 @@ public class BMPImageReaderTest extends ImageReaderAbstractTest<BMPImageReader>
|
|||||||
public void testMetadataEqualsJRE() throws IOException {
|
public void testMetadataEqualsJRE() throws IOException {
|
||||||
ImageReader jreReader;
|
ImageReader jreReader;
|
||||||
try {
|
try {
|
||||||
ImageReaderSpi provider = (ImageReaderSpi) IIORegistry.getDefaultInstance().getServiceProviderByClass(Class.forName("com.sun.imageio.plugins.bmp.BMPImageReaderSpi"));
|
@SuppressWarnings("unchecked")
|
||||||
jreReader = provider.createReaderInstance();
|
Class<ImageReader> jreReaderClass = (Class<ImageReader>) Class.forName("com.sun.imageio.plugins.bmp.BMPImageReader");
|
||||||
|
Constructor<ImageReader> constructor = jreReaderClass.getConstructor(ImageReaderSpi.class);
|
||||||
|
jreReader = constructor.newInstance(new Object[] {null});
|
||||||
}
|
}
|
||||||
catch (Exception e) {
|
catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>com.twelvemonkeys.imageio</groupId>
|
<groupId>com.twelvemonkeys.imageio</groupId>
|
||||||
<artifactId>imageio</artifactId>
|
<artifactId>imageio</artifactId>
|
||||||
<version>3.11.0-SNAPSHOT</version>
|
<version>3.9.4</version>
|
||||||
</parent>
|
</parent>
|
||||||
<artifactId>imageio-clippath</artifactId>
|
<artifactId>imageio-clippath</artifactId>
|
||||||
<name>TwelveMonkeys :: ImageIO :: Photoshop Path Support</name>
|
<name>TwelveMonkeys :: ImageIO :: Photoshop Path Support</name>
|
||||||
@@ -32,13 +32,4 @@
|
|||||||
<artifactId>imageio-metadata</artifactId>
|
<artifactId>imageio-metadata</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
|
||||||
<plugins>
|
|
||||||
<plugin>
|
|
||||||
<groupId>org.apache.felix</groupId>
|
|
||||||
<artifactId>maven-bundle-plugin</artifactId>
|
|
||||||
</plugin>
|
|
||||||
</plugins>
|
|
||||||
</build>
|
|
||||||
</project>
|
</project>
|
||||||
|
|||||||
@@ -42,7 +42,6 @@ import com.twelvemonkeys.imageio.metadata.tiff.TIFF;
|
|||||||
import com.twelvemonkeys.imageio.metadata.tiff.TIFFReader;
|
import com.twelvemonkeys.imageio.metadata.tiff.TIFFReader;
|
||||||
import com.twelvemonkeys.imageio.stream.ByteArrayImageInputStream;
|
import com.twelvemonkeys.imageio.stream.ByteArrayImageInputStream;
|
||||||
import com.twelvemonkeys.imageio.stream.SubImageInputStream;
|
import com.twelvemonkeys.imageio.stream.SubImageInputStream;
|
||||||
import com.twelvemonkeys.imageio.util.ImageTypeSpecifiers;
|
|
||||||
|
|
||||||
import javax.imageio.*;
|
import javax.imageio.*;
|
||||||
import javax.imageio.metadata.IIOMetadata;
|
import javax.imageio.metadata.IIOMetadata;
|
||||||
@@ -308,7 +307,7 @@ public final class Paths {
|
|||||||
throw new IllegalArgumentException("output == null!");
|
throw new IllegalArgumentException("output == null!");
|
||||||
}
|
}
|
||||||
|
|
||||||
ImageTypeSpecifier type = ImageTypeSpecifiers.createFromRenderedImage(image);
|
ImageTypeSpecifier type = ImageTypeSpecifier.createFromRenderedImage(image);
|
||||||
Iterator<ImageWriter> writers = ImageIO.getImageWriters(type, formatName);
|
Iterator<ImageWriter> writers = ImageIO.getImageWriters(type, formatName);
|
||||||
|
|
||||||
if (writers.hasNext()) {
|
if (writers.hasNext()) {
|
||||||
|
|||||||
@@ -4,13 +4,10 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>com.twelvemonkeys.imageio</groupId>
|
<groupId>com.twelvemonkeys.imageio</groupId>
|
||||||
<artifactId>imageio</artifactId>
|
<artifactId>imageio</artifactId>
|
||||||
<version>3.11.0-SNAPSHOT</version>
|
<version>3.9.4</version>
|
||||||
</parent>
|
</parent>
|
||||||
<artifactId>imageio-core</artifactId>
|
<artifactId>imageio-core</artifactId>
|
||||||
<name>TwelveMonkeys :: ImageIO :: Core</name>
|
<name>TwelveMonkeys :: ImageIO :: Core</name>
|
||||||
<description>
|
|
||||||
TwelveMonkeys ImageIO core support classes.
|
|
||||||
</description>
|
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<project.jpms.module.name>com.twelvemonkeys.imageio.core</project.jpms.module.name>
|
<project.jpms.module.name>com.twelvemonkeys.imageio.core</project.jpms.module.name>
|
||||||
@@ -31,20 +28,4 @@
|
|||||||
</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.ImageInputStreamSpi
|
|
||||||
</Provide-Capability>
|
|
||||||
</instructions>
|
|
||||||
</configuration>
|
|
||||||
</plugin>
|
|
||||||
</plugins>
|
|
||||||
</build>
|
|
||||||
</project>
|
</project>
|
||||||
|
|||||||
@@ -188,7 +188,7 @@ public final class ColorSpaces {
|
|||||||
// Will throw IllegalArgumentException or CMMException if the profile is bad
|
// Will throw IllegalArgumentException or CMMException if the profile is bad
|
||||||
cs.fromRGB(new float[] {0.999f, 0.5f, 0.001f});
|
cs.fromRGB(new float[] {0.999f, 0.5f, 0.001f});
|
||||||
|
|
||||||
// This breaks *sometimes* after validation of bad profiles,
|
// This breaks *some times* after validation of bad profiles,
|
||||||
// we'll let it blow up early in this case
|
// we'll let it blow up early in this case
|
||||||
cs.getProfile().getData();
|
cs.getProfile().getData();
|
||||||
}
|
}
|
||||||
|
|||||||
+9
-11
@@ -257,18 +257,18 @@ public final class ImageTypeSpecifiers {
|
|||||||
return createFromIndexColorModel(new IndexColorModel(bits, colors.length, colors, 0, hasAlpha, transIndex, dataType));
|
return createFromIndexColorModel(new IndexColorModel(bits, colors.length, colors, 0, hasAlpha, transIndex, dataType));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ImageTypeSpecifier createFromIndexColorModel(final IndexColorModel colorModel) {
|
public static ImageTypeSpecifier createFromIndexColorModel(final IndexColorModel pColorModel) {
|
||||||
return new IndexedImageTypeSpecifier(colorModel);
|
return new IndexedImageTypeSpecifier(pColorModel);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ImageTypeSpecifier createDiscreteAlphaIndexedFromIndexColorModel(final IndexColorModel colorModel) {
|
public static ImageTypeSpecifier createDiscreteAlphaIndexedFromIndexColorModel(final IndexColorModel pColorModel) {
|
||||||
ColorModel discreteAlphaIndexColorModel = new DiscreteAlphaIndexColorModel(colorModel);
|
ColorModel colorModel = new DiscreteAlphaIndexColorModel(pColorModel);
|
||||||
return new ImageTypeSpecifier(discreteAlphaIndexColorModel, discreteAlphaIndexColorModel.createCompatibleSampleModel(1, 1));
|
return new ImageTypeSpecifier(colorModel, colorModel.createCompatibleSampleModel(1, 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ImageTypeSpecifier createDiscreteExtraSamplesIndexedFromIndexColorModel(final IndexColorModel colorModel, int extraSamples, boolean hasAlpha) {
|
public static ImageTypeSpecifier createDiscreteExtraSamplesIndexedFromIndexColorModel(final IndexColorModel pColorModel, int extraSamples, boolean hasAlpha) {
|
||||||
ColorModel discreteAlphaIndexColorModel = new DiscreteAlphaIndexColorModel(colorModel, extraSamples, hasAlpha);
|
ColorModel colorModel = new DiscreteAlphaIndexColorModel(pColorModel, extraSamples, hasAlpha);
|
||||||
return new ImageTypeSpecifier(discreteAlphaIndexColorModel, discreteAlphaIndexColorModel.createCompatibleSampleModel(1, 1));
|
return new ImageTypeSpecifier(colorModel, colorModel.createCompatibleSampleModel(1, 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ImageTypeSpecifier createFromRenderedImage(RenderedImage image) {
|
public static ImageTypeSpecifier createFromRenderedImage(RenderedImage image) {
|
||||||
@@ -279,9 +279,7 @@ public final class ImageTypeSpecifiers {
|
|||||||
if (image instanceof BufferedImage) {
|
if (image instanceof BufferedImage) {
|
||||||
int bufferedImageType = ((BufferedImage) image).getType();
|
int bufferedImageType = ((BufferedImage) image).getType();
|
||||||
|
|
||||||
if (bufferedImageType != BufferedImage.TYPE_CUSTOM &&
|
if (bufferedImageType != BufferedImage.TYPE_CUSTOM) {
|
||||||
// Need to retain the actual palette in the color model for IndexColorModel
|
|
||||||
bufferedImageType != BufferedImage.TYPE_BYTE_BINARY && bufferedImageType != BufferedImage.TYPE_BYTE_INDEXED) {
|
|
||||||
return createFromBufferedImageType(bufferedImageType);
|
return createFromBufferedImageType(bufferedImageType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -52,12 +52,12 @@ final class IndexedImageTypeSpecifier extends ImageTypeSpecifier {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BufferedImage createBufferedImage(final int width, final int height) {
|
public final BufferedImage createBufferedImage(final int pWidth, final int pHeight) {
|
||||||
try {
|
try {
|
||||||
// This is a fix for the super-method, that first creates a sample model, and then
|
// This is a fix for the super-method, that first creates a sample model, and then
|
||||||
// creates a raster from it, using Raster.createWritableRaster. The problem with
|
// creates a raster from it, using Raster.createWritableRaster. The problem with
|
||||||
// that approach, is that it always creates a TYPE_CUSTOM BufferedImage for indexed images.
|
// that approach, is that it always creates a TYPE_CUSTOM BufferedImage for indexed images.
|
||||||
WritableRaster raster = colorModel.createCompatibleWritableRaster(width, height);
|
WritableRaster raster = colorModel.createCompatibleWritableRaster(pWidth, pHeight);
|
||||||
return new BufferedImage(colorModel, raster, colorModel.isAlphaPremultiplied(), null);
|
return new BufferedImage(colorModel, raster, colorModel.isAlphaPremultiplied(), null);
|
||||||
}
|
}
|
||||||
catch (NegativeArraySizeException e) {
|
catch (NegativeArraySizeException e) {
|
||||||
|
|||||||
+1
-2
@@ -17,7 +17,6 @@ import java.util.Arrays;
|
|||||||
import java.util.Calendar;
|
import java.util.Calendar;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.LinkedHashMap;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
@@ -171,7 +170,7 @@ public class StandardImageMetadataSupportTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void withTextValuesMap() {
|
public void withTextValuesMap() {
|
||||||
Map<String, String> entries = new LinkedHashMap<>();
|
Map<String, String> entries = new HashMap<>();
|
||||||
entries.put("foo", "bar");
|
entries.put("foo", "bar");
|
||||||
entries.put("bar", "xyzzy");
|
entries.put("bar", "xyzzy");
|
||||||
|
|
||||||
|
|||||||
-15
@@ -36,11 +36,9 @@ import java.awt.color.ColorSpace;
|
|||||||
import java.awt.color.ICC_ColorSpace;
|
import java.awt.color.ICC_ColorSpace;
|
||||||
import java.awt.color.ICC_Profile;
|
import java.awt.color.ICC_Profile;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.lang.reflect.Method;
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
|
||||||
import static org.junit.Assert.assertArrayEquals;
|
import static org.junit.Assert.assertArrayEquals;
|
||||||
import static org.junit.Assume.assumeFalse;
|
|
||||||
import static org.mockito.Mockito.*;
|
import static org.mockito.Mockito.*;
|
||||||
|
|
||||||
public class KCMSSanitizerStrategyTest {
|
public class KCMSSanitizerStrategyTest {
|
||||||
@@ -58,8 +56,6 @@ public class KCMSSanitizerStrategyTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testFixProfileUpdateHeader() throws Exception {
|
public void testFixProfileUpdateHeader() throws Exception {
|
||||||
assumeICC_ProfileNotSealed(); // Ignores test for JDK 19+
|
|
||||||
|
|
||||||
byte[] header = new byte[128];
|
byte[] header = new byte[128];
|
||||||
header[ICC_Profile.icHdrRenderingIntent + 3] = 1;
|
header[ICC_Profile.icHdrRenderingIntent + 3] = 1;
|
||||||
ICC_Profile profile = mock(ICC_Profile.class);
|
ICC_Profile profile = mock(ICC_Profile.class);
|
||||||
@@ -73,17 +69,6 @@ public class KCMSSanitizerStrategyTest {
|
|||||||
verify(profile).setData(eq(ICC_Profile.icSigHead), any(byte[].class));
|
verify(profile).setData(eq(ICC_Profile.icSigHead), any(byte[].class));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void assumeICC_ProfileNotSealed() {
|
|
||||||
try {
|
|
||||||
Method isSealed = Class.class.getMethod("isSealed");
|
|
||||||
Boolean result = (Boolean) isSealed.invoke(ICC_Profile.class);
|
|
||||||
assumeFalse("Can't mock ICC_Profile, class is sealed (as of JDK 19).", result);
|
|
||||||
}
|
|
||||||
catch (ReflectiveOperationException ignore) {
|
|
||||||
// We can't have sealed classes if we don't have the isSealed method...
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testFixProfileCorbisRGB() throws IOException {
|
public void testFixProfileCorbisRGB() throws IOException {
|
||||||
// TODO: Consider re-writing this using mocks, to avoid dependencies on the CMS implementation
|
// TODO: Consider re-writing this using mocks, to avoid dependencies on the CMS implementation
|
||||||
|
|||||||
-3
@@ -34,7 +34,6 @@ import org.junit.Test;
|
|||||||
|
|
||||||
import java.awt.color.ICC_Profile;
|
import java.awt.color.ICC_Profile;
|
||||||
|
|
||||||
import static com.twelvemonkeys.imageio.color.KCMSSanitizerStrategyTest.assumeICC_ProfileNotSealed;
|
|
||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
import static org.mockito.Mockito.verifyNoMoreInteractions;
|
import static org.mockito.Mockito.verifyNoMoreInteractions;
|
||||||
|
|
||||||
@@ -47,8 +46,6 @@ public class LCMSSanitizerStrategyTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testFixProfile() throws Exception {
|
public void testFixProfile() throws Exception {
|
||||||
assumeICC_ProfileNotSealed(); // Ignores test for JDK 19+
|
|
||||||
|
|
||||||
ICC_Profile profile = mock(ICC_Profile.class);
|
ICC_Profile profile = mock(ICC_Profile.class);
|
||||||
new LCMSSanitizerStrategy().fixProfile(profile);
|
new LCMSSanitizerStrategy().fixProfile(profile);
|
||||||
|
|
||||||
|
|||||||
+45
-50
@@ -31,7 +31,6 @@
|
|||||||
package com.twelvemonkeys.imageio.util;
|
package com.twelvemonkeys.imageio.util;
|
||||||
|
|
||||||
import com.twelvemonkeys.imageio.stream.URLImageInputStreamSpi;
|
import com.twelvemonkeys.imageio.stream.URLImageInputStreamSpi;
|
||||||
import com.twelvemonkeys.lang.Validate;
|
|
||||||
|
|
||||||
import org.junit.Ignore;
|
import org.junit.Ignore;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
@@ -39,18 +38,14 @@ import org.mockito.InOrder;
|
|||||||
import org.mockito.invocation.InvocationOnMock;
|
import org.mockito.invocation.InvocationOnMock;
|
||||||
import org.mockito.stubbing.Answer;
|
import org.mockito.stubbing.Answer;
|
||||||
|
|
||||||
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.IIOReadProgressListener;
|
import javax.imageio.event.IIOReadProgressListener;
|
||||||
import javax.imageio.metadata.IIOMetadata;
|
import javax.imageio.metadata.IIOMetadata;
|
||||||
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.awt.*;
|
import java.awt.*;
|
||||||
import java.awt.geom.*;
|
import java.awt.geom.AffineTransform;
|
||||||
import java.awt.image.*;
|
import java.awt.image.*;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@@ -58,7 +53,6 @@ import java.lang.reflect.ParameterizedType;
|
|||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@@ -608,7 +602,7 @@ public abstract class ImageReaderAbstractTest<T extends ImageReader> {
|
|||||||
assertReadWithSourceRegionParamEqualImage(new Rectangle(3, 3, 9, 9), getTestData().get(0), 0);
|
assertReadWithSourceRegionParamEqualImage(new Rectangle(3, 3, 9, 9), getTestData().get(0), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void assertReadWithSourceRegionParamEqualImage(final Rectangle r, final TestData data, @SuppressWarnings("SameParameterValue") final int imageIndex) throws IOException {
|
protected void assertReadWithSourceRegionParamEqualImage(final Rectangle r, final TestData data, final int imageIndex) throws IOException {
|
||||||
ImageReader reader = createReader();
|
ImageReader reader = createReader();
|
||||||
try (ImageInputStream inputStream = data.getInputStream()) {
|
try (ImageInputStream inputStream = data.getInputStream()) {
|
||||||
reader.setInput(inputStream);
|
reader.setInput(inputStream);
|
||||||
@@ -1834,51 +1828,52 @@ public abstract class ImageReaderAbstractTest<T extends ImageReader> {
|
|||||||
private final List<Dimension> sizes;
|
private final List<Dimension> sizes;
|
||||||
private final List<BufferedImage> images;
|
private final List<BufferedImage> images;
|
||||||
|
|
||||||
public TestData(final Object input, final Dimension... dimensions) {
|
public TestData(final Object pInput, final Dimension... pSizes) {
|
||||||
this(input, Arrays.asList(dimensions), null);
|
this(pInput, Arrays.asList(pSizes), null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public TestData(final Object input, final BufferedImage... images) {
|
public TestData(final Object pInput, final BufferedImage... pImages) {
|
||||||
this(input, null, Arrays.asList(images));
|
this(pInput, null, Arrays.asList(pImages));
|
||||||
}
|
}
|
||||||
|
|
||||||
public TestData(final Object input, final List<Dimension> dimensions, final List<BufferedImage> images) {
|
public TestData(final Object pInput, final List<Dimension> pSizes, final List<BufferedImage> pImages) {
|
||||||
Validate.notNull(input, "input");
|
if (pInput == null) {
|
||||||
Validate.isTrue(dimensions != null || images != null, "Need either dimensions or image");
|
throw new IllegalArgumentException("input == null");
|
||||||
|
|
||||||
List<Dimension> combinedDimensions;
|
|
||||||
if (dimensions == null) {
|
|
||||||
// Copy dimensions from images
|
|
||||||
combinedDimensions = new ArrayList<>(images.size());
|
|
||||||
|
|
||||||
for (BufferedImage image : images) {
|
|
||||||
combinedDimensions.add(new Dimension(image.getWidth(), image.getHeight()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// Validate equal dimensions
|
|
||||||
if (images != null) {
|
|
||||||
if (images.size() != dimensions.size()) {
|
|
||||||
throw new IllegalArgumentException("Dimensions and images parameter's size differs");
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < dimensions.size(); i++) {
|
|
||||||
if (!new Dimension(images.get(i).getWidth(), images.get(i).getHeight()).equals(dimensions.get(i))) {
|
|
||||||
throw new IllegalArgumentException("Dimensions and images parameter's dimensions differ");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
combinedDimensions = new ArrayList<>(dimensions);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.sizes = Collections.unmodifiableList(combinedDimensions);
|
sizes = new ArrayList<>();
|
||||||
|
images = new ArrayList<>();
|
||||||
|
|
||||||
this.images = images != null
|
List<Dimension> sizes = pSizes;
|
||||||
? Collections.unmodifiableList(new ArrayList<>(images))
|
if (sizes == null) {
|
||||||
: Collections.<BufferedImage>emptyList();
|
sizes = new ArrayList<>();
|
||||||
|
if (pImages != null) {
|
||||||
|
for (BufferedImage image : pImages) {
|
||||||
|
sizes.add(new Dimension(image.getWidth(), image.getHeight()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw new IllegalArgumentException("Need either size or image");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (pImages != null) {
|
||||||
|
if (pImages.size() != pSizes.size()) {
|
||||||
|
throw new IllegalArgumentException("Size parameter and image size differs");
|
||||||
|
}
|
||||||
|
for (int i = 0; i < sizes.size(); i++) {
|
||||||
|
if (!new Dimension(pImages.get(i).getWidth(), pImages.get(i).getHeight()).equals(sizes.get(i))) {
|
||||||
|
throw new IllegalArgumentException("Size parameter and image size differs");
|
||||||
|
}
|
||||||
|
|
||||||
this.input = input;
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.sizes.addAll(sizes);
|
||||||
|
if (pImages != null) {
|
||||||
|
images.addAll(pImages);
|
||||||
|
}
|
||||||
|
|
||||||
|
input = pInput;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Object getInput() {
|
public Object getInput() {
|
||||||
@@ -1903,13 +1898,13 @@ public abstract class ImageReaderAbstractTest<T extends ImageReader> {
|
|||||||
return sizes.size();
|
return sizes.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Dimension getDimension(final int index) {
|
public Dimension getDimension(final int pIndex) {
|
||||||
return sizes.get(index);
|
return sizes.get(pIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
public BufferedImage getImage(final int index) {
|
public BufferedImage getImage(final int pIndex) {
|
||||||
return images.get(index);
|
return images.get(pIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
+2
-35
@@ -39,7 +39,6 @@ import java.awt.color.*;
|
|||||||
import java.awt.image.*;
|
import java.awt.image.*;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
import static org.junit.Assert.assertSame;
|
|
||||||
|
|
||||||
public class ImageTypeSpecifiersTest {
|
public class ImageTypeSpecifiersTest {
|
||||||
|
|
||||||
@@ -737,7 +736,6 @@ public class ImageTypeSpecifiersTest {
|
|||||||
ImageTypeSpecifier fromType = ImageTypeSpecifiers.createFromBufferedImageType(type);
|
ImageTypeSpecifier fromType = ImageTypeSpecifiers.createFromBufferedImageType(type);
|
||||||
|
|
||||||
assertEquals(fromConstructor.getColorModel(), fromType.getColorModel());
|
assertEquals(fromConstructor.getColorModel(), fromType.getColorModel());
|
||||||
assertEquals(fromConstructor.getSampleModel(), fromType.getSampleModel());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -749,43 +747,13 @@ public class ImageTypeSpecifiersTest {
|
|||||||
ImageTypeSpecifier fromImage = ImageTypeSpecifiers.createFromRenderedImage(image);
|
ImageTypeSpecifier fromImage = ImageTypeSpecifiers.createFromRenderedImage(image);
|
||||||
|
|
||||||
assertEquals(fromConstructor.getColorModel(), fromImage.getColorModel());
|
assertEquals(fromConstructor.getColorModel(), fromImage.getColorModel());
|
||||||
assertEquals(fromConstructor.getSampleModel(), fromImage.getSampleModel());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testCreateFromRenderedImageIndexedBinaryShouldRetainPalette() {
|
|
||||||
IndexColorModel whiteIsZero = new IndexColorModel(1, 2, new int[]{0xFFFFFFFF, 0xFF000000}, 0, false, -1, DataBuffer.TYPE_BYTE);
|
|
||||||
|
|
||||||
BufferedImage image = new BufferedImage(1, 1, BufferedImage.TYPE_BYTE_BINARY, whiteIsZero);
|
|
||||||
ImageTypeSpecifier fromImage = ImageTypeSpecifiers.createFromRenderedImage(image);
|
|
||||||
|
|
||||||
assertEquals(whiteIsZero, fromImage.getColorModel());
|
|
||||||
assertSame(whiteIsZero, fromImage.getColorModel()); // Note: This can be relaxed to asserting the LUTs are equal
|
|
||||||
assertEquals(image.getSampleModel(), fromImage.getSampleModel());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testCreateFromRenderedImageIndexedShouldRetainPalette() {
|
|
||||||
IndexColorModel palette = new IndexColorModel(4, 16, new int[]{
|
|
||||||
0xFFFFFFFF, 0xFF999999, 0xFF666666, 0xFF333333,
|
|
||||||
0xFF000000, 0xFF00202E, 0xFF003F5C, 0xFF2C4875,
|
|
||||||
0xFF8A508F, 0xFFBC5090, 0xFFFF6361, 0xFFFF8531,
|
|
||||||
0xFFFFA600, 0xFFFFD380, 0xFF74A892, 0xFF008585
|
|
||||||
}, 0, false, -1, DataBuffer.TYPE_BYTE);
|
|
||||||
|
|
||||||
BufferedImage image = new BufferedImage(1, 1, BufferedImage.TYPE_BYTE_INDEXED, palette);
|
|
||||||
ImageTypeSpecifier fromImage = ImageTypeSpecifiers.createFromRenderedImage(image);
|
|
||||||
|
|
||||||
assertEquals(palette, fromImage.getColorModel());
|
|
||||||
assertSame(palette, fromImage.getColorModel()); // Note: This can be relaxed to asserting the LUTs are equal
|
|
||||||
assertEquals(image.getSampleModel(), fromImage.getSampleModel());
|
|
||||||
}
|
|
||||||
|
|
||||||
private static byte[] createByteLut(final int count) {
|
private static byte[] createByteLut(final int count) {
|
||||||
byte[] lut = new byte[count];
|
byte[] lut = new byte[count];
|
||||||
for (int i = 0; i < count; i++) {
|
for (int i = 0; i < count; i++) {
|
||||||
lut[i] = (byte) (i * 255 / count);
|
lut[i] = (byte) count;
|
||||||
}
|
}
|
||||||
return lut;
|
return lut;
|
||||||
}
|
}
|
||||||
@@ -794,8 +762,7 @@ public class ImageTypeSpecifiersTest {
|
|||||||
int[] lut = new int[count];
|
int[] lut = new int[count];
|
||||||
|
|
||||||
for (int i = 0; i < count; i++) {
|
for (int i = 0; i < count; i++) {
|
||||||
int val = (i * 255 / count);
|
lut[i] = 0xff000000 | count << 16 | count << 8 | count;
|
||||||
lut[i] = 0xff000000 | val << 16 | val << 8 | val;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return lut;
|
return lut;
|
||||||
|
|||||||
+5
-7
@@ -43,17 +43,15 @@ import javax.imageio.spi.IIORegistry;
|
|||||||
import javax.imageio.spi.ImageWriterSpi;
|
import javax.imageio.spi.ImageWriterSpi;
|
||||||
import javax.imageio.stream.ImageOutputStream;
|
import javax.imageio.stream.ImageOutputStream;
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.awt.image.*;
|
import java.awt.image.BufferedImage;
|
||||||
|
import java.awt.image.RenderedImage;
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.lang.reflect.ParameterizedType;
|
import java.lang.reflect.ParameterizedType;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.*;
|
||||||
import static org.junit.Assert.assertNotNull;
|
|
||||||
import static org.junit.Assert.assertTrue;
|
|
||||||
import static org.junit.Assert.fail;
|
|
||||||
import static org.mockito.Mockito.*;
|
import static org.mockito.Mockito.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -110,8 +108,8 @@ public abstract class ImageWriterAbstractTest<T extends ImageWriter> {
|
|||||||
return getTestData().get(index);
|
return getTestData().get(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected URL getClassLoaderResource(final String name) {
|
protected URL getClassLoaderResource(final String pName) {
|
||||||
return getClass().getResource(name);
|
return getClass().getResource(pName);
|
||||||
}
|
}
|
||||||
|
|
||||||
@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.11.0-SNAPSHOT</version>
|
<version>3.9.4</version>
|
||||||
</parent>
|
</parent>
|
||||||
<artifactId>imageio-hdr</artifactId>
|
<artifactId>imageio-hdr</artifactId>
|
||||||
<name>TwelveMonkeys :: ImageIO :: HDR plugin</name>
|
<name>TwelveMonkeys :: ImageIO :: HDR plugin</name>
|
||||||
@@ -32,21 +32,4 @@
|
|||||||
<artifactId>imageio-metadata</artifactId>
|
<artifactId>imageio-metadata</artifactId>
|
||||||
</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
|
|
||||||
</Provide-Capability>
|
|
||||||
</instructions>
|
|
||||||
</configuration>
|
|
||||||
</plugin>
|
|
||||||
</plugins>
|
|
||||||
</build>
|
|
||||||
</project>
|
</project>
|
||||||
|
|||||||
+3
-3
@@ -59,7 +59,7 @@ public final class HDRImageReader extends ImageReaderBase {
|
|||||||
|
|
||||||
private HDRHeader header;
|
private HDRHeader header;
|
||||||
|
|
||||||
HDRImageReader(final ImageReaderSpi provider) {
|
protected HDRImageReader(final ImageReaderSpi provider) {
|
||||||
super(provider);
|
super(provider);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -196,7 +196,7 @@ public final class HDRImageReader extends ImageReaderBase {
|
|||||||
int ySub = param != null ? param.getSourceYSubsampling() : 1;
|
int ySub = param != null ? param.getSourceYSubsampling() : 1;
|
||||||
|
|
||||||
byte[] rowRGBE = new byte[width * 4];
|
byte[] rowRGBE = new byte[width * 4];
|
||||||
byte[] pixelRGBE = new byte[4];
|
byte[] pixelRGBE = new byte[width];
|
||||||
|
|
||||||
processImageStarted(imageIndex);
|
processImageStarted(imageIndex);
|
||||||
|
|
||||||
@@ -231,7 +231,7 @@ public final class HDRImageReader extends ImageReaderBase {
|
|||||||
|
|
||||||
processImageComplete();
|
processImageComplete();
|
||||||
|
|
||||||
return raster;
|
return destination.getRaster();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
+1
-1
@@ -5,7 +5,7 @@ import com.twelvemonkeys.imageio.StandardImageMetadataSupport;
|
|||||||
import javax.imageio.ImageTypeSpecifier;
|
import javax.imageio.ImageTypeSpecifier;
|
||||||
import javax.imageio.metadata.IIOMetadataNode;
|
import javax.imageio.metadata.IIOMetadataNode;
|
||||||
|
|
||||||
final class HDRMetadata extends StandardImageMetadataSupport {
|
public class HDRMetadata extends StandardImageMetadataSupport {
|
||||||
public HDRMetadata(ImageTypeSpecifier type, HDRHeader header) {
|
public HDRMetadata(ImageTypeSpecifier type, HDRHeader header) {
|
||||||
super(builder(type)
|
super(builder(type)
|
||||||
.withCompressionTypeName("RLE")
|
.withCompressionTypeName("RLE")
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>com.twelvemonkeys.imageio</groupId>
|
<groupId>com.twelvemonkeys.imageio</groupId>
|
||||||
<artifactId>imageio</artifactId>
|
<artifactId>imageio</artifactId>
|
||||||
<version>3.11.0-SNAPSHOT</version>
|
<version>3.9.4</version>
|
||||||
</parent>
|
</parent>
|
||||||
<artifactId>imageio-icns</artifactId>
|
<artifactId>imageio-icns</artifactId>
|
||||||
<name>TwelveMonkeys :: ImageIO :: ICNS plugin</name>
|
<name>TwelveMonkeys :: ImageIO :: ICNS 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>
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>com.twelvemonkeys.imageio</groupId>
|
<groupId>com.twelvemonkeys.imageio</groupId>
|
||||||
<artifactId>imageio</artifactId>
|
<artifactId>imageio</artifactId>
|
||||||
<version>3.11.0-SNAPSHOT</version>
|
<version>3.9.4</version>
|
||||||
</parent>
|
</parent>
|
||||||
<artifactId>imageio-iff</artifactId>
|
<artifactId>imageio-iff</artifactId>
|
||||||
<name>TwelveMonkeys :: ImageIO :: IFF plugin</name>
|
<name>TwelveMonkeys :: ImageIO :: IFF plugin</name>
|
||||||
@@ -29,23 +29,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>
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>com.twelvemonkeys.imageio</groupId>
|
<groupId>com.twelvemonkeys.imageio</groupId>
|
||||||
<artifactId>imageio</artifactId>
|
<artifactId>imageio</artifactId>
|
||||||
<version>3.11.0-SNAPSHOT</version>
|
<version>3.9.4</version>
|
||||||
</parent>
|
</parent>
|
||||||
<artifactId>imageio-jpeg-jai-interop</artifactId>
|
<artifactId>imageio-jpeg-jai-interop</artifactId>
|
||||||
<name>TwelveMonkeys :: ImageIO :: JPEG/JAI TIFF Interop</name>
|
<name>TwelveMonkeys :: ImageIO :: JPEG/JAI TIFF Interop</name>
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>com.twelvemonkeys.imageio</groupId>
|
<groupId>com.twelvemonkeys.imageio</groupId>
|
||||||
<artifactId>imageio</artifactId>
|
<artifactId>imageio</artifactId>
|
||||||
<version>3.11.0-SNAPSHOT</version>
|
<version>3.9.4</version>
|
||||||
</parent>
|
</parent>
|
||||||
<artifactId>imageio-jpeg-jep262-interop</artifactId>
|
<artifactId>imageio-jpeg-jep262-interop</artifactId>
|
||||||
<name>TwelveMonkeys :: ImageIO :: JPEG/JEP-262 Interop</name>
|
<name>TwelveMonkeys :: ImageIO :: JPEG/JEP-262 Interop</name>
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>com.twelvemonkeys.imageio</groupId>
|
<groupId>com.twelvemonkeys.imageio</groupId>
|
||||||
<artifactId>imageio</artifactId>
|
<artifactId>imageio</artifactId>
|
||||||
<version>3.11.0-SNAPSHOT</version>
|
<version>3.9.4</version>
|
||||||
</parent>
|
</parent>
|
||||||
<artifactId>imageio-jpeg</artifactId>
|
<artifactId>imageio-jpeg</artifactId>
|
||||||
<name>TwelveMonkeys :: ImageIO :: JPEG plugin</name>
|
<name>TwelveMonkeys :: ImageIO :: JPEG plugin</name>
|
||||||
@@ -32,23 +32,4 @@
|
|||||||
<artifactId>imageio-metadata</artifactId>
|
<artifactId>imageio-metadata</artifactId>
|
||||||
</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>
|
||||||
|
|||||||
+2
-2
@@ -145,8 +145,8 @@ final class HuffmanTable extends Segment {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int c = temp >> 4;
|
int c = temp >> 4;
|
||||||
if (c > 1) {
|
if (c > 2) {
|
||||||
throw new IIOException("Unexpected JPEG Huffman Table class (> 1): " + c);
|
throw new IIOException("Unexpected JPEG Huffman Table class (> 2): " + c);
|
||||||
}
|
}
|
||||||
|
|
||||||
table.tc[t][c] = true;
|
table.tc[t][c] = true;
|
||||||
|
|||||||
+7
-8
@@ -888,21 +888,20 @@ public final class JPEGImageReader extends ImageReaderBase {
|
|||||||
throw new IIOException("No SOF segment in stream");
|
throw new IIOException("No SOF segment in stream");
|
||||||
}
|
}
|
||||||
|
|
||||||
private Application lastAppSegment(int marker, String identifier) throws IOException {
|
|
||||||
List<Application> appSegments = getAppSegments(marker, identifier);
|
|
||||||
return appSegments.isEmpty() ? null : appSegments.get(appSegments.size() - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
AdobeDCT getAdobeDCT() throws IOException {
|
AdobeDCT getAdobeDCT() throws IOException {
|
||||||
return (AdobeDCT) lastAppSegment(JPEG.APP14, "Adobe");
|
List<Application> adobe = getAppSegments(JPEG.APP14, "Adobe");
|
||||||
|
return adobe.isEmpty() ? null : (AdobeDCT) adobe.get(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
JFIF getJFIF() throws IOException{
|
JFIF getJFIF() throws IOException{
|
||||||
return (JFIF) lastAppSegment(JPEG.APP0, "JFIF");
|
List<Application> jfif = getAppSegments(JPEG.APP0, "JFIF");
|
||||||
|
return jfif.isEmpty() ? null : (JFIF) jfif.get(0);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
JFXX getJFXX() throws IOException {
|
JFXX getJFXX() throws IOException {
|
||||||
return (JFXX) lastAppSegment(JPEG.APP0, "JFXX");
|
List<Application> jfxx = getAppSegments(JPEG.APP0, "JFXX");
|
||||||
|
return jfxx.isEmpty() ? null : (JFXX) jfxx.get(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
private EXIF getExif() throws IOException {
|
private EXIF getExif() throws IOException {
|
||||||
|
|||||||
+1
-1
@@ -52,7 +52,7 @@ import static com.twelvemonkeys.imageio.util.IIOUtil.lookupProviderByName;
|
|||||||
* @version $Id: JPEGImageReaderSpi.java,v 1.0 24.01.11 22.12 haraldk Exp$
|
* @version $Id: JPEGImageReaderSpi.java,v 1.0 24.01.11 22.12 haraldk Exp$
|
||||||
*/
|
*/
|
||||||
public final class JPEGImageReaderSpi extends ImageReaderSpiBase {
|
public final class JPEGImageReaderSpi extends ImageReaderSpiBase {
|
||||||
ImageReaderSpi delegateProvider;
|
protected ImageReaderSpi delegateProvider;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor for use by {@link javax.imageio.spi.IIORegistry} only.
|
* Constructor for use by {@link javax.imageio.spi.IIORegistry} only.
|
||||||
|
|||||||
+29
-63
@@ -32,21 +32,19 @@ package com.twelvemonkeys.imageio.plugins.jpeg;
|
|||||||
|
|
||||||
import com.twelvemonkeys.imageio.ImageWriterBase;
|
import com.twelvemonkeys.imageio.ImageWriterBase;
|
||||||
import com.twelvemonkeys.imageio.metadata.jpeg.JPEG;
|
import com.twelvemonkeys.imageio.metadata.jpeg.JPEG;
|
||||||
import com.twelvemonkeys.imageio.util.ImageTypeSpecifiers;
|
|
||||||
import com.twelvemonkeys.imageio.util.ProgressListenerBase;
|
import com.twelvemonkeys.imageio.util.ProgressListenerBase;
|
||||||
|
|
||||||
import org.w3c.dom.NodeList;
|
|
||||||
|
|
||||||
import javax.imageio.IIOImage;
|
import javax.imageio.IIOImage;
|
||||||
import javax.imageio.ImageTypeSpecifier;
|
import javax.imageio.ImageTypeSpecifier;
|
||||||
import javax.imageio.ImageWriteParam;
|
import javax.imageio.ImageWriteParam;
|
||||||
import javax.imageio.ImageWriter;
|
import javax.imageio.ImageWriter;
|
||||||
import javax.imageio.event.IIOWriteWarningListener;
|
import javax.imageio.event.IIOWriteWarningListener;
|
||||||
import javax.imageio.metadata.IIOInvalidTreeException;
|
|
||||||
import javax.imageio.metadata.IIOMetadata;
|
import javax.imageio.metadata.IIOMetadata;
|
||||||
import javax.imageio.metadata.IIOMetadataNode;
|
import javax.imageio.metadata.IIOMetadataNode;
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.awt.color.*;
|
import java.awt.color.ColorSpace;
|
||||||
|
import java.awt.color.ICC_ColorSpace;
|
||||||
|
import java.awt.color.ICC_Profile;
|
||||||
import java.awt.image.*;
|
import java.awt.image.*;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
@@ -163,7 +161,7 @@ public final class JPEGImageWriter extends ImageWriterBase {
|
|||||||
else {
|
else {
|
||||||
// If the image metadata is our substitute, convert it back to native com.sun format
|
// If the image metadata is our substitute, convert it back to native com.sun format
|
||||||
if (image.getMetadata() instanceof JPEGImage10Metadata) {
|
if (image.getMetadata() instanceof JPEGImage10Metadata) {
|
||||||
ImageTypeSpecifier type = image.hasRaster() ? null : ImageTypeSpecifiers.createFromRenderedImage(image.getRenderedImage());
|
ImageTypeSpecifier type = image.hasRaster() ? null : ImageTypeSpecifier.createFromRenderedImage(image.getRenderedImage());
|
||||||
IIOMetadata nativeMetadata = delegate.getDefaultImageMetadata(type, param);
|
IIOMetadata nativeMetadata = delegate.getDefaultImageMetadata(type, param);
|
||||||
|
|
||||||
JPEGImage10Metadata metadata = (JPEGImage10Metadata) image.getMetadata();
|
JPEGImage10Metadata metadata = (JPEGImage10Metadata) image.getMetadata();
|
||||||
@@ -186,67 +184,23 @@ public final class JPEGImageWriter extends ImageWriterBase {
|
|||||||
RenderedImage renderedImage = image.getRenderedImage();
|
RenderedImage renderedImage = image.getRenderedImage();
|
||||||
boolean overrideDestination = param != null && param.getDestinationType() != null;
|
boolean overrideDestination = param != null && param.getDestinationType() != null;
|
||||||
ImageTypeSpecifier destinationType = overrideDestination
|
ImageTypeSpecifier destinationType = overrideDestination
|
||||||
? param.getDestinationType()
|
? param.getDestinationType()
|
||||||
: ImageTypeSpecifiers.createFromRenderedImage(renderedImage);
|
: ImageTypeSpecifier.createFromRenderedImage(renderedImage);
|
||||||
|
|
||||||
IIOMetadata metadata = convertCMYKMetadata(image.getMetadata(), destinationType, param);
|
ColorSpace cmykCS = destinationType.getColorModel().getColorSpace();
|
||||||
|
|
||||||
Raster raster = new InvertedRaster(getRaster(renderedImage));
|
IIOMetadata metadata = delegate.getDefaultImageMetadata(destinationType, param);
|
||||||
|
|
||||||
// TODO: For YCCK we need oposite conversion
|
|
||||||
// for (int i = 0; i < data.length; i += 4) {
|
|
||||||
// YCbCrConverter.convertYCbCr2RGB(data, data, i);
|
|
||||||
// }
|
|
||||||
|
|
||||||
if (overrideDestination) {
|
|
||||||
// Avoid javax.imageio.IIOException: Invalid argument to native writeImage
|
|
||||||
param.setDestinationType(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
delegate.write(streamMetadata, new IIOImage(raster, null, metadata), param);
|
|
||||||
}
|
|
||||||
finally {
|
|
||||||
if (overrideDestination) {
|
|
||||||
param.setDestinationType(destinationType);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private IIOMetadata convertCMYKMetadata(IIOMetadata original, ImageTypeSpecifier destinationType, ImageWriteParam param) throws IIOInvalidTreeException {
|
|
||||||
IIOMetadataNode jpegMeta = new IIOMetadataNode(JAVAX_IMAGEIO_JPEG_IMAGE_1_0);
|
IIOMetadataNode jpegMeta = new IIOMetadataNode(JAVAX_IMAGEIO_JPEG_IMAGE_1_0);
|
||||||
jpegMeta.appendChild(new IIOMetadataNode("JPEGVariety")); // Just leave as default, we can't write JFIF
|
jpegMeta.appendChild(new IIOMetadataNode("JPEGVariety")); // Just leave as default
|
||||||
|
|
||||||
IIOMetadataNode markerSequence = new IIOMetadataNode("markerSequence");
|
IIOMetadataNode markerSequence = new IIOMetadataNode("markerSequence");
|
||||||
jpegMeta.appendChild(markerSequence);
|
jpegMeta.appendChild(markerSequence);
|
||||||
|
|
||||||
IIOMetadataNode originalTree = original != null
|
|
||||||
? (IIOMetadataNode) original.getAsTree(JAVAX_IMAGEIO_JPEG_IMAGE_1_0)
|
|
||||||
: new IIOMetadataNode("emptyNode");
|
|
||||||
|
|
||||||
// Append original unknown nodes, if present, but filter out any ICC Profiles
|
|
||||||
NodeList unknowns = originalTree.getElementsByTagName("unknown");
|
|
||||||
for (int i = 0; i < unknowns.getLength(); i++) {
|
|
||||||
IIOMetadataNode unknown = (IIOMetadataNode) unknowns.item(i);
|
|
||||||
|
|
||||||
// TODO: If the cmykCS is not an ICC profile, maybe it makes sense to NOT filter here? that's a corner case...
|
|
||||||
if ("226".equals(unknown.getAttribute("MarkerTag"))) {
|
|
||||||
Object userObject = unknown.getUserObject();
|
|
||||||
|
|
||||||
if (userObject instanceof byte[] && ((byte[]) userObject).length >= "ICC_PROFILE".length()
|
|
||||||
&& "ICC_PROFILE".equals(new String((byte[]) userObject, 0, "ICC_PROFILE".length()))) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
markerSequence.appendChild(unknown);
|
|
||||||
}
|
|
||||||
|
|
||||||
IIOMetadataNode app14Adobe = new IIOMetadataNode("app14Adobe");
|
IIOMetadataNode app14Adobe = new IIOMetadataNode("app14Adobe");
|
||||||
app14Adobe.setAttribute("transform", "0"); // 0 for CMYK, 2 for YCCK
|
app14Adobe.setAttribute("transform", "0"); // 0 for CMYK, 2 for YCCK
|
||||||
markerSequence.appendChild(app14Adobe);
|
markerSequence.appendChild(app14Adobe);
|
||||||
|
|
||||||
ColorSpace cmykCS = destinationType.getColorModel().getColorSpace();
|
|
||||||
if (cmykCS instanceof ICC_ColorSpace) {
|
if (cmykCS instanceof ICC_ColorSpace) {
|
||||||
ICC_Profile profile = ((ICC_ColorSpace) cmykCS).getProfile();
|
ICC_Profile profile = ((ICC_ColorSpace) cmykCS).getProfile();
|
||||||
byte[] profileData = profile.getData();
|
byte[] profileData = profile.getData();
|
||||||
@@ -279,16 +233,28 @@ public final class JPEGImageWriter extends ImageWriterBase {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Append original comment nodes, if present
|
|
||||||
NodeList comments = originalTree.getElementsByTagName("COM");
|
|
||||||
for (int i = 0; i < comments.getLength(); i++) {
|
|
||||||
markerSequence.appendChild(comments.item(i));
|
|
||||||
}
|
|
||||||
|
|
||||||
IIOMetadata metadata = delegate.getDefaultImageMetadata(destinationType, param);
|
|
||||||
metadata.mergeTree(JAVAX_IMAGEIO_JPEG_IMAGE_1_0, jpegMeta);
|
metadata.mergeTree(JAVAX_IMAGEIO_JPEG_IMAGE_1_0, jpegMeta);
|
||||||
|
|
||||||
return metadata;
|
Raster raster = new InvertedRaster(getRaster(renderedImage));
|
||||||
|
|
||||||
|
// TODO: For YCCK we need oposite conversion
|
||||||
|
// for (int i = 0; i < data.length; i += 4) {
|
||||||
|
// YCbCrConverter.convertYCbCr2RGB(data, data, i);
|
||||||
|
// }
|
||||||
|
|
||||||
|
if (overrideDestination) {
|
||||||
|
// Avoid javax.imageio.IIOException: Invalid argument to native writeImage
|
||||||
|
param.setDestinationType(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
delegate.write(streamMetadata, new IIOImage(raster, null, metadata), param);
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
if (overrideDestination) {
|
||||||
|
param.setDestinationType(destinationType);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Candidate util method
|
// TODO: Candidate util method
|
||||||
|
|||||||
+6
-10
@@ -38,13 +38,7 @@ import com.twelvemonkeys.imageio.util.ImageWriterAbstractTest;
|
|||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.w3c.dom.NodeList;
|
import org.w3c.dom.NodeList;
|
||||||
|
|
||||||
import javax.imageio.IIOImage;
|
import javax.imageio.*;
|
||||||
import javax.imageio.ImageIO;
|
|
||||||
import javax.imageio.ImageReadParam;
|
|
||||||
import javax.imageio.ImageReader;
|
|
||||||
import javax.imageio.ImageTypeSpecifier;
|
|
||||||
import javax.imageio.ImageWriteParam;
|
|
||||||
import javax.imageio.ImageWriter;
|
|
||||||
import javax.imageio.metadata.IIOMetadata;
|
import javax.imageio.metadata.IIOMetadata;
|
||||||
import javax.imageio.metadata.IIOMetadataFormatImpl;
|
import javax.imageio.metadata.IIOMetadataFormatImpl;
|
||||||
import javax.imageio.metadata.IIOMetadataNode;
|
import javax.imageio.metadata.IIOMetadataNode;
|
||||||
@@ -54,7 +48,8 @@ import javax.imageio.stream.ImageInputStream;
|
|||||||
import javax.imageio.stream.ImageOutputStream;
|
import javax.imageio.stream.ImageOutputStream;
|
||||||
import javax.imageio.stream.MemoryCacheImageOutputStream;
|
import javax.imageio.stream.MemoryCacheImageOutputStream;
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.awt.color.*;
|
import java.awt.color.ColorSpace;
|
||||||
|
import java.awt.color.ICC_Profile;
|
||||||
import java.awt.image.*;
|
import java.awt.image.*;
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@@ -216,7 +211,7 @@ public class JPEGImageWriterTest extends ImageWriterAbstractTest<JPEGImageWriter
|
|||||||
// Test APP2/ICC_PROFILE segments form native metadata
|
// Test APP2/ICC_PROFILE segments form native metadata
|
||||||
IIOMetadataNode nativeMeta = (IIOMetadataNode) metadata.getAsTree(JPEGImage10Metadata.JAVAX_IMAGEIO_JPEG_IMAGE_1_0);
|
IIOMetadataNode nativeMeta = (IIOMetadataNode) metadata.getAsTree(JPEGImage10Metadata.JAVAX_IMAGEIO_JPEG_IMAGE_1_0);
|
||||||
NodeList unknown = nativeMeta.getElementsByTagName("unknown");
|
NodeList unknown = nativeMeta.getElementsByTagName("unknown");
|
||||||
assertEquals(14, unknown.getLength()); // We write longer segments than the original, so we get less segments
|
assertEquals(11, unknown.getLength()); // We write longer segments than the original, so we get less segments
|
||||||
|
|
||||||
ByteArrayOutputStream iccSegments = new ByteArrayOutputStream(1024 * 1024);
|
ByteArrayOutputStream iccSegments = new ByteArrayOutputStream(1024 * 1024);
|
||||||
|
|
||||||
@@ -243,6 +238,7 @@ public class JPEGImageWriterTest extends ImageWriterAbstractTest<JPEGImageWriter
|
|||||||
ImageWriter writer = createWriter();
|
ImageWriter writer = createWriter();
|
||||||
ImageReader reader = ImageIO.getImageReader(writer);
|
ImageReader reader = ImageIO.getImageReader(writer);
|
||||||
|
|
||||||
|
// TODO: Add flag to allow removing the ICC profile from image
|
||||||
ByteArrayOutputStream stream = transcode(reader, getClassLoaderResource("/jpeg/cmyk-sample-multiple-chunk-icc.jpg"), writer, ColorSpace.TYPE_CMYK, false);
|
ByteArrayOutputStream stream = transcode(reader, getClassLoaderResource("/jpeg/cmyk-sample-multiple-chunk-icc.jpg"), writer, ColorSpace.TYPE_CMYK, false);
|
||||||
|
|
||||||
reader.reset();
|
reader.reset();
|
||||||
@@ -263,7 +259,7 @@ public class JPEGImageWriterTest extends ImageWriterAbstractTest<JPEGImageWriter
|
|||||||
// Test APP2/ICC_PROFILE segments form native metadata
|
// Test APP2/ICC_PROFILE segments form native metadata
|
||||||
IIOMetadataNode nativeMeta = (IIOMetadataNode) metadata.getAsTree(JPEGImage10Metadata.JAVAX_IMAGEIO_JPEG_IMAGE_1_0);
|
IIOMetadataNode nativeMeta = (IIOMetadataNode) metadata.getAsTree(JPEGImage10Metadata.JAVAX_IMAGEIO_JPEG_IMAGE_1_0);
|
||||||
NodeList unknown = nativeMeta.getElementsByTagName("unknown");
|
NodeList unknown = nativeMeta.getElementsByTagName("unknown");
|
||||||
assertEquals(3, unknown.getLength());
|
assertEquals(0, unknown.getLength());
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: YCCK
|
// TODO: YCCK
|
||||||
|
|||||||
@@ -3,13 +3,13 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>com.twelvemonkeys.imageio</groupId>
|
<groupId>com.twelvemonkeys.imageio</groupId>
|
||||||
<artifactId>imageio</artifactId>
|
<artifactId>imageio</artifactId>
|
||||||
<version>3.11.0-SNAPSHOT</version>
|
<version>3.9.4</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<artifactId>imageio-metadata</artifactId>
|
<artifactId>imageio-metadata</artifactId>
|
||||||
<name>TwelveMonkeys :: ImageIO :: Metadata</name>
|
<name>TwelveMonkeys :: ImageIO :: Metadata</name>
|
||||||
<description>
|
<description>
|
||||||
TwelveMonkeys ImageIO metadata support classes.
|
ImageIO metadata module.
|
||||||
</description>
|
</description>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
@@ -28,13 +28,4 @@
|
|||||||
<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>
|
||||||
|
|||||||
+1
-1
@@ -88,7 +88,7 @@ public interface JPEG {
|
|||||||
// Start of Frame segment markers (SOFn).
|
// Start of Frame segment markers (SOFn).
|
||||||
/** SOF0: Baseline DCT, Huffman coding. */
|
/** SOF0: Baseline DCT, Huffman coding. */
|
||||||
int SOF0 = 0xFFC0;
|
int SOF0 = 0xFFC0;
|
||||||
/** SOF1: Extended DCT, Huffman coding. */
|
/** SOF0: Extended DCT, Huffman coding. */
|
||||||
int SOF1 = 0xFFC1;
|
int SOF1 = 0xFFC1;
|
||||||
/** SOF2: Progressive DCT, Huffman coding. */
|
/** SOF2: Progressive DCT, Huffman coding. */
|
||||||
int SOF2 = 0xFFC2;
|
int SOF2 = 0xFFC2;
|
||||||
|
|||||||
+7
-32
@@ -35,11 +35,8 @@ import static org.hamcrest.MatcherAssert.assertThat;
|
|||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
import static org.junit.Assert.assertNotNull;
|
import static org.junit.Assert.assertNotNull;
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
|
||||||
import java.io.ByteArrayInputStream;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.InputStreamReader;
|
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.net.ServerSocket;
|
import java.net.ServerSocket;
|
||||||
import java.net.Socket;
|
import java.net.Socket;
|
||||||
@@ -53,7 +50,6 @@ import java.util.Iterator;
|
|||||||
import javax.imageio.ImageIO;
|
import javax.imageio.ImageIO;
|
||||||
import javax.imageio.stream.ImageInputStream;
|
import javax.imageio.stream.ImageInputStream;
|
||||||
|
|
||||||
import com.twelvemonkeys.imageio.stream.DirectImageInputStream;
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import com.twelvemonkeys.imageio.metadata.CompoundDirectory;
|
import com.twelvemonkeys.imageio.metadata.CompoundDirectory;
|
||||||
@@ -494,15 +490,12 @@ public class XMPReaderTest extends MetadataReaderAbstractTest {
|
|||||||
assertThat(exif.getEntryById("http://ns.adobe.com/exif/1.0/NativeDigest"), hasValue("36864,40960,40961,37121,37122,40962,40963,37510,40964,36867,36868,33434,33437,34850,34852,34855,34856,37377,37378,37379,37380,37381,37382,37383,37384,37385,37386,37396,41483,41484,41486,41487,41488,41492,41493,41495,41728,41729,41730,41985,41986,41987,41988,41989,41990,41991,41992,41993,41994,41995,41996,42016,0,2,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,20,22,23,24,25,26,27,28,30;A7F21D25E2C562F152B2C4ECC9E534DA"));
|
assertThat(exif.getEntryById("http://ns.adobe.com/exif/1.0/NativeDigest"), hasValue("36864,40960,40961,37121,37122,40962,40963,37510,40964,36867,36868,33434,33437,34850,34852,34855,34856,37377,37378,37379,37380,37381,37382,37383,37384,37385,37386,37396,41483,41484,41486,41487,41488,41492,41493,41495,41728,41729,41730,41985,41986,41987,41988,41989,41990,41991,41992,41993,41994,41995,41996,42016,0,2,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,20,22,23,24,25,26,27,28,30;A7F21D25E2C562F152B2C4ECC9E534DA"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(timeout = 2500L)
|
@Test(timeout = 1500L)
|
||||||
public void testNoExternalRequest() throws Exception {
|
public void testNoExternalRequest() throws Exception {
|
||||||
String maliciousXML = resourceAsString("/xmp/xmp-jpeg-xxe.xml");
|
// TODO: Use dynamic port?
|
||||||
|
try (HTTPServer server = new HTTPServer(7777)) {
|
||||||
try (HTTPServer server = new HTTPServer()) {
|
try {
|
||||||
String dynamicXML = maliciousXML.replace("http://localhost:7777/", "http://localhost:" + server.port() + "/");
|
createReader().read(getResourceAsIIS("/xmp/xmp-jpeg-xxe.xml"));
|
||||||
|
|
||||||
try (DirectImageInputStream input = new DirectImageInputStream(new ByteArrayInputStream(dynamicXML.getBytes(StandardCharsets.UTF_8)));) {
|
|
||||||
createReader().read(input);
|
|
||||||
} catch (IOException ioe) {
|
} catch (IOException ioe) {
|
||||||
if (ioe.getMessage().contains("501")) {
|
if (ioe.getMessage().contains("501")) {
|
||||||
throw new AssertionError("Reading should not cause external requests", ioe);
|
throw new AssertionError("Reading should not cause external requests", ioe);
|
||||||
@@ -514,26 +507,12 @@ public class XMPReaderTest extends MetadataReaderAbstractTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private String resourceAsString(String name) throws IOException {
|
|
||||||
StringBuilder builder = new StringBuilder(1024);
|
|
||||||
|
|
||||||
try (BufferedReader reader = new BufferedReader(new InputStreamReader(getResource(name).openStream(), StandardCharsets.UTF_8))) {
|
|
||||||
String line;
|
|
||||||
while ((line = reader.readLine()) != null) {
|
|
||||||
builder.append(line)
|
|
||||||
.append('\n');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return builder.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class HTTPServer implements AutoCloseable {
|
private static class HTTPServer implements AutoCloseable {
|
||||||
private final ServerSocket server;
|
private final ServerSocket server;
|
||||||
private final Thread thread;
|
private final Thread thread;
|
||||||
|
|
||||||
HTTPServer() throws IOException {
|
HTTPServer(int port) throws IOException {
|
||||||
server = new ServerSocket(0, 1);
|
server = new ServerSocket(port, 1);
|
||||||
thread = new Thread(new Runnable() {
|
thread = new Thread(new Runnable() {
|
||||||
@Override public void run() {
|
@Override public void run() {
|
||||||
serve();
|
serve();
|
||||||
@@ -542,10 +521,6 @@ public class XMPReaderTest extends MetadataReaderAbstractTest {
|
|||||||
thread.start();
|
thread.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
public final int port() {
|
|
||||||
return server.getLocalPort();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void serve() {
|
private void serve() {
|
||||||
try {
|
try {
|
||||||
Socket client = server.accept();
|
Socket client = server.accept();
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>com.twelvemonkeys.imageio</groupId>
|
<groupId>com.twelvemonkeys.imageio</groupId>
|
||||||
<artifactId>imageio</artifactId>
|
<artifactId>imageio</artifactId>
|
||||||
<version>3.11.0-SNAPSHOT</version>
|
<version>3.9.4</version>
|
||||||
</parent>
|
</parent>
|
||||||
<artifactId>imageio-pcx</artifactId>
|
<artifactId>imageio-pcx</artifactId>
|
||||||
<name>TwelveMonkeys :: ImageIO :: PCX plugin</name>
|
<name>TwelveMonkeys :: ImageIO :: PCX plugin</name>
|
||||||
@@ -28,21 +28,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
|
|
||||||
</Provide-Capability>
|
|
||||||
</instructions>
|
|
||||||
</configuration>
|
|
||||||
</plugin>
|
|
||||||
</plugins>
|
|
||||||
</build>
|
|
||||||
</project>
|
</project>
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>com.twelvemonkeys.imageio</groupId>
|
<groupId>com.twelvemonkeys.imageio</groupId>
|
||||||
<artifactId>imageio</artifactId>
|
<artifactId>imageio</artifactId>
|
||||||
<version>3.11.0-SNAPSHOT</version>
|
<version>3.9.4</version>
|
||||||
</parent>
|
</parent>
|
||||||
<artifactId>imageio-pdf</artifactId>
|
<artifactId>imageio-pdf</artifactId>
|
||||||
<name>TwelveMonkeys :: ImageIO :: PDF plugin</name>
|
<name>TwelveMonkeys :: ImageIO :: PDF plugin</name>
|
||||||
@@ -28,13 +28,4 @@
|
|||||||
<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>
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>com.twelvemonkeys.imageio</groupId>
|
<groupId>com.twelvemonkeys.imageio</groupId>
|
||||||
<artifactId>imageio</artifactId>
|
<artifactId>imageio</artifactId>
|
||||||
<version>3.11.0-SNAPSHOT</version>
|
<version>3.9.4</version>
|
||||||
</parent>
|
</parent>
|
||||||
<artifactId>imageio-pict</artifactId>
|
<artifactId>imageio-pict</artifactId>
|
||||||
<name>TwelveMonkeys :: ImageIO :: PICT plugin</name>
|
<name>TwelveMonkeys :: ImageIO :: PICT plugin</name>
|
||||||
@@ -27,22 +27,4 @@
|
|||||||
</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>
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>com.twelvemonkeys.imageio</groupId>
|
<groupId>com.twelvemonkeys.imageio</groupId>
|
||||||
<artifactId>imageio</artifactId>
|
<artifactId>imageio</artifactId>
|
||||||
<version>3.11.0-SNAPSHOT</version>
|
<version>3.9.4</version>
|
||||||
</parent>
|
</parent>
|
||||||
<artifactId>imageio-pnm</artifactId>
|
<artifactId>imageio-pnm</artifactId>
|
||||||
<name>TwelveMonkeys :: ImageIO :: PNM plugin</name>
|
<name>TwelveMonkeys :: ImageIO :: PNM plugin</name>
|
||||||
@@ -28,23 +28,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>
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>com.twelvemonkeys.imageio</groupId>
|
<groupId>com.twelvemonkeys.imageio</groupId>
|
||||||
<artifactId>imageio</artifactId>
|
<artifactId>imageio</artifactId>
|
||||||
<version>3.11.0-SNAPSHOT</version>
|
<version>3.9.4</version>
|
||||||
</parent>
|
</parent>
|
||||||
<artifactId>imageio-psd</artifactId>
|
<artifactId>imageio-psd</artifactId>
|
||||||
<name>TwelveMonkeys :: ImageIO :: PSD plugin</name>
|
<name>TwelveMonkeys :: ImageIO :: PSD plugin</name>
|
||||||
@@ -31,23 +31,4 @@
|
|||||||
<artifactId>imageio-metadata</artifactId>
|
<artifactId>imageio-metadata</artifactId>
|
||||||
</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>
|
||||||
|
|||||||
@@ -709,6 +709,4 @@ interface PSD extends com.twelvemonkeys.imageio.metadata.psd.PSD {
|
|||||||
int luni = 'l' << 24 | 'u' << 16 | 'n' << 8 | 'i';
|
int luni = 'l' << 24 | 'u' << 16 | 'n' << 8 | 'i';
|
||||||
int lyid = 'l' << 24 | 'y' << 16 | 'i' << 8 | 'd';
|
int lyid = 'l' << 24 | 'y' << 16 | 'i' << 8 | 'd';
|
||||||
int lsct = 'l' << 24 | 's' << 16 | 'c' << 8 | 't';
|
int lsct = 'l' << 24 | 's' << 16 | 'c' << 8 | 't';
|
||||||
// Undocumented: Nested section divider setting
|
|
||||||
int lsdk = 'l' << 24 | 's' << 16 | 'd' << 8 | 'k';
|
|
||||||
}
|
}
|
||||||
|
|||||||
+13
-19
@@ -864,27 +864,21 @@ public final class PSDImageReader extends ImageReaderBase {
|
|||||||
|
|
||||||
long imageResourcesLength = imageInput.readUnsignedInt();
|
long imageResourcesLength = imageInput.readUnsignedInt();
|
||||||
|
|
||||||
if (pParseData && metadata.imageResources == null) {
|
if (pParseData && metadata.imageResources == null && imageResourcesLength > 0) {
|
||||||
if (imageResourcesLength == 0) {
|
long expectedEnd = imageInput.getStreamPosition() + imageResourcesLength;
|
||||||
metadata.imageResources = Collections.emptyList();
|
metadata.imageResources = new ArrayList<>();
|
||||||
|
|
||||||
|
while (imageInput.getStreamPosition() < expectedEnd) {
|
||||||
|
PSDImageResource resource = PSDImageResource.read(imageInput);
|
||||||
|
metadata.imageResources.add(resource);
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
metadata.imageResources = new ArrayList<>();
|
|
||||||
|
|
||||||
long expectedEnd = imageInput.getStreamPosition() + imageResourcesLength;
|
if (DEBUG) {
|
||||||
|
System.out.println("imageResources: " + metadata.imageResources);
|
||||||
|
}
|
||||||
|
|
||||||
while (imageInput.getStreamPosition() < expectedEnd) {
|
if (imageInput.getStreamPosition() != expectedEnd) {
|
||||||
PSDImageResource resource = PSDImageResource.read(imageInput);
|
throw new IIOException("Corrupt PSD document"); // ..or maybe just a bug in the reader.. ;-)
|
||||||
metadata.imageResources.add(resource);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (DEBUG) {
|
|
||||||
System.out.println("imageResources: " + metadata.imageResources);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (imageInput.getStreamPosition() != expectedEnd) {
|
|
||||||
throw new IIOException("Corrupt PSD document"); // ..or maybe just a bug in the reader.. ;-)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1070,7 +1064,7 @@ public final class PSDImageReader extends ImageReaderBase {
|
|||||||
final int height = getLayerHeight(layerIndex);
|
final int height = getLayerHeight(layerIndex);
|
||||||
|
|
||||||
// TODO: This behaviour must be documented!
|
// TODO: This behaviour must be documented!
|
||||||
// If layer has no pixel data, return null, as we can't create a 0 x 0 sample model/raster
|
// If layer has no pixel data, return null
|
||||||
if (width <= 0 || height <= 0) {
|
if (width <= 0 || height <= 0) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|||||||
-1
@@ -155,7 +155,6 @@ final class PSDLayerInfo {
|
|||||||
layerId = pInput.readInt();
|
layerId = pInput.readInt();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PSD.lsdk:
|
|
||||||
case PSD.lsct:
|
case PSD.lsct:
|
||||||
if (resourceLength < 4) {
|
if (resourceLength < 4) {
|
||||||
throw new IIOException(String.format("Expected sectionDividerSetting length >= 4: %d", resourceLength));
|
throw new IIOException(String.format("Expected sectionDividerSetting length >= 4: %d", resourceLength));
|
||||||
|
|||||||
-1
@@ -203,7 +203,6 @@ public final class PSDMetadata extends AbstractMetadata {
|
|||||||
IIOMetadataNode guideNode = new IIOMetadataNode("Guide");
|
IIOMetadataNode guideNode = new IIOMetadataNode("Guide");
|
||||||
guideNode.setAttribute("location", Integer.toString(guide.location));
|
guideNode.setAttribute("location", Integer.toString(guide.location));
|
||||||
guideNode.setAttribute("orientation", GUIDE_ORIENTATIONS[guide.direction]);
|
guideNode.setAttribute("orientation", GUIDE_ORIENTATIONS[guide.direction]);
|
||||||
node.appendChild(guideNode);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (imageResource instanceof PSDPixelAspectRatio) {
|
else if (imageResource instanceof PSDPixelAspectRatio) {
|
||||||
|
|||||||
+4
-8
@@ -32,7 +32,6 @@ package com.twelvemonkeys.imageio.plugins.psd;
|
|||||||
|
|
||||||
import com.twelvemonkeys.imageio.stream.DirectImageInputStream;
|
import com.twelvemonkeys.imageio.stream.DirectImageInputStream;
|
||||||
import com.twelvemonkeys.imageio.stream.SubImageInputStream;
|
import com.twelvemonkeys.imageio.stream.SubImageInputStream;
|
||||||
import com.twelvemonkeys.io.SubStream;
|
|
||||||
import com.twelvemonkeys.io.enc.DecoderStream;
|
import com.twelvemonkeys.io.enc.DecoderStream;
|
||||||
import com.twelvemonkeys.io.enc.PackBitsDecoder;
|
import com.twelvemonkeys.io.enc.PackBitsDecoder;
|
||||||
import com.twelvemonkeys.lang.StringUtil;
|
import com.twelvemonkeys.lang.StringUtil;
|
||||||
@@ -108,8 +107,7 @@ final class PSDUtil {
|
|||||||
return new SubImageInputStream(stream, streamLength < 0 ? Long.MAX_VALUE : streamLength);
|
return new SubImageInputStream(stream, streamLength < 0 ? Long.MAX_VALUE : streamLength);
|
||||||
|
|
||||||
case PSD.COMPRESSION_RLE:
|
case PSD.COMPRESSION_RLE:
|
||||||
int rowLength = (columns * bitsPerSample + 7) / 8;
|
return new DirectImageInputStream(new SequenceInputStream(new LazyPackBitsStreamEnumeration(byteCounts, stream)));
|
||||||
return new DirectImageInputStream(new SequenceInputStream(new LazyPackBitsStreamEnumeration(stream, byteCounts, rowLength)));
|
|
||||||
|
|
||||||
case PSD.COMPRESSION_ZIP:
|
case PSD.COMPRESSION_ZIP:
|
||||||
return new DirectImageInputStream(new InflaterInputStream(createStreamAdapter(stream, compressedLength)));
|
return new DirectImageInputStream(new InflaterInputStream(createStreamAdapter(stream, compressedLength)));
|
||||||
@@ -126,13 +124,11 @@ final class PSDUtil {
|
|||||||
private static class LazyPackBitsStreamEnumeration implements Enumeration<InputStream> {
|
private static class LazyPackBitsStreamEnumeration implements Enumeration<InputStream> {
|
||||||
private final ImageInputStream stream;
|
private final ImageInputStream stream;
|
||||||
private final int[] byteCounts;
|
private final int[] byteCounts;
|
||||||
private final int rowLength;
|
|
||||||
private int index;
|
private int index;
|
||||||
|
|
||||||
public LazyPackBitsStreamEnumeration(ImageInputStream stream, int[] byteCounts, int rowLength) {
|
public LazyPackBitsStreamEnumeration(int[] byteCounts, ImageInputStream stream) {
|
||||||
this.stream = stream;
|
|
||||||
this.byteCounts = byteCounts;
|
this.byteCounts = byteCounts;
|
||||||
this.rowLength = rowLength;
|
this.stream = stream;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -142,7 +138,7 @@ final class PSDUtil {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public InputStream nextElement() {
|
public InputStream nextElement() {
|
||||||
return new SubStream(new DecoderStream(createStreamAdapter(stream, byteCounts[index++]), new PackBitsDecoder(), rowLength), rowLength);
|
return new DecoderStream(createStreamAdapter(stream, byteCounts[index++]), new PackBitsDecoder());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
-25
@@ -47,7 +47,6 @@ import javax.imageio.stream.ImageInputStream;
|
|||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.awt.color.*;
|
import java.awt.color.*;
|
||||||
import java.awt.image.*;
|
import java.awt.image.*;
|
||||||
import java.io.EOFException;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
@@ -696,30 +695,6 @@ public class PSDImageReaderTest extends ImageReaderAbstractTest<PSDImageReader>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(timeout = 1000)
|
|
||||||
public void testBrokenPackBitsThrowsEOFException() throws IOException {
|
|
||||||
PSDImageReader imageReader = createReader();
|
|
||||||
|
|
||||||
try (ImageInputStream stream = ImageIO.createImageInputStream(getClassLoaderResource("/broken-psd/short-packbits.psd"))) {
|
|
||||||
imageReader.setInput(stream);
|
|
||||||
|
|
||||||
assertEquals(1, imageReader.getNumImages(true));
|
|
||||||
|
|
||||||
assertEquals(427, imageReader.getWidth(0));
|
|
||||||
assertEquals(107, imageReader.getHeight(0));
|
|
||||||
|
|
||||||
try {
|
|
||||||
imageReader.read(0);
|
|
||||||
|
|
||||||
fail("Expected EOFException, is the test broken?");
|
|
||||||
}
|
|
||||||
catch (EOFException expected) {
|
|
||||||
assertTrue(expected.getMessage().contains("PackBits"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
final static class FakeCMYKColorSpace extends ColorSpace {
|
final static class FakeCMYKColorSpace extends ColorSpace {
|
||||||
FakeCMYKColorSpace() {
|
FakeCMYKColorSpace() {
|
||||||
super(ColorSpace.TYPE_CMYK, 4);
|
super(ColorSpace.TYPE_CMYK, 4);
|
||||||
|
|||||||
Binary file not shown.
@@ -4,7 +4,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>com.twelvemonkeys.imageio</groupId>
|
<groupId>com.twelvemonkeys.imageio</groupId>
|
||||||
<artifactId>imageio</artifactId>
|
<artifactId>imageio</artifactId>
|
||||||
<version>3.11.0-SNAPSHOT</version>
|
<version>3.9.4</version>
|
||||||
</parent>
|
</parent>
|
||||||
<artifactId>imageio-reference</artifactId>
|
<artifactId>imageio-reference</artifactId>
|
||||||
<name>TwelveMonkeys :: ImageIO :: JDK Reference Tests</name>
|
<name>TwelveMonkeys :: ImageIO :: JDK Reference Tests</name>
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>com.twelvemonkeys.imageio</groupId>
|
<groupId>com.twelvemonkeys.imageio</groupId>
|
||||||
<artifactId>imageio</artifactId>
|
<artifactId>imageio</artifactId>
|
||||||
<version>3.11.0-SNAPSHOT</version>
|
<version>3.9.4</version>
|
||||||
</parent>
|
</parent>
|
||||||
<artifactId>imageio-sgi</artifactId>
|
<artifactId>imageio-sgi</artifactId>
|
||||||
<name>TwelveMonkeys :: ImageIO :: SGI plugin</name>
|
<name>TwelveMonkeys :: ImageIO :: SGI plugin</name>
|
||||||
@@ -28,21 +28,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
|
|
||||||
</Provide-Capability>
|
|
||||||
</instructions>
|
|
||||||
</configuration>
|
|
||||||
</plugin>
|
|
||||||
</plugins>
|
|
||||||
</build>
|
|
||||||
</project>
|
</project>
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>com.twelvemonkeys.imageio</groupId>
|
<groupId>com.twelvemonkeys.imageio</groupId>
|
||||||
<artifactId>imageio</artifactId>
|
<artifactId>imageio</artifactId>
|
||||||
<version>3.11.0-SNAPSHOT</version>
|
<version>3.9.4</version>
|
||||||
</parent>
|
</parent>
|
||||||
<artifactId>imageio-tga</artifactId>
|
<artifactId>imageio-tga</artifactId>
|
||||||
<name>TwelveMonkeys :: ImageIO :: TGA plugin</name>
|
<name>TwelveMonkeys :: ImageIO :: TGA plugin</name>
|
||||||
@@ -28,23 +28,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>
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>com.twelvemonkeys.imageio</groupId>
|
<groupId>com.twelvemonkeys.imageio</groupId>
|
||||||
<artifactId>imageio</artifactId>
|
<artifactId>imageio</artifactId>
|
||||||
<version>3.11.0-SNAPSHOT</version>
|
<version>3.9.4</version>
|
||||||
</parent>
|
</parent>
|
||||||
<artifactId>imageio-thumbsdb</artifactId>
|
<artifactId>imageio-thumbsdb</artifactId>
|
||||||
<name>TwelveMonkeys :: ImageIO :: Thumbs.db plugin</name>
|
<name>TwelveMonkeys :: ImageIO :: Thumbs.db plugin</name>
|
||||||
@@ -28,21 +28,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
|
|
||||||
</Provide-Capability>
|
|
||||||
</instructions>
|
|
||||||
</configuration>
|
|
||||||
</plugin>
|
|
||||||
</plugins>
|
|
||||||
</build>
|
|
||||||
</project>
|
</project>
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>com.twelvemonkeys.imageio</groupId>
|
<groupId>com.twelvemonkeys.imageio</groupId>
|
||||||
<artifactId>imageio</artifactId>
|
<artifactId>imageio</artifactId>
|
||||||
<version>3.11.0-SNAPSHOT</version>
|
<version>3.9.4</version>
|
||||||
</parent>
|
</parent>
|
||||||
<artifactId>imageio-tiff-jai-interop</artifactId>
|
<artifactId>imageio-tiff-jai-interop</artifactId>
|
||||||
<name>TwelveMonkeys :: ImageIO :: TIFF/JAI Metadata Interop</name>
|
<name>TwelveMonkeys :: ImageIO :: TIFF/JAI Metadata Interop</name>
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>com.twelvemonkeys.imageio</groupId>
|
<groupId>com.twelvemonkeys.imageio</groupId>
|
||||||
<artifactId>imageio</artifactId>
|
<artifactId>imageio</artifactId>
|
||||||
<version>3.11.0-SNAPSHOT</version>
|
<version>3.9.4</version>
|
||||||
</parent>
|
</parent>
|
||||||
<artifactId>imageio-tiff-jdk-interop</artifactId>
|
<artifactId>imageio-tiff-jdk-interop</artifactId>
|
||||||
<name>TwelveMonkeys :: ImageIO :: TIFF/JDK JPEG Interop</name>
|
<name>TwelveMonkeys :: ImageIO :: TIFF/JDK JPEG Interop</name>
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>com.twelvemonkeys.imageio</groupId>
|
<groupId>com.twelvemonkeys.imageio</groupId>
|
||||||
<artifactId>imageio</artifactId>
|
<artifactId>imageio</artifactId>
|
||||||
<version>3.11.0-SNAPSHOT</version>
|
<version>3.9.4</version>
|
||||||
</parent>
|
</parent>
|
||||||
<artifactId>imageio-tiff</artifactId>
|
<artifactId>imageio-tiff</artifactId>
|
||||||
<name>TwelveMonkeys :: ImageIO :: TIFF plugin</name>
|
<name>TwelveMonkeys :: ImageIO :: TIFF plugin</name>
|
||||||
@@ -30,11 +30,6 @@
|
|||||||
<artifactId>imageio-jpeg</artifactId>
|
<artifactId>imageio-jpeg</artifactId>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>com.twelvemonkeys.imageio</groupId>
|
|
||||||
<artifactId>imageio-webp</artifactId>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.twelvemonkeys.imageio</groupId>
|
<groupId>com.twelvemonkeys.imageio</groupId>
|
||||||
<artifactId>imageio-core</artifactId>
|
<artifactId>imageio-core</artifactId>
|
||||||
@@ -42,23 +37,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>
|
||||||
|
|||||||
-99
@@ -1,99 +0,0 @@
|
|||||||
package com.twelvemonkeys.imageio.plugins.tiff;
|
|
||||||
|
|
||||||
import javax.imageio.IIOException;
|
|
||||||
import javax.imageio.ImageIO;
|
|
||||||
import javax.imageio.ImageReadParam;
|
|
||||||
import javax.imageio.ImageReader;
|
|
||||||
import javax.imageio.event.IIOReadWarningListener;
|
|
||||||
import javax.imageio.stream.ImageInputStream;
|
|
||||||
import java.awt.*;
|
|
||||||
import java.awt.image.*;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.function.Predicate;
|
|
||||||
|
|
||||||
import static com.twelvemonkeys.lang.Validate.notNull;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* DelegateTileDecoder.
|
|
||||||
*
|
|
||||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
|
||||||
* @author last modified by $Author: haraldk$
|
|
||||||
* @version $Id: DelegateTileDecoder.java,v 1.0 09/11/2023 haraldk Exp$
|
|
||||||
*/
|
|
||||||
class DelegateTileDecoder extends TileDecoder {
|
|
||||||
|
|
||||||
protected final ImageReader delegate;
|
|
||||||
protected final ImageReadParam param;
|
|
||||||
|
|
||||||
private final Predicate<ImageReader> needsRasterConversion;
|
|
||||||
private final RasterConverter converter;
|
|
||||||
private Boolean readRasterAndConvert;
|
|
||||||
|
|
||||||
DelegateTileDecoder(final IIOReadWarningListener warningListener, final String format, final ImageReadParam originalParam) throws IOException {
|
|
||||||
this(warningListener, createDelegate(format), originalParam, imageReader -> false, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
DelegateTileDecoder(final IIOReadWarningListener warningListener, final String format, final ImageReadParam originalParam, final Predicate<ImageReader> needsRasterConversion, final RasterConverter converter) throws IOException {
|
|
||||||
this(warningListener, createDelegate(format), originalParam, needsRasterConversion, converter);
|
|
||||||
}
|
|
||||||
|
|
||||||
private DelegateTileDecoder(final IIOReadWarningListener warningListener, final ImageReader delegate, final ImageReadParam originalParam, final Predicate<ImageReader> needsRasterConversion, final RasterConverter converter) {
|
|
||||||
super(warningListener);
|
|
||||||
|
|
||||||
this.delegate = notNull(delegate, "delegate");
|
|
||||||
delegate.addIIOReadWarningListener(warningListener);
|
|
||||||
|
|
||||||
if (TIFFImageReader.DEBUG) {
|
|
||||||
System.out.println("tile reading delegate: " + delegate);
|
|
||||||
}
|
|
||||||
|
|
||||||
param = delegate.getDefaultReadParam();
|
|
||||||
param.setSourceSubsampling(originalParam.getSourceXSubsampling(), originalParam.getSourceYSubsampling(), 0, 0);
|
|
||||||
|
|
||||||
this.needsRasterConversion = needsRasterConversion;
|
|
||||||
this.converter = converter;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static ImageReader createDelegate(String format) throws IOException {
|
|
||||||
// We'll just use the default (first) reader
|
|
||||||
// If it's the TwelveMonkeys one, we will be able to read JPEG Lossless etc.
|
|
||||||
Iterator<ImageReader> readers = ImageIO.getImageReadersByFormatName(format);
|
|
||||||
if (!readers.hasNext()) {
|
|
||||||
throw new IIOException("No ImageReader registered for '" + format + "' format");
|
|
||||||
}
|
|
||||||
|
|
||||||
return readers.next();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
void decodeTile(final ImageInputStream input, final Rectangle sourceRegion, final Point destinationOffset, final BufferedImage destination) throws IOException {
|
|
||||||
delegate.setInput(input);
|
|
||||||
param.setSourceRegion(sourceRegion);
|
|
||||||
|
|
||||||
if (readRasterAndConvert == null) {
|
|
||||||
// All tiles in an image will use the same format, test once and cache result
|
|
||||||
readRasterAndConvert = needsRasterConversion.test(delegate);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!readRasterAndConvert) {
|
|
||||||
// No conversion needed
|
|
||||||
param.setDestinationOffset(destinationOffset);
|
|
||||||
param.setDestination(destination);
|
|
||||||
delegate.read(0, param);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// Otherwise, it's likely CMYK or some other interpretation we don't need to convert.
|
|
||||||
// We'll have to use readAsRaster and later apply color space conversion ourselves
|
|
||||||
Raster raster = delegate.readRaster(0, param);
|
|
||||||
converter.convert(raster);
|
|
||||||
|
|
||||||
destination.getRaster().setDataElements(destinationOffset.x, destinationOffset.y, raster);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void close() {
|
|
||||||
delegate.dispose();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-198
@@ -1,198 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2023, 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.imageio.plugins.tiff;
|
|
||||||
|
|
||||||
import com.twelvemonkeys.lang.Validate;
|
|
||||||
|
|
||||||
import java.io.EOFException;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.nio.ByteBuffer;
|
|
||||||
import java.nio.ByteOrder;
|
|
||||||
import java.nio.channels.Channels;
|
|
||||||
import java.nio.channels.ReadableByteChannel;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A decoder for data converted using "floating point horizontal differencing predictor".
|
|
||||||
*
|
|
||||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
|
||||||
* @author last modified by $Author: haraldk$
|
|
||||||
* @version $Id: HorizontalDeDifferencingStream.java,v 1.0 11.03.13 14:20 haraldk Exp$
|
|
||||||
*/
|
|
||||||
final class HorizontalDeDifferencingFloatingPointStream extends InputStream {
|
|
||||||
// See TIFF 6.0 Specification, Section 14: "Differencing Predictor", page 64.
|
|
||||||
// Adapted from the C code in Adobe Photoshop® TIFF Technical Note 3
|
|
||||||
|
|
||||||
private final int columns;
|
|
||||||
// NOTE: PlanarConfiguration == 2 may be treated as samplesPerPixel == 1
|
|
||||||
private final int samplesPerPixel;
|
|
||||||
private final int bytesPerSample;
|
|
||||||
|
|
||||||
private final ReadableByteChannel channel;
|
|
||||||
private final ByteBuffer buffer;
|
|
||||||
private final byte[] fpRow;
|
|
||||||
|
|
||||||
public HorizontalDeDifferencingFloatingPointStream(final InputStream stream, final int columns, final int samplesPerPixel, final int bitsPerSample, final ByteOrder byteOrder) {
|
|
||||||
this.columns = Validate.isTrue(columns > 0, columns, "width must be greater than 0");
|
|
||||||
this.samplesPerPixel = samplesPerPixel;
|
|
||||||
Validate.isTrue(isValidBPS(bitsPerSample), bitsPerSample, "Unsupported bits per sample value: %s");
|
|
||||||
bytesPerSample = (samplesPerPixel * bitsPerSample + 7) / 8;
|
|
||||||
|
|
||||||
channel = Channels.newChannel(Validate.notNull(stream, "stream"));
|
|
||||||
buffer = ByteBuffer.allocate(columns * bytesPerSample)
|
|
||||||
.order(byteOrder);
|
|
||||||
fpRow = buffer.array().clone();
|
|
||||||
|
|
||||||
buffer.flip();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static boolean isValidBPS(final int bitsPerSample) {
|
|
||||||
switch (bitsPerSample) {
|
|
||||||
case 16:
|
|
||||||
case 24:
|
|
||||||
case 32:
|
|
||||||
case 64:
|
|
||||||
return true;
|
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("StatementWithEmptyBody")
|
|
||||||
private boolean fetch() throws IOException {
|
|
||||||
buffer.clear();
|
|
||||||
|
|
||||||
// This *SHOULD* read an entire row of pixels (or nothing at all) into the buffer,
|
|
||||||
// otherwise we will throw EOFException below
|
|
||||||
while (channel.read(buffer) > 0);
|
|
||||||
|
|
||||||
if (buffer.position() > 0) {
|
|
||||||
if (buffer.hasRemaining()) {
|
|
||||||
throw new EOFException("Unexpected end of stream");
|
|
||||||
}
|
|
||||||
|
|
||||||
decodeRow();
|
|
||||||
buffer.flip();
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
buffer.position(buffer.capacity());
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void decodeDeltaBytes(byte[] bytes, int columns, int samplesPerPixel) {
|
|
||||||
for (int column = 1; column < columns; column++) {
|
|
||||||
for (int channel = 0; channel < samplesPerPixel; channel++) {
|
|
||||||
bytes[column * samplesPerPixel + channel] = (byte) (bytes[column * samplesPerPixel + channel] + bytes[(column - 1) * samplesPerPixel + channel]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void decodeFloatingPointDelta(byte[] input, byte[] output, int columns, int channels, int bytesPerSample, final ByteOrder order) {
|
|
||||||
// undo byte difference on input
|
|
||||||
decodeDeltaBytes(input, columns * bytesPerSample, channels);
|
|
||||||
|
|
||||||
// reorder the bytes into the floating point buffer
|
|
||||||
int rowIncrement = columns * channels;
|
|
||||||
|
|
||||||
for (int column = 0; column < rowIncrement; column++) {
|
|
||||||
for (int b = 0; b < bytesPerSample; b++) {
|
|
||||||
output[bytesPerSample * column + b] = order == ByteOrder.BIG_ENDIAN
|
|
||||||
? input[b * rowIncrement + column]
|
|
||||||
: input[(bytesPerSample - b - 1) * rowIncrement + column];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void decodeRow() {
|
|
||||||
// Un-apply horizontal predictor
|
|
||||||
decodeFloatingPointDelta(buffer.array(), fpRow, columns, samplesPerPixel, bytesPerSample, buffer.order());
|
|
||||||
System.arraycopy(fpRow, 0, buffer.array(), 0, fpRow.length);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int read() throws IOException {
|
|
||||||
if (!buffer.hasRemaining()) {
|
|
||||||
if (!fetch()) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return buffer.get() & 0xff;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int read(byte[] b, int off, int len) throws IOException {
|
|
||||||
if (!buffer.hasRemaining()) {
|
|
||||||
if (!fetch()) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int read = Math.min(buffer.remaining(), len);
|
|
||||||
buffer.get(b, off, read);
|
|
||||||
|
|
||||||
return read;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long skip(long n) throws IOException {
|
|
||||||
if (n < 0) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!buffer.hasRemaining()) {
|
|
||||||
if (!fetch()) {
|
|
||||||
return 0; // SIC
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int skipped = (int) Math.min(buffer.remaining(), n);
|
|
||||||
buffer.position(buffer.position() + skipped);
|
|
||||||
|
|
||||||
return skipped;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void close() throws IOException {
|
|
||||||
try {
|
|
||||||
super.close();
|
|
||||||
}
|
|
||||||
finally {
|
|
||||||
if (channel.isOpen()) {
|
|
||||||
channel.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+1
-2
@@ -68,8 +68,7 @@ final class HorizontalDeDifferencingStream extends InputStream {
|
|||||||
|
|
||||||
channel = Channels.newChannel(Validate.notNull(stream, "stream"));
|
channel = Channels.newChannel(Validate.notNull(stream, "stream"));
|
||||||
|
|
||||||
buffer = ByteBuffer.allocate((columns * samplesPerPixel * bitsPerSample + 7) / 8)
|
buffer = ByteBuffer.allocate((columns * samplesPerPixel * bitsPerSample + 7) / 8).order(byteOrder);
|
||||||
.order(byteOrder);
|
|
||||||
buffer.flip();
|
buffer.flip();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+159
@@ -0,0 +1,159 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2012, 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.imageio.plugins.tiff;
|
||||||
|
|
||||||
|
import com.twelvemonkeys.imageio.metadata.jpeg.JPEG;
|
||||||
|
import com.twelvemonkeys.imageio.metadata.jpeg.JPEGQuality;
|
||||||
|
import com.twelvemonkeys.imageio.metadata.jpeg.JPEGSegment;
|
||||||
|
import com.twelvemonkeys.imageio.metadata.jpeg.JPEGSegmentUtil;
|
||||||
|
|
||||||
|
import javax.imageio.IIOException;
|
||||||
|
import javax.imageio.plugins.jpeg.JPEGHuffmanTable;
|
||||||
|
import javax.imageio.plugins.jpeg.JPEGQTable;
|
||||||
|
import javax.imageio.stream.ImageInputStream;
|
||||||
|
import java.io.DataInputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* JPEGTables
|
||||||
|
*
|
||||||
|
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||||
|
* @author last modified by $Author: haraldk$
|
||||||
|
* @version $Id: JPEGTables.java,v 1.0 11.05.12 09:13 haraldk Exp$
|
||||||
|
*/
|
||||||
|
class JPEGTables {
|
||||||
|
private static final int DHT_LENGTH = 16;
|
||||||
|
private static final Map<Integer, List<String>> SEGMENT_IDS = createSegmentIdsMap();
|
||||||
|
|
||||||
|
private JPEGQTable[] qTables;
|
||||||
|
private JPEGHuffmanTable[] dcHTables;
|
||||||
|
private JPEGHuffmanTable[] acHTables;
|
||||||
|
|
||||||
|
private static Map<Integer, List<String>> createSegmentIdsMap() {
|
||||||
|
Map<Integer, List<String>> segmentIds = new HashMap<Integer, List<String>>();
|
||||||
|
segmentIds.put(JPEG.DQT, null);
|
||||||
|
segmentIds.put(JPEG.DHT, null);
|
||||||
|
|
||||||
|
return Collections.unmodifiableMap(segmentIds);
|
||||||
|
}
|
||||||
|
|
||||||
|
private final List<JPEGSegment> segments;
|
||||||
|
|
||||||
|
public JPEGTables(ImageInputStream input) throws IOException {
|
||||||
|
segments = JPEGSegmentUtil.readSegments(input, SEGMENT_IDS);
|
||||||
|
}
|
||||||
|
|
||||||
|
public JPEGQTable[] getQTables() throws IOException {
|
||||||
|
if (qTables == null) {
|
||||||
|
qTables = JPEGQuality.getQTables(segments);
|
||||||
|
}
|
||||||
|
|
||||||
|
return qTables;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void getHuffmanTables() throws IOException {
|
||||||
|
if (dcHTables == null || acHTables == null) {
|
||||||
|
List<JPEGHuffmanTable> dc = new ArrayList<JPEGHuffmanTable>();
|
||||||
|
List<JPEGHuffmanTable> ac = new ArrayList<JPEGHuffmanTable>();
|
||||||
|
|
||||||
|
// JPEG may contain multiple DHT marker segments
|
||||||
|
for (JPEGSegment segment : segments) {
|
||||||
|
if (segment.marker() != JPEG.DHT) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
DataInputStream data = new DataInputStream(segment.data());
|
||||||
|
int read = 0;
|
||||||
|
|
||||||
|
// A single DHT marker segment may contain multiple tables
|
||||||
|
while (read < segment.length()) {
|
||||||
|
int htInfo = data.read();
|
||||||
|
read++;
|
||||||
|
|
||||||
|
int num = htInfo & 0x0f; // 0-3
|
||||||
|
int type = htInfo >> 4; // 0 == DC, 1 == AC
|
||||||
|
|
||||||
|
if (type > 1) {
|
||||||
|
throw new IIOException("Bad DHT type: " + type);
|
||||||
|
}
|
||||||
|
if (num >= 4) {
|
||||||
|
throw new IIOException("Bad DHT table index: " + num);
|
||||||
|
}
|
||||||
|
else if (type == 0 ? dc.size() > num : ac.size() > num) {
|
||||||
|
throw new IIOException("Duplicate DHT table index: " + num);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read lengths as short array
|
||||||
|
short[] lengths = new short[DHT_LENGTH];
|
||||||
|
for (int i = 0; i < DHT_LENGTH; i++) {
|
||||||
|
lengths[i] = (short) data.readUnsignedByte();
|
||||||
|
}
|
||||||
|
read += lengths.length;
|
||||||
|
|
||||||
|
int sum = 0;
|
||||||
|
for (short length : lengths) {
|
||||||
|
sum += length;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Expand table to short array
|
||||||
|
short[] table = new short[sum];
|
||||||
|
for (int j = 0; j < sum; j++) {
|
||||||
|
table[j] = (short) data.readUnsignedByte();
|
||||||
|
}
|
||||||
|
|
||||||
|
JPEGHuffmanTable hTable = new JPEGHuffmanTable(lengths, table);
|
||||||
|
if (type == 0) {
|
||||||
|
dc.add(num, hTable);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ac.add(num, hTable);
|
||||||
|
}
|
||||||
|
|
||||||
|
read += sum;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dcHTables = dc.toArray(new JPEGHuffmanTable[dc.size()]);
|
||||||
|
acHTables = ac.toArray(new JPEGHuffmanTable[ac.size()]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public JPEGHuffmanTable[] getDCHuffmanTables() throws IOException {
|
||||||
|
getHuffmanTables();
|
||||||
|
return dcHTables;
|
||||||
|
}
|
||||||
|
|
||||||
|
public JPEGHuffmanTable[] getACHuffmanTables() throws IOException {
|
||||||
|
getHuffmanTables();
|
||||||
|
return acHTables;
|
||||||
|
}
|
||||||
|
}
|
||||||
-37
@@ -1,37 +0,0 @@
|
|||||||
package com.twelvemonkeys.imageio.plugins.tiff;
|
|
||||||
|
|
||||||
import com.twelvemonkeys.imageio.stream.ByteArrayImageInputStream;
|
|
||||||
|
|
||||||
import javax.imageio.ImageReadParam;
|
|
||||||
import javax.imageio.ImageReader;
|
|
||||||
import javax.imageio.event.IIOReadWarningListener;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.function.Predicate;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* JPEGTileDecoder.
|
|
||||||
*
|
|
||||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
|
||||||
* @author last modified by $Author: haraldk$
|
|
||||||
* @version $Id: JPEGTileDecoder.java,v 1.0 09/11/2023 haraldk Exp$
|
|
||||||
*/
|
|
||||||
final class JPEGTileDecoder extends DelegateTileDecoder {
|
|
||||||
JPEGTileDecoder(final IIOReadWarningListener warningListener, final int compression, final byte[] jpegTables, final int numTiles, final ImageReadParam originalParam, final Predicate<ImageReader> needsConversion, final RasterConverter converter) throws IOException {
|
|
||||||
super(warningListener, "JPEG", originalParam, needsConversion, converter);
|
|
||||||
|
|
||||||
if (jpegTables != null) {
|
|
||||||
// This initializes the tables and other internal settings for the reader,
|
|
||||||
// and is actually a feature of JPEG, see "abbreviated streams":
|
|
||||||
// http://docs.oracle.com/javase/6/docs/api/javax/imageio/metadata/doc-files/jpeg_metadata.html#abbrev
|
|
||||||
delegate.setInput(new ByteArrayImageInputStream(jpegTables));
|
|
||||||
delegate.getStreamMetadata();
|
|
||||||
}
|
|
||||||
else if (numTiles > 1) {
|
|
||||||
// TODO: This is not really a problem as long as we read ALL tiles, but we can't have random access in this case...
|
|
||||||
if (compression == TIFFExtension.COMPRESSION_JPEG) {
|
|
||||||
warningListener.warningOccurred(delegate, "Missing JPEGTables for tiled/striped TIFF with compression: 7 (JPEG)");
|
|
||||||
}
|
|
||||||
// ...and the JPEG reader might choke on missing tables...
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-2
@@ -54,8 +54,6 @@ interface TIFFCustom {
|
|||||||
int COMPRESSION_JPEG2000 = 34712;
|
int COMPRESSION_JPEG2000 = 34712;
|
||||||
// TODO: Aperio SVS JPEG2000: 33003 (YCbCr) and 33005 (RGB), see http://openslide.org/formats/aperio/
|
// TODO: Aperio SVS JPEG2000: 33003 (YCbCr) and 33005 (RGB), see http://openslide.org/formats/aperio/
|
||||||
|
|
||||||
int COMPRESSION_WEBP = 50001;
|
|
||||||
|
|
||||||
// PIXTIFF aka DELL PixTools, see https://community.emc.com/message/515755#515755
|
// PIXTIFF aka DELL PixTools, see https://community.emc.com/message/515755#515755
|
||||||
/** PIXTIFF proprietary ZIP compression, identical to Deflate/ZLib. */
|
/** PIXTIFF proprietary ZIP compression, identical to Deflate/ZLib. */
|
||||||
int COMPRESSION_PIXTIFF_ZIP = 50013;
|
int COMPRESSION_PIXTIFF_ZIP = 50013;
|
||||||
|
|||||||
+507
-504
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user