mirror of
https://github.com/haraldk/TwelveMonkeys.git
synced 2026-05-24 00:00:01 -04:00
Compare commits
10 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 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"
|
|
||||||
+15
-27
@@ -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,11 +80,11 @@ 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)
|
||||||
MAVEN_CENTRAL_GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }} # must be the same env variable name as (3)
|
MAVEN_CENTRAL_GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }} # must be the same env variable name as (3)
|
||||||
@@ -1,69 +0,0 @@
|
|||||||
name: "CodeQL"
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches: [ "master" ]
|
|
||||||
pull_request:
|
|
||||||
# The branches below must be a subset of the branches above
|
|
||||||
branches: [ "master" ]
|
|
||||||
schedule:
|
|
||||||
- cron: '26 13 * * 6'
|
|
||||||
|
|
||||||
permissions: {}
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
analyze:
|
|
||||||
name: Analyze
|
|
||||||
# Runner size impacts CodeQL analysis time. To learn more, please see:
|
|
||||||
# - https://gh.io/recommended-hardware-resources-for-running-codeql
|
|
||||||
# - https://gh.io/supported-runners-and-hardware-resources
|
|
||||||
# - https://gh.io/using-larger-runners
|
|
||||||
# Consider using larger runners for possible analysis time improvements.
|
|
||||||
runs-on: ${{ (matrix.language == 'swift' && 'macos-latest') || 'ubuntu-latest' }}
|
|
||||||
timeout-minutes: ${{ (matrix.language == 'swift' && 120) || 360 }}
|
|
||||||
permissions:
|
|
||||||
actions: read
|
|
||||||
contents: read
|
|
||||||
security-events: write
|
|
||||||
|
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
language: [ 'java' ]
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Checkout repository
|
|
||||||
uses: actions/checkout@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.9.4</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.9.4</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.9.4</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.9.4</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.9.4.jar
|
twelvemonkeys-common-lang-3.8.1.jar
|
||||||
twelvemonkeys-common-io-3.9.4.jar
|
twelvemonkeys-common-io-3.8.1.jar
|
||||||
twelvemonkeys-common-image-3.9.4.jar
|
twelvemonkeys-common-image-3.8.1.jar
|
||||||
twelvemonkeys-imageio-core-3.9.4.jar
|
twelvemonkeys-imageio-core-3.8.1.jar
|
||||||
twelvemonkeys-imageio-metadata-3.9.4.jar
|
twelvemonkeys-imageio-metadata-3.8.1.jar
|
||||||
twelvemonkeys-imageio-jpeg-3.9.4.jar
|
twelvemonkeys-imageio-jpeg-3.8.1.jar
|
||||||
twelvemonkeys-imageio-tiff-3.9.4.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.9.4)
|
##### 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.9.4.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/common/common-lang/3.9.4/common-lang-3.9.4.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.9.4.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/common/common-io/3.9.4/common-io-3.9.4.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.9.4.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/common/common-image/3.9.4/common-image-3.9.4.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.9.4.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-core/3.9.4/imageio-core-3.9.4.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.9.4.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-metadata/3.9.4/imageio-metadata-3.9.4.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.9.4.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-bmp/3.9.4/imageio-bmp-3.9.4.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.9.4.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-hdr/3.9.4/imageio-hdr-3.9.4.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.9.4.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-icns/3.9.4/imageio-icns-3.9.4.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.9.4.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-iff/3.9.4/imageio-iff-3.9.4.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.9.4.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-jpeg/3.9.4/imageio-jpeg-3.9.4.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.9.4.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-pcx/3.9.4/imageio-pcx-3.9.4.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.9.4.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-pict/3.9.4/imageio-pict-3.9.4.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.9.4.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-pnm/3.9.4/imageio-pnm-3.9.4.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.9.4.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-psd/3.9.4/imageio-psd-3.9.4.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.9.4.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-sgi/3.9.4/imageio-sgi-3.9.4.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.9.4.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-tga/3.9.4/imageio-tga-3.9.4.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.9.4.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-thumbsdb/3.9.4/imageio-thumbsdb-3.9.4.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.9.4.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-tiff/3.9.4/imageio-tiff-3.9.4.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.9.4.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-webp/3.9.4/imageio-webp-3.9.4.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.9.4.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-xwd/3.9.4/imageio-xwd-3.9.4.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.9.4.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-batik/3.9.4/imageio-batik-3.9.4.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.9.4.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-clippath/3.9.4/imageio-clippath-3.9.4.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.9.4.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/servlet/servlet/3.9.4/servlet-3.9.4.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.10.2-SNAPSHOT</version>
|
<version>3.9.2</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.10.2-SNAPSHOT</version>
|
<version>3.9.2</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.10.2-SNAPSHOT</version>
|
<version>3.9.2</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.10.2-SNAPSHOT</version>
|
<version>3.9.2</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.10.2-SNAPSHOT</version>
|
<version>3.9.2</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.10.2-SNAPSHOT</version>
|
<version>3.9.2</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.10.2-SNAPSHOT</version>
|
<version>3.9.2</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.15</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.10.2-SNAPSHOT</version>
|
<version>3.9.2</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.10.2-SNAPSHOT</version>
|
<version>3.9.2</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.10.2-SNAPSHOT</version>
|
<version>3.9.2</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();
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-17
@@ -17,12 +17,8 @@ final class MemoryCache implements Cache {
|
|||||||
|
|
||||||
final static int BLOCK_SIZE = 1 << 13;
|
final static int BLOCK_SIZE = 1 << 13;
|
||||||
|
|
||||||
private static final byte[] NULL_BLOCK = new byte[0];
|
|
||||||
|
|
||||||
private final List<byte[]> cache = new ArrayList<>();
|
private final List<byte[]> cache = new ArrayList<>();
|
||||||
private final ReadableByteChannel channel;
|
private final ReadableByteChannel channel;
|
||||||
|
|
||||||
private int maxBlock = Integer.MAX_VALUE;
|
|
||||||
private long length;
|
private long length;
|
||||||
private long position;
|
private long position;
|
||||||
private long start;
|
private long start;
|
||||||
@@ -38,14 +34,12 @@ final class MemoryCache implements Cache {
|
|||||||
|
|
||||||
byte[] fetchBlock() throws IOException {
|
byte[] fetchBlock() throws IOException {
|
||||||
long currPos = position;
|
long currPos = position;
|
||||||
|
|
||||||
long index = currPos / BLOCK_SIZE;
|
long index = currPos / BLOCK_SIZE;
|
||||||
|
|
||||||
if (index >= Integer.MAX_VALUE) {
|
if (index >= Integer.MAX_VALUE) {
|
||||||
throw new IOException("Memory cache max size exceeded");
|
throw new IOException("Memory cache max size exceeded");
|
||||||
}
|
}
|
||||||
if (index > maxBlock) {
|
|
||||||
return NULL_BLOCK;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (index >= cache.size()) {
|
while (index >= cache.size()) {
|
||||||
byte[] block;
|
byte[] block;
|
||||||
@@ -57,14 +51,7 @@ final class MemoryCache implements Cache {
|
|||||||
}
|
}
|
||||||
|
|
||||||
cache.add(block);
|
cache.add(block);
|
||||||
int bytesRead = readBlock(block);
|
length += readBlock(block);
|
||||||
length += bytesRead;
|
|
||||||
|
|
||||||
if (bytesRead < BLOCK_SIZE) {
|
|
||||||
// Last block, EOF found
|
|
||||||
maxBlock = (int) index;
|
|
||||||
return block;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return cache.get((int) index);
|
return cache.get((int) index);
|
||||||
@@ -76,7 +63,7 @@ final class MemoryCache implements Cache {
|
|||||||
while (wrapped.hasRemaining()) {
|
while (wrapped.hasRemaining()) {
|
||||||
int count = channel.read(wrapped);
|
int count = channel.read(wrapped);
|
||||||
if (count == -1) {
|
if (count == -1) {
|
||||||
// Last block, EOF found
|
// Last block
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -97,12 +84,12 @@ final class MemoryCache implements Cache {
|
|||||||
@Override
|
@Override
|
||||||
public int read(ByteBuffer dest) throws IOException {
|
public int read(ByteBuffer dest) throws IOException {
|
||||||
byte[] buffer = fetchBlock();
|
byte[] buffer = fetchBlock();
|
||||||
|
int bufferPos = (int) (position % BLOCK_SIZE);
|
||||||
|
|
||||||
if (position >= length) {
|
if (position >= length) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int bufferPos = (int) (position % BLOCK_SIZE);
|
|
||||||
int len = min(dest.remaining(), (int) min(BLOCK_SIZE - bufferPos, length - position));
|
int len = min(dest.remaining(), (int) min(BLOCK_SIZE - bufferPos, length - position));
|
||||||
dest.put(buffer, bufferPos, len);
|
dest.put(buffer, bufferPos, len);
|
||||||
|
|
||||||
|
|||||||
+21
-21
@@ -53,20 +53,20 @@ public final class SubImageInputStream extends ImageInputStreamImpl {
|
|||||||
/**
|
/**
|
||||||
* Creates a {@link ImageInputStream}, reading up to a maximum number of bytes from the underlying stream.
|
* Creates a {@link ImageInputStream}, reading up to a maximum number of bytes from the underlying stream.
|
||||||
*
|
*
|
||||||
* @param stream the underlying stream
|
* @param pStream the underlying stream
|
||||||
* @param length the maximum length to read from the stream.
|
* @param pLength the maximum length to read from the stream.
|
||||||
* Note that {@code stream} may contain less than this maximum number of bytes.
|
* Note that {@code pStream} may contain less than this maximum number of bytes.
|
||||||
*
|
*
|
||||||
* @throws IOException if {@code stream}'s position can't be determined.
|
* @throws IOException if {@code pStream}'s position can't be determined.
|
||||||
* @throws IllegalArgumentException if {@code stream == null} or {@code length < 0}
|
* @throws IllegalArgumentException if {@code pStream == null} or {@code pLength < 0}
|
||||||
*/
|
*/
|
||||||
public SubImageInputStream(final ImageInputStream stream, final long length) throws IOException {
|
public SubImageInputStream(final ImageInputStream pStream, final long pLength) throws IOException {
|
||||||
Validate.notNull(stream, "stream");
|
Validate.notNull(pStream, "stream");
|
||||||
Validate.isTrue(length >= 0, length, "length < 0: %d");
|
Validate.isTrue(pLength >= 0, pLength, "length < 0: %d");
|
||||||
|
|
||||||
this.stream = stream;
|
stream = pStream;
|
||||||
this.startPos = stream.getStreamPosition();
|
startPos = pStream.getStreamPosition();
|
||||||
this.length = length;
|
length = pLength;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int read() throws IOException {
|
public int read() throws IOException {
|
||||||
@@ -84,14 +84,14 @@ public final class SubImageInputStream extends ImageInputStreamImpl {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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 (streamPos >= length) { // Local EOF
|
if (streamPos >= length) { // Local EOF
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Safe cast, as len can never cause int overflow
|
// Safe cast, as pLength can never cause int overflow
|
||||||
int length = (int) Math.min(len, this.length - streamPos);
|
int length = (int) Math.min(pLength, this.length - streamPos);
|
||||||
int count = stream.read(bytes, off, length);
|
int count = stream.read(pBytes, pOffset, length);
|
||||||
|
|
||||||
if (count >= 0) {
|
if (count >= 0) {
|
||||||
streamPos += count;
|
streamPos += count;
|
||||||
@@ -113,18 +113,18 @@ public final class SubImageInputStream extends ImageInputStreamImpl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void seek(final long position) throws IOException {
|
public void seek(final long pPosition) throws IOException {
|
||||||
if (position < getFlushedPosition()) {
|
if (pPosition < getFlushedPosition()) {
|
||||||
throw new IndexOutOfBoundsException("pos < flushedPosition");
|
throw new IndexOutOfBoundsException("pos < flushedPosition");
|
||||||
}
|
}
|
||||||
|
|
||||||
stream.seek(startPos + position);
|
stream.seek(startPos + pPosition);
|
||||||
streamPos = position;
|
streamPos = pPosition;
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("MethodDoesntCallSuperMethod")
|
@SuppressWarnings({"FinalizeDoesntCallSuperFinalize"})
|
||||||
@Override
|
@Override
|
||||||
protected void finalize() {
|
protected void finalize() throws Throwable {
|
||||||
// Empty finalizer (for improved performance; no need to call super.finalize() in this case)
|
// Empty finalizer (for improved performance; no need to call super.finalize() in this case)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+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);
|
||||||
|
|
||||||
|
|||||||
-18
@@ -402,24 +402,6 @@ public class BufferedChannelImageInputStreamMemoryCacheTest {
|
|||||||
assertEquals(-1, stream.read());
|
assertEquals(-1, stream.read());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@Test
|
|
||||||
public void testSeekWayPastEOFShouldNotThrowOOME() throws IOException {
|
|
||||||
byte[] bytes = new byte[9];
|
|
||||||
InputStream input = randomDataToInputStream(bytes);
|
|
||||||
|
|
||||||
try (final ImageInputStream stream = new BufferedChannelImageInputStream(new MemoryCache(input))) {
|
|
||||||
stream.seek(Integer.MAX_VALUE * 4L * 512L); // ~4 TB
|
|
||||||
|
|
||||||
assertEquals(-1, stream.read()); // No OOME should happen...
|
|
||||||
|
|
||||||
stream.seek(0);
|
|
||||||
for (byte value : bytes) {
|
|
||||||
assertEquals(value, stream.readByte());
|
|
||||||
}
|
|
||||||
|
|
||||||
assertEquals(-1, stream.read());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testClose() throws IOException {
|
public void testClose() throws IOException {
|
||||||
|
|||||||
+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.10.2-SNAPSHOT</version>
|
<version>3.9.2</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.10.2-SNAPSHOT</version>
|
<version>3.9.2</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.10.2-SNAPSHOT</version>
|
<version>3.9.2</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.10.2-SNAPSHOT</version>
|
<version>3.9.2</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.10.2-SNAPSHOT</version>
|
<version>3.9.2</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.10.2-SNAPSHOT</version>
|
<version>3.9.2</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.10.2-SNAPSHOT</version>
|
<version>3.9.2</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>
|
||||||
|
|||||||
+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.10.2-SNAPSHOT</version>
|
<version>3.9.2</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.10.2-SNAPSHOT</version>
|
<version>3.9.2</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.10.2-SNAPSHOT</version>
|
<version>3.9.2</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.10.2-SNAPSHOT</version>
|
<version>3.9.2</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>
|
||||||
|
|||||||
+21
-25
@@ -30,6 +30,8 @@
|
|||||||
|
|
||||||
package com.twelvemonkeys.imageio.plugins.pnm;
|
package com.twelvemonkeys.imageio.plugins.pnm;
|
||||||
|
|
||||||
|
import com.twelvemonkeys.imageio.ImageWriterBase;
|
||||||
|
|
||||||
import org.w3c.dom.NodeList;
|
import org.w3c.dom.NodeList;
|
||||||
|
|
||||||
import javax.imageio.IIOImage;
|
import javax.imageio.IIOImage;
|
||||||
@@ -38,7 +40,7 @@ import javax.imageio.metadata.IIOMetadataFormatImpl;
|
|||||||
import javax.imageio.metadata.IIOMetadataNode;
|
import javax.imageio.metadata.IIOMetadataNode;
|
||||||
import javax.imageio.spi.ImageWriterSpi;
|
import javax.imageio.spi.ImageWriterSpi;
|
||||||
import javax.imageio.stream.ImageOutputStream;
|
import javax.imageio.stream.ImageOutputStream;
|
||||||
import java.awt.image.*;
|
import java.awt.image.DataBuffer;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
|
||||||
@@ -51,7 +53,11 @@ abstract class HeaderWriter {
|
|||||||
this.imageOutput = imageOutput;
|
this.imageOutput = imageOutput;
|
||||||
}
|
}
|
||||||
|
|
||||||
static HeaderWriter createHeaderWriter(final String formatName, final ImageOutputStream imageOutput) {
|
public static void write(final IIOImage image, final ImageWriterBase writer, final ImageOutputStream imageOutput) throws IOException {
|
||||||
|
createHeaderWriter(writer.getFormatName(), imageOutput).writeHeader(image, writer.getOriginatingProvider());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static HeaderWriter createHeaderWriter(final String formatName, final ImageOutputStream imageOutput) {
|
||||||
if (formatName.equals("pam")) {
|
if (formatName.equals("pam")) {
|
||||||
return new PAMHeaderWriter(imageOutput);
|
return new PAMHeaderWriter(imageOutput);
|
||||||
}
|
}
|
||||||
@@ -77,36 +83,25 @@ abstract class HeaderWriter {
|
|||||||
return image.hasRaster() ? image.getRaster().getNumBands() : image.getRenderedImage().getSampleModel().getNumBands();
|
return image.hasRaster() ? image.getRaster().getNumBands() : image.getRenderedImage().getSampleModel().getNumBands();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected final SampleModel getSampleModel(final IIOImage image) {
|
|
||||||
return image.hasRaster() ? image.getRaster().getSampleModel() : image.getRenderedImage().getSampleModel();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected int getMaxVal(final IIOImage image) {
|
protected int getMaxVal(final IIOImage image) {
|
||||||
int transferType = getTransferType(image);
|
int transferType = getTransferType(image);
|
||||||
|
|
||||||
switch (transferType) {
|
if (transferType == DataBuffer.TYPE_BYTE) {
|
||||||
case DataBuffer.TYPE_BYTE:
|
return PNM.MAX_VAL_8BIT;
|
||||||
return PNM.MAX_VAL_8BIT;
|
}
|
||||||
|
else if (transferType == DataBuffer.TYPE_USHORT) {
|
||||||
case DataBuffer.TYPE_USHORT:
|
return PNM.MAX_VAL_16BIT;
|
||||||
return PNM.MAX_VAL_16BIT;
|
}
|
||||||
|
// else if (transferType == DataBuffer.TYPE_INT) {
|
||||||
case DataBuffer.TYPE_INT:
|
// TODO: Support TYPE_INT through conversion, if number of channels is 3 or 4 (TYPE_INT_RGB, TYPE_INT_ARGB)
|
||||||
// We support TYPE_INT through conversion, if number of channels is 3 or 4 (TYPE_INT_RGB, TYPE_INT_ARGB)
|
// }
|
||||||
SampleModel sampleModel = getSampleModel(image);
|
else {
|
||||||
int numBands = sampleModel.getNumBands();
|
throw new IllegalArgumentException("Unsupported data type: " + transferType);
|
||||||
|
|
||||||
if (sampleModel instanceof SinglePixelPackedSampleModel && (numBands == 3 || numBands == 4)) {
|
|
||||||
return PNM.MAX_VAL_8BIT;
|
|
||||||
}
|
|
||||||
// ...else fall through
|
|
||||||
default:
|
|
||||||
throw new IllegalArgumentException("Unsupported data type: " + transferType);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected final int getTransferType(final IIOImage image) {
|
protected final int getTransferType(final IIOImage image) {
|
||||||
return image.hasRaster() ? image.getRaster().getTransferType() : image.getRenderedImage().getSampleModel().getTransferType();
|
return image.hasRaster() ? image.getRaster().getTransferType() : image.getRenderedImage().getSampleModel().getTransferType();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected final void writeComments(final IIOMetadata metadata, final ImageWriterSpi provider) throws IOException {
|
protected final void writeComments(final IIOMetadata metadata, final ImageWriterSpi provider) throws IOException {
|
||||||
@@ -125,4 +120,5 @@ abstract class HeaderWriter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+5
-16
@@ -30,8 +30,6 @@
|
|||||||
|
|
||||||
package com.twelvemonkeys.imageio.plugins.pnm;
|
package com.twelvemonkeys.imageio.plugins.pnm;
|
||||||
|
|
||||||
import com.twelvemonkeys.imageio.util.ImageTypeSpecifiers;
|
|
||||||
|
|
||||||
import javax.imageio.IIOImage;
|
import javax.imageio.IIOImage;
|
||||||
import javax.imageio.spi.ImageWriterSpi;
|
import javax.imageio.spi.ImageWriterSpi;
|
||||||
import javax.imageio.stream.ImageOutputStream;
|
import javax.imageio.stream.ImageOutputStream;
|
||||||
@@ -46,8 +44,6 @@ final class PAMHeaderWriter extends HeaderWriter {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void writeHeader(final IIOImage image, final ImageWriterSpi provider) throws IOException {
|
public void writeHeader(final IIOImage image, final ImageWriterSpi provider) throws IOException {
|
||||||
TupleType tupleType = tupleType(image);
|
|
||||||
|
|
||||||
// Write PAM magic
|
// Write PAM magic
|
||||||
imageOutput.writeShort(PNM.PAM);
|
imageOutput.writeShort(PNM.PAM);
|
||||||
imageOutput.write('\n');
|
imageOutput.write('\n');
|
||||||
@@ -56,19 +52,12 @@ final class PAMHeaderWriter extends HeaderWriter {
|
|||||||
// Write width/height and number of channels
|
// Write width/height and number of channels
|
||||||
imageOutput.write(String.format("WIDTH %s\nHEIGHT %s\n", getWidth(image), getHeight(image)).getBytes(UTF_8));
|
imageOutput.write(String.format("WIDTH %s\nHEIGHT %s\n", getWidth(image), getHeight(image)).getBytes(UTF_8));
|
||||||
imageOutput.write(String.format("DEPTH %s\n", getNumBands(image)).getBytes(UTF_8));
|
imageOutput.write(String.format("DEPTH %s\n", getNumBands(image)).getBytes(UTF_8));
|
||||||
|
|
||||||
|
// TODO: maxSample (8 or16 bit)
|
||||||
imageOutput.write(String.format("MAXVAL %s\n", getMaxVal(image)).getBytes(UTF_8));
|
imageOutput.write(String.format("MAXVAL %s\n", getMaxVal(image)).getBytes(UTF_8));
|
||||||
|
|
||||||
|
// TODO: Determine tuple type based on input color model and image data
|
||||||
|
TupleType tupleType = getNumBands(image) > 3 ? TupleType.RGB_ALPHA : TupleType.RGB;
|
||||||
imageOutput.write(String.format("TUPLTYPE %s\nENDHDR\n", tupleType).getBytes(UTF_8));
|
imageOutput.write(String.format("TUPLTYPE %s\nENDHDR\n", tupleType).getBytes(UTF_8));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static TupleType tupleType(IIOImage image) {
|
|
||||||
TupleType tupleType = image.hasRaster()
|
|
||||||
? TupleType.forPAM(image.getRaster())
|
|
||||||
: TupleType.forPAM(ImageTypeSpecifiers.createFromRenderedImage(image.getRenderedImage()));
|
|
||||||
|
|
||||||
if (tupleType == null) {
|
|
||||||
throw new IllegalArgumentException("Unknown TupleType for " + (image.hasRaster() ? image.getRaster() : image.getRenderedImage()));
|
|
||||||
}
|
|
||||||
|
|
||||||
return tupleType;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-3
@@ -45,11 +45,12 @@ public final class PAMImageWriterSpi extends ImageWriterSpiBase {
|
|||||||
super(new PAMProviderInfo());
|
super(new PAMProviderInfo());
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean canEncodeImage(final ImageTypeSpecifier type) {
|
public boolean canEncodeImage(final ImageTypeSpecifier pType) {
|
||||||
return TupleType.forPAM(type) != null;
|
// TODO: FixMe
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ImageWriter createWriterInstance(final Object extension) {
|
public ImageWriter createWriterInstance(final Object pExtension) {
|
||||||
return new PNMImageWriter(this);
|
return new PNMImageWriter(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -69,7 +69,7 @@ final class PFMHeaderParser extends HeaderParser {
|
|||||||
public PNMHeader parse() throws IOException {
|
public PNMHeader parse() throws IOException {
|
||||||
int width = 0;
|
int width = 0;
|
||||||
int height = 0;
|
int height = 0;
|
||||||
float maxSample = 0;
|
float maxSample = tupleType == TupleType.BLACKANDWHITE_WHITE_IS_ZERO ? 1 : 0; // PBM has no maxSample line
|
||||||
|
|
||||||
List<String> comments = new ArrayList<>();
|
List<String> comments = new ArrayList<>();
|
||||||
|
|
||||||
@@ -77,7 +77,7 @@ final class PFMHeaderParser extends HeaderParser {
|
|||||||
String line = input.readLine();
|
String line = input.readLine();
|
||||||
|
|
||||||
if (line == null) {
|
if (line == null) {
|
||||||
throw new IIOException("Unexpected end of stream");
|
throw new IIOException("Unexpeced end of stream");
|
||||||
}
|
}
|
||||||
|
|
||||||
int commentStart = line.indexOf('#');
|
int commentStart = line.indexOf('#');
|
||||||
|
|||||||
+2
-34
@@ -30,8 +30,6 @@
|
|||||||
|
|
||||||
package com.twelvemonkeys.imageio.plugins.pnm;
|
package com.twelvemonkeys.imageio.plugins.pnm;
|
||||||
|
|
||||||
import com.twelvemonkeys.imageio.util.ImageTypeSpecifiers;
|
|
||||||
|
|
||||||
import javax.imageio.IIOImage;
|
import javax.imageio.IIOImage;
|
||||||
import javax.imageio.spi.ImageWriterSpi;
|
import javax.imageio.spi.ImageWriterSpi;
|
||||||
import javax.imageio.stream.ImageOutputStream;
|
import javax.imageio.stream.ImageOutputStream;
|
||||||
@@ -47,7 +45,8 @@ final class PNMHeaderWriter extends HeaderWriter {
|
|||||||
@Override
|
@Override
|
||||||
public void writeHeader(final IIOImage image, final ImageWriterSpi provider) throws IOException {
|
public void writeHeader(final IIOImage image, final ImageWriterSpi provider) throws IOException {
|
||||||
// Write P4/P5/P6 magic (Support only RAW formats for now; if we are to support PLAIN formats, pass parameter)
|
// Write P4/P5/P6 magic (Support only RAW formats for now; if we are to support PLAIN formats, pass parameter)
|
||||||
short type = type(image);
|
// TODO: Determine PBM, PBM or PPM based on input color model and image data?
|
||||||
|
short type = PNM.PPM;
|
||||||
imageOutput.writeShort(type);
|
imageOutput.writeShort(type);
|
||||||
imageOutput.write('\n');
|
imageOutput.write('\n');
|
||||||
|
|
||||||
@@ -62,35 +61,4 @@ final class PNMHeaderWriter extends HeaderWriter {
|
|||||||
imageOutput.write(String.format("%s\n", getMaxVal(image)).getBytes(UTF_8));
|
imageOutput.write(String.format("%s\n", getMaxVal(image)).getBytes(UTF_8));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private short type(IIOImage image) {
|
|
||||||
TupleType type = tupleType(image);
|
|
||||||
|
|
||||||
if (type != null) {
|
|
||||||
switch (type) {
|
|
||||||
case BLACKANDWHITE_WHITE_IS_ZERO:
|
|
||||||
return PNM.PBM;
|
|
||||||
case GRAYSCALE:
|
|
||||||
return PNM.PGM;
|
|
||||||
case RGB:
|
|
||||||
return PNM.PPM;
|
|
||||||
default:
|
|
||||||
// fall through...
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new IllegalArgumentException("Unsupported tupleType: " + type);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static TupleType tupleType(IIOImage image) {
|
|
||||||
TupleType tupleType = image.hasRaster()
|
|
||||||
? TupleType.forPNM(image.getRaster())
|
|
||||||
: TupleType.forPNM(ImageTypeSpecifiers.createFromRenderedImage(image.getRenderedImage()));
|
|
||||||
|
|
||||||
if (tupleType == null) {
|
|
||||||
throw new IllegalArgumentException("Unknown TupleType for " + (image.hasRaster() ? image.getRaster() : image.getRenderedImage()));
|
|
||||||
}
|
|
||||||
|
|
||||||
return tupleType;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
+8
-15
@@ -31,17 +31,14 @@
|
|||||||
package com.twelvemonkeys.imageio.plugins.pnm;
|
package com.twelvemonkeys.imageio.plugins.pnm;
|
||||||
|
|
||||||
import com.twelvemonkeys.imageio.ImageWriterBase;
|
import com.twelvemonkeys.imageio.ImageWriterBase;
|
||||||
import com.twelvemonkeys.imageio.util.RasterUtils;
|
|
||||||
|
|
||||||
import javax.imageio.IIOImage;
|
import javax.imageio.*;
|
||||||
import javax.imageio.ImageIO;
|
|
||||||
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.spi.ImageWriterSpi;
|
import javax.imageio.spi.ImageWriterSpi;
|
||||||
import javax.imageio.stream.ImageOutputStream;
|
import java.awt.image.BufferedImage;
|
||||||
import java.awt.image.*;
|
import java.awt.image.DataBuffer;
|
||||||
|
import java.awt.image.Raster;
|
||||||
|
import java.awt.image.SampleModel;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
@@ -72,7 +69,7 @@ public final class PNMImageWriter extends ImageWriterBase {
|
|||||||
// TODO: Issue warning if streamMetadata is non-null?
|
// TODO: Issue warning if streamMetadata is non-null?
|
||||||
// TODO: Issue warning if IIOImage contains thumbnails or other data we can't store?
|
// TODO: Issue warning if IIOImage contains thumbnails or other data we can't store?
|
||||||
|
|
||||||
writeHeader(image, this, imageOutput);
|
HeaderWriter.write(image, this, imageOutput);
|
||||||
|
|
||||||
// TODO: Sub region
|
// TODO: Sub region
|
||||||
// TODO: Subsampling
|
// TODO: Subsampling
|
||||||
@@ -83,20 +80,16 @@ public final class PNMImageWriter extends ImageWriterBase {
|
|||||||
processImageComplete();
|
processImageComplete();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void writeHeader(final IIOImage image, final ImageWriterBase writer, final ImageOutputStream imageOutput) throws IOException {
|
|
||||||
HeaderWriter.createHeaderWriter(writer.getFormatName(), imageOutput).writeHeader(image, writer.getOriginatingProvider());
|
|
||||||
}
|
|
||||||
|
|
||||||
private void writeImageData(final IIOImage image) throws IOException {
|
private void writeImageData(final IIOImage image) throws IOException {
|
||||||
// - dump data as is (or convert, if TYPE_INT_xxx
|
// - dump data as is (or convert, if TYPE_INT_xxx)
|
||||||
// Enforce RGB/CMYK order for such data!
|
// Enforce RGB/CMYK order for such data!
|
||||||
|
|
||||||
// TODO: Loop over x/y tiles, using 0,0 is only valid for BufferedImage
|
// TODO: Loop over x/y tiles, using 0,0 is only valid for BufferedImage
|
||||||
// TODO: PNM/PAM does not support tiling, we must iterate all tiles along the x-axis for each row we write
|
// TODO: PNM/PAM does not support tiling, we must iterate all tiles along the x-axis for each row we write
|
||||||
Raster tile = image.hasRaster() ? image.getRaster() : image.getRenderedImage().getTile(0, 0);
|
Raster tile = image.hasRaster() ? image.getRaster() : image.getRenderedImage().getTile(0, 0);
|
||||||
tile = tile.getTransferType() == DataBuffer.TYPE_INT ? RasterUtils.asByteRaster(tile) : tile;
|
|
||||||
|
|
||||||
SampleModel sampleModel = tile.getSampleModel();
|
SampleModel sampleModel = tile.getSampleModel();
|
||||||
|
|
||||||
DataBuffer dataBuffer = tile.getDataBuffer();
|
DataBuffer dataBuffer = tile.getDataBuffer();
|
||||||
|
|
||||||
int tileWidth = tile.getWidth();
|
int tileWidth = tile.getWidth();
|
||||||
|
|||||||
+4
-3
@@ -48,11 +48,12 @@ public final class PNMImageWriterSpi extends ImageWriterSpiBase {
|
|||||||
super(new PNMProviderInfo());
|
super(new PNMProviderInfo());
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean canEncodeImage(final ImageTypeSpecifier type) {
|
public boolean canEncodeImage(final ImageTypeSpecifier pType) {
|
||||||
return TupleType.forPNM(type) != null;
|
// TODO: FixMe: Support only 1 bit b/w, 8-16 bit gray and 8-16 bit/sample RGB
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ImageWriter createWriterInstance(final Object extension) {
|
public ImageWriter createWriterInstance(final Object pExtension) {
|
||||||
return new PNMImageWriter(this);
|
return new PNMImageWriter(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
-149
@@ -30,10 +30,7 @@
|
|||||||
|
|
||||||
package com.twelvemonkeys.imageio.plugins.pnm;
|
package com.twelvemonkeys.imageio.plugins.pnm;
|
||||||
|
|
||||||
import javax.imageio.ImageTypeSpecifier;
|
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.awt.color.*;
|
|
||||||
import java.awt.image.*;
|
|
||||||
|
|
||||||
enum TupleType {
|
enum TupleType {
|
||||||
// Official:
|
// Official:
|
||||||
@@ -83,150 +80,4 @@ enum TupleType {
|
|||||||
public boolean isValidMaxSample(int maxSample) {
|
public boolean isValidMaxSample(int maxSample) {
|
||||||
return maxSample >= minMaxSample && maxSample <= maxMaxSample;
|
return maxSample >= minMaxSample && maxSample <= maxMaxSample;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static TupleType forPNM(Raster raster) {
|
|
||||||
return filterPNM(forPAM(raster));
|
|
||||||
}
|
|
||||||
|
|
||||||
static TupleType forPNM(ImageTypeSpecifier type) {
|
|
||||||
return filterPNM(forPAM(type));
|
|
||||||
}
|
|
||||||
|
|
||||||
private static TupleType filterPNM(TupleType tupleType) {
|
|
||||||
if (tupleType == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (tupleType) {
|
|
||||||
case BLACKANDWHITE:
|
|
||||||
return BLACKANDWHITE_WHITE_IS_ZERO;
|
|
||||||
case GRAYSCALE:
|
|
||||||
case RGB:
|
|
||||||
return tupleType;
|
|
||||||
default:
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static TupleType forPAM(Raster raster) {
|
|
||||||
SampleModel sampleModel = raster.getSampleModel();
|
|
||||||
switch (sampleModel.getTransferType()) {
|
|
||||||
case DataBuffer.TYPE_BYTE:
|
|
||||||
case DataBuffer.TYPE_USHORT:
|
|
||||||
case DataBuffer.TYPE_INT:
|
|
||||||
// B/W, Gray or RGB
|
|
||||||
int bands = sampleModel.getNumBands();
|
|
||||||
|
|
||||||
if (bands == 1 && sampleModel.getSampleSize(0) == 1) {
|
|
||||||
return TupleType.BLACKANDWHITE;
|
|
||||||
}
|
|
||||||
else if (bands == 2 && sampleModel.getSampleSize(0) == 1 && sampleModel.getSampleSize(1) == 1) {
|
|
||||||
return TupleType.BLACKANDWHITE_ALPHA;
|
|
||||||
}
|
|
||||||
|
|
||||||
// We can only write 8 or 16 bits/band
|
|
||||||
if (!(sampleModel.getSampleSize(0) == 8 || sampleModel.getSampleSize(0) == 16)) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
for (int i = 1; i < bands; i++) {
|
|
||||||
if (sampleModel.getSampleSize(0) != sampleModel.getSampleSize(i)) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (bands == 1) {
|
|
||||||
return TupleType.GRAYSCALE;
|
|
||||||
}
|
|
||||||
else if (bands == 2) {
|
|
||||||
return TupleType.GRAYSCALE_ALPHA;
|
|
||||||
}
|
|
||||||
else if (bands == 3) {
|
|
||||||
return TupleType.RGB;
|
|
||||||
}
|
|
||||||
else if (bands == 4) {
|
|
||||||
return TupleType.RGB_ALPHA;
|
|
||||||
}
|
|
||||||
// ...else fall through...
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
static TupleType forPAM(ImageTypeSpecifier type) {
|
|
||||||
// Support only 1 bit b/w, 8-16 bit gray and 8-16 bit/sample RGB
|
|
||||||
switch (type.getBufferedImageType()) {
|
|
||||||
// 1 bit b/w or b/w + a
|
|
||||||
case BufferedImage.TYPE_BYTE_BINARY:
|
|
||||||
switch (type.getNumBands()) {
|
|
||||||
case 1:
|
|
||||||
return type.getBitsPerBand(0) == 1 ? TupleType.BLACKANDWHITE : null;
|
|
||||||
case 2:
|
|
||||||
return type.getBitsPerBand(0) == 2 || type.getBitsPerBand(0) == 1 && type.getBitsPerBand(1) == 1 ? TupleType.BLACKANDWHITE_ALPHA : null;
|
|
||||||
default:
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
// Gray
|
|
||||||
case BufferedImage.TYPE_BYTE_GRAY:
|
|
||||||
case BufferedImage.TYPE_USHORT_GRAY:
|
|
||||||
return TupleType.GRAYSCALE;
|
|
||||||
// RGB
|
|
||||||
case BufferedImage.TYPE_3BYTE_BGR:
|
|
||||||
case BufferedImage.TYPE_INT_RGB:
|
|
||||||
case BufferedImage.TYPE_INT_BGR:
|
|
||||||
return TupleType.RGB;
|
|
||||||
// RGBA
|
|
||||||
case BufferedImage.TYPE_4BYTE_ABGR:
|
|
||||||
case BufferedImage.TYPE_4BYTE_ABGR_PRE:
|
|
||||||
case BufferedImage.TYPE_INT_ARGB:
|
|
||||||
case BufferedImage.TYPE_INT_ARGB_PRE:
|
|
||||||
return TupleType.RGB_ALPHA;
|
|
||||||
default:
|
|
||||||
// BYTE, USHORT or INT (packed)
|
|
||||||
switch (type.getSampleModel().getTransferType()) {
|
|
||||||
case DataBuffer.TYPE_BYTE:
|
|
||||||
case DataBuffer.TYPE_USHORT:
|
|
||||||
case DataBuffer.TYPE_INT:
|
|
||||||
// Gray or RGB
|
|
||||||
ColorModel colorModel = type.getColorModel();
|
|
||||||
|
|
||||||
if (!(colorModel instanceof IndexColorModel)) {
|
|
||||||
ColorSpace cs = colorModel.getColorSpace();
|
|
||||||
|
|
||||||
// We can only write 8 or 16 bits/band
|
|
||||||
int bands = type.getNumBands();
|
|
||||||
if (!(type.getBitsPerBand(0) == 8 || type.getBitsPerBand(0) == 16)) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
for (int i = 1; i < bands; i++) {
|
|
||||||
if (type.getBitsPerBand(0) != type.getBitsPerBand(i)) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cs.getType() == ColorSpace.TYPE_GRAY && bands == 1) {
|
|
||||||
return TupleType.GRAYSCALE;
|
|
||||||
}
|
|
||||||
else if (cs.getType() == ColorSpace.TYPE_GRAY && colorModel.hasAlpha() && bands == 2) {
|
|
||||||
return TupleType.GRAYSCALE_ALPHA;
|
|
||||||
}
|
|
||||||
else if (cs.getType() == ColorSpace.TYPE_RGB && bands == 3) {
|
|
||||||
return TupleType.RGB;
|
|
||||||
}
|
|
||||||
else if (cs.getType() == ColorSpace.TYPE_RGB && colorModel.hasAlpha() && bands == 4) {
|
|
||||||
return TupleType.RGB_ALPHA;
|
|
||||||
}
|
|
||||||
else if (cs.getType() == ColorSpace.TYPE_CMYK && bands == 4) {
|
|
||||||
return TupleType.CMYK;
|
|
||||||
}
|
|
||||||
else if (cs.getType() == ColorSpace.TYPE_CMYK && colorModel.hasAlpha() && bands == 5) {
|
|
||||||
return TupleType.CMYK_ALPHA;
|
|
||||||
}
|
|
||||||
// ...else fall through...
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
-89
@@ -30,23 +30,15 @@
|
|||||||
|
|
||||||
package com.twelvemonkeys.imageio.plugins.pnm;
|
package com.twelvemonkeys.imageio.plugins.pnm;
|
||||||
|
|
||||||
import com.twelvemonkeys.imageio.color.ColorSpaces;
|
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import javax.imageio.ImageTypeSpecifier;
|
|
||||||
import javax.imageio.ImageWriter;
|
import javax.imageio.ImageWriter;
|
||||||
import javax.imageio.spi.ImageReaderSpi;
|
import javax.imageio.spi.ImageReaderSpi;
|
||||||
import javax.imageio.spi.ImageWriterSpi;
|
import javax.imageio.spi.ImageWriterSpi;
|
||||||
import java.awt.*;
|
|
||||||
import java.awt.color.*;
|
|
||||||
import java.awt.image.*;
|
|
||||||
|
|
||||||
import static com.twelvemonkeys.imageio.spi.ReaderWriterProviderInfoTest.assertClassExists;
|
import static com.twelvemonkeys.imageio.spi.ReaderWriterProviderInfoTest.assertClassExists;
|
||||||
import static com.twelvemonkeys.imageio.spi.ReaderWriterProviderInfoTest.assertClassesExist;
|
import static com.twelvemonkeys.imageio.spi.ReaderWriterProviderInfoTest.assertClassesExist;
|
||||||
import static org.junit.Assert.assertFalse;
|
|
||||||
import static org.junit.Assert.assertNotNull;
|
import static org.junit.Assert.assertNotNull;
|
||||||
import static org.junit.Assert.assertTrue;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* PAMImageWriterSpiTest.
|
* PAMImageWriterSpiTest.
|
||||||
@@ -73,85 +65,4 @@ public class PAMImageWriterSpiTest {
|
|||||||
public void getOutputTypes() {
|
public void getOutputTypes() {
|
||||||
assertNotNull(spi.getOutputTypes());
|
assertNotNull(spi.getOutputTypes());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void canEncodeImageBinary() {
|
|
||||||
assertTrue(spi.canEncodeImage(new BufferedImage(1, 1, BufferedImage.TYPE_BYTE_BINARY)));
|
|
||||||
assertTrue(spi.canEncodeImage(ImageTypeSpecifier.createFromBufferedImageType(BufferedImage.TYPE_BYTE_BINARY)));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void canNotEncodeImageIndexed() {
|
|
||||||
assertFalse(spi.canEncodeImage(new BufferedImage(1, 1, BufferedImage.TYPE_BYTE_INDEXED)));
|
|
||||||
assertFalse(spi.canEncodeImage(ImageTypeSpecifier.createFromBufferedImageType(BufferedImage.TYPE_BYTE_INDEXED)));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void canEncodeImageGray() {
|
|
||||||
assertTrue(spi.canEncodeImage(new BufferedImage(1, 1, BufferedImage.TYPE_BYTE_GRAY)));
|
|
||||||
assertTrue(spi.canEncodeImage(ImageTypeSpecifier.createFromBufferedImageType(BufferedImage.TYPE_BYTE_GRAY)));
|
|
||||||
|
|
||||||
assertTrue(spi.canEncodeImage(new BufferedImage(1, 1, BufferedImage.TYPE_USHORT_GRAY)));
|
|
||||||
assertTrue(spi.canEncodeImage(ImageTypeSpecifier.createFromBufferedImageType(BufferedImage.TYPE_USHORT_GRAY)));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void canEncodeImageGrayAlpha() {
|
|
||||||
ComponentColorModel grayAlphaByte = new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_GRAY), true, false, Transparency.TRANSLUCENT, DataBuffer.TYPE_BYTE);
|
|
||||||
assertTrue(spi.canEncodeImage(new ImageTypeSpecifier(grayAlphaByte, grayAlphaByte.createCompatibleSampleModel(1, 1))));
|
|
||||||
|
|
||||||
ComponentColorModel grayAlphaUShort = new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_GRAY), true, false, Transparency.TRANSLUCENT, DataBuffer.TYPE_USHORT);
|
|
||||||
assertTrue(spi.canEncodeImage(new ImageTypeSpecifier(grayAlphaUShort, grayAlphaUShort.createCompatibleSampleModel(1, 1))));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void canEncodeImageRGB() {
|
|
||||||
assertTrue(spi.canEncodeImage(new BufferedImage(1, 1, BufferedImage.TYPE_3BYTE_BGR)));
|
|
||||||
assertTrue(spi.canEncodeImage(ImageTypeSpecifier.createFromBufferedImageType(BufferedImage.TYPE_3BYTE_BGR)));
|
|
||||||
|
|
||||||
assertTrue(spi.canEncodeImage(new BufferedImage(1, 1, BufferedImage.TYPE_INT_RGB)));
|
|
||||||
assertTrue(spi.canEncodeImage(ImageTypeSpecifier.createFromBufferedImageType(BufferedImage.TYPE_INT_RGB)));
|
|
||||||
|
|
||||||
assertTrue(spi.canEncodeImage(new BufferedImage(1, 1, BufferedImage.TYPE_INT_BGR)));
|
|
||||||
assertTrue(spi.canEncodeImage(ImageTypeSpecifier.createFromBufferedImageType(BufferedImage.TYPE_INT_BGR)));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void canEncodeImageARGB() {
|
|
||||||
assertTrue(spi.canEncodeImage(new BufferedImage(1, 1, BufferedImage.TYPE_4BYTE_ABGR)));
|
|
||||||
assertTrue(spi.canEncodeImage(ImageTypeSpecifier.createFromBufferedImageType(BufferedImage.TYPE_4BYTE_ABGR)));
|
|
||||||
|
|
||||||
assertTrue(spi.canEncodeImage(new BufferedImage(1, 1, BufferedImage.TYPE_4BYTE_ABGR_PRE)));
|
|
||||||
assertTrue(spi.canEncodeImage(ImageTypeSpecifier.createFromBufferedImageType(BufferedImage.TYPE_4BYTE_ABGR_PRE)));
|
|
||||||
|
|
||||||
assertTrue(spi.canEncodeImage(new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB)));
|
|
||||||
assertTrue(spi.canEncodeImage(ImageTypeSpecifier.createFromBufferedImageType(BufferedImage.TYPE_INT_ARGB)));
|
|
||||||
|
|
||||||
assertTrue(spi.canEncodeImage(new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB_PRE)));
|
|
||||||
assertTrue(spi.canEncodeImage(ImageTypeSpecifier.createFromBufferedImageType(BufferedImage.TYPE_INT_ARGB_PRE)));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void canEncodeImageCMYK() {
|
|
||||||
ComponentColorModel cmykByte = new ComponentColorModel(ColorSpaces.getColorSpace(ColorSpaces.CS_GENERIC_CMYK), false, false, Transparency.OPAQUE, DataBuffer.TYPE_BYTE);
|
|
||||||
assertTrue(spi.canEncodeImage(new ImageTypeSpecifier(cmykByte, cmykByte.createCompatibleSampleModel(1, 1))));
|
|
||||||
|
|
||||||
ComponentColorModel cmykUShort = new ComponentColorModel(ColorSpaces.getColorSpace(ColorSpaces.CS_GENERIC_CMYK), false, false, Transparency.OPAQUE, DataBuffer.TYPE_USHORT);
|
|
||||||
assertTrue(spi.canEncodeImage(new ImageTypeSpecifier(cmykUShort, cmykUShort.createCompatibleSampleModel(1, 1))));
|
|
||||||
|
|
||||||
ComponentColorModel cmykAlphaByte = new ComponentColorModel(ColorSpaces.getColorSpace(ColorSpaces.CS_GENERIC_CMYK), true, false, Transparency.TRANSLUCENT, DataBuffer.TYPE_BYTE);
|
|
||||||
assertTrue(spi.canEncodeImage(new ImageTypeSpecifier(cmykAlphaByte, cmykAlphaByte.createCompatibleSampleModel(1, 1))));
|
|
||||||
|
|
||||||
ComponentColorModel cmykAlphaUShort = new ComponentColorModel(ColorSpaces.getColorSpace(ColorSpaces.CS_GENERIC_CMYK), true, false, Transparency.TRANSLUCENT, DataBuffer.TYPE_USHORT);
|
|
||||||
assertTrue(spi.canEncodeImage(new ImageTypeSpecifier(cmykAlphaUShort, cmykAlphaUShort.createCompatibleSampleModel(1, 1))));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void canNotEncodeImageNonGrayOrRGB() {
|
|
||||||
ComponentColorModel xyzByte = new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_CIEXYZ), false, false, Transparency.OPAQUE, DataBuffer.TYPE_BYTE);
|
|
||||||
assertFalse(spi.canEncodeImage(new ImageTypeSpecifier(xyzByte, xyzByte.createCompatibleSampleModel(1, 1))));
|
|
||||||
|
|
||||||
ComponentColorModel xyzUshort = new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_CIEXYZ), false, false, Transparency.OPAQUE, DataBuffer.TYPE_USHORT);
|
|
||||||
assertFalse(spi.canEncodeImage(new ImageTypeSpecifier(xyzUshort, xyzUshort.createCompatibleSampleModel(1, 1))));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
-37
@@ -1,37 +0,0 @@
|
|||||||
package com.twelvemonkeys.imageio.plugins.pnm;
|
|
||||||
|
|
||||||
import com.twelvemonkeys.imageio.color.ColorSpaces;
|
|
||||||
import com.twelvemonkeys.imageio.util.ImageWriterAbstractTest;
|
|
||||||
|
|
||||||
import javax.imageio.spi.ImageWriterSpi;
|
|
||||||
import java.awt.*;
|
|
||||||
import java.awt.color.*;
|
|
||||||
import java.awt.image.*;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public class PAMImageWriterTest extends ImageWriterAbstractTest<PNMImageWriter> {
|
|
||||||
// NOTE: It's the same writer, however, the different SPI configures PAM mode, and enables extra formats
|
|
||||||
@Override
|
|
||||||
protected ImageWriterSpi createProvider() {
|
|
||||||
return new PAMImageWriterSpi();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected List<? extends RenderedImage> getTestData() {
|
|
||||||
return Arrays.asList(
|
|
||||||
new BufferedImage(100, 100, BufferedImage.TYPE_BYTE_BINARY),
|
|
||||||
new BufferedImage(100, 100, BufferedImage.TYPE_3BYTE_BGR),
|
|
||||||
new BufferedImage(100, 100, BufferedImage.TYPE_BYTE_GRAY),
|
|
||||||
new BufferedImage(100, 100, BufferedImage.TYPE_USHORT_GRAY),
|
|
||||||
new BufferedImage(100, 100, BufferedImage.TYPE_4BYTE_ABGR),
|
|
||||||
new BufferedImage(100, 100, BufferedImage.TYPE_INT_BGR),
|
|
||||||
new BufferedImage(10, 10, BufferedImage.TYPE_INT_BGR),
|
|
||||||
new BufferedImage(10, 10, BufferedImage.TYPE_INT_ARGB),
|
|
||||||
new BufferedImage(10, 10, BufferedImage.TYPE_INT_ARGB_PRE),
|
|
||||||
new BufferedImage(new ComponentColorModel(ColorSpaces.getColorSpace(ColorSpace.CS_GRAY), true, false, Transparency.TRANSLUCENT, DataBuffer.TYPE_USHORT), Raster.createInterleavedRaster(DataBuffer.TYPE_USHORT, 10, 10, 2, null), false, null),
|
|
||||||
new BufferedImage(new ComponentColorModel(ColorSpaces.getColorSpace(ColorSpaces.CS_GENERIC_CMYK), false, false, Transparency.OPAQUE, DataBuffer.TYPE_BYTE), Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE, 10, 10, 4, null), false, null),
|
|
||||||
new BufferedImage(new ComponentColorModel(ColorSpaces.getColorSpace(ColorSpaces.CS_GENERIC_CMYK), true, false, Transparency.TRANSLUCENT, DataBuffer.TYPE_USHORT), Raster.createInterleavedRaster(DataBuffer.TYPE_USHORT, 10, 10, 5, null), false, null)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-72
@@ -32,19 +32,13 @@ package com.twelvemonkeys.imageio.plugins.pnm;
|
|||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import javax.imageio.ImageTypeSpecifier;
|
|
||||||
import javax.imageio.ImageWriter;
|
import javax.imageio.ImageWriter;
|
||||||
import javax.imageio.spi.ImageReaderSpi;
|
import javax.imageio.spi.ImageReaderSpi;
|
||||||
import javax.imageio.spi.ImageWriterSpi;
|
import javax.imageio.spi.ImageWriterSpi;
|
||||||
import java.awt.*;
|
|
||||||
import java.awt.color.*;
|
|
||||||
import java.awt.image.*;
|
|
||||||
|
|
||||||
import static com.twelvemonkeys.imageio.spi.ReaderWriterProviderInfoTest.assertClassExists;
|
import static com.twelvemonkeys.imageio.spi.ReaderWriterProviderInfoTest.assertClassExists;
|
||||||
import static com.twelvemonkeys.imageio.spi.ReaderWriterProviderInfoTest.assertClassesExist;
|
import static com.twelvemonkeys.imageio.spi.ReaderWriterProviderInfoTest.assertClassesExist;
|
||||||
import static org.junit.Assert.assertFalse;
|
|
||||||
import static org.junit.Assert.assertNotNull;
|
import static org.junit.Assert.assertNotNull;
|
||||||
import static org.junit.Assert.assertTrue;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* PNMImageWriterSpiTest.
|
* PNMImageWriterSpiTest.
|
||||||
@@ -71,70 +65,4 @@ public class PNMImageWriterSpiTest {
|
|||||||
public void getOutputTypes() {
|
public void getOutputTypes() {
|
||||||
assertNotNull(spi.getOutputTypes());
|
assertNotNull(spi.getOutputTypes());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void canEncodeImageBinary() {
|
|
||||||
assertTrue(spi.canEncodeImage(new BufferedImage(1, 1, BufferedImage.TYPE_BYTE_BINARY)));
|
|
||||||
assertTrue(spi.canEncodeImage(ImageTypeSpecifier.createFromBufferedImageType(BufferedImage.TYPE_BYTE_BINARY)));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void canNotEncodeImageIndexed() {
|
|
||||||
assertFalse(spi.canEncodeImage(new BufferedImage(1, 1, BufferedImage.TYPE_BYTE_INDEXED)));
|
|
||||||
assertFalse(spi.canEncodeImage(ImageTypeSpecifier.createFromBufferedImageType(BufferedImage.TYPE_BYTE_INDEXED)));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void canEncodeImageGray() {
|
|
||||||
assertTrue(spi.canEncodeImage(new BufferedImage(1, 1, BufferedImage.TYPE_BYTE_GRAY)));
|
|
||||||
assertTrue(spi.canEncodeImage(ImageTypeSpecifier.createFromBufferedImageType(BufferedImage.TYPE_BYTE_GRAY)));
|
|
||||||
|
|
||||||
assertTrue(spi.canEncodeImage(new BufferedImage(1, 1, BufferedImage.TYPE_USHORT_GRAY)));
|
|
||||||
assertTrue(spi.canEncodeImage(ImageTypeSpecifier.createFromBufferedImageType(BufferedImage.TYPE_USHORT_GRAY)));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void canNotEncodeImageGrayAlpha() {
|
|
||||||
ComponentColorModel grayAlphaByte = new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_GRAY), true, false, Transparency.TRANSLUCENT, DataBuffer.TYPE_BYTE);
|
|
||||||
assertFalse(spi.canEncodeImage(new ImageTypeSpecifier(grayAlphaByte, grayAlphaByte.createCompatibleSampleModel(1, 1))));
|
|
||||||
|
|
||||||
ComponentColorModel grayAlphaUShort = new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_GRAY), true, false, Transparency.TRANSLUCENT, DataBuffer.TYPE_USHORT);
|
|
||||||
assertFalse(spi.canEncodeImage(new ImageTypeSpecifier(grayAlphaUShort, grayAlphaUShort.createCompatibleSampleModel(1, 1))));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void canEncodeImageRGB() {
|
|
||||||
assertTrue(spi.canEncodeImage(new BufferedImage(1, 1, BufferedImage.TYPE_3BYTE_BGR)));
|
|
||||||
assertTrue(spi.canEncodeImage(ImageTypeSpecifier.createFromBufferedImageType(BufferedImage.TYPE_3BYTE_BGR)));
|
|
||||||
|
|
||||||
assertTrue(spi.canEncodeImage(new BufferedImage(1, 1, BufferedImage.TYPE_INT_RGB)));
|
|
||||||
assertTrue(spi.canEncodeImage(ImageTypeSpecifier.createFromBufferedImageType(BufferedImage.TYPE_INT_RGB)));
|
|
||||||
|
|
||||||
assertTrue(spi.canEncodeImage(new BufferedImage(1, 1, BufferedImage.TYPE_INT_BGR)));
|
|
||||||
assertTrue(spi.canEncodeImage(ImageTypeSpecifier.createFromBufferedImageType(BufferedImage.TYPE_INT_BGR)));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void canNotEncodeImageARGB() {
|
|
||||||
assertFalse(spi.canEncodeImage(new BufferedImage(1, 1, BufferedImage.TYPE_4BYTE_ABGR)));
|
|
||||||
assertFalse(spi.canEncodeImage(ImageTypeSpecifier.createFromBufferedImageType(BufferedImage.TYPE_4BYTE_ABGR)));
|
|
||||||
|
|
||||||
assertFalse(spi.canEncodeImage(new BufferedImage(1, 1, BufferedImage.TYPE_4BYTE_ABGR_PRE)));
|
|
||||||
assertFalse(spi.canEncodeImage(ImageTypeSpecifier.createFromBufferedImageType(BufferedImage.TYPE_4BYTE_ABGR_PRE)));
|
|
||||||
|
|
||||||
assertFalse(spi.canEncodeImage(new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB)));
|
|
||||||
assertFalse(spi.canEncodeImage(ImageTypeSpecifier.createFromBufferedImageType(BufferedImage.TYPE_INT_ARGB)));
|
|
||||||
|
|
||||||
assertFalse(spi.canEncodeImage(new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB_PRE)));
|
|
||||||
assertFalse(spi.canEncodeImage(ImageTypeSpecifier.createFromBufferedImageType(BufferedImage.TYPE_INT_ARGB_PRE)));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void canNotEncodeImageNonGrayOrRGB() {
|
|
||||||
ComponentColorModel xyzByte = new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_CIEXYZ), false, false, Transparency.OPAQUE, DataBuffer.TYPE_BYTE);
|
|
||||||
assertFalse(spi.canEncodeImage(new ImageTypeSpecifier(xyzByte, xyzByte.createCompatibleSampleModel(1, 1))));
|
|
||||||
|
|
||||||
ComponentColorModel xyzUshort = new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_CIEXYZ), false, false, Transparency.OPAQUE, DataBuffer.TYPE_USHORT);
|
|
||||||
assertFalse(spi.canEncodeImage(new ImageTypeSpecifier(xyzUshort, xyzUshort.createCompatibleSampleModel(1, 1))));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
+3
-4
@@ -3,7 +3,8 @@ package com.twelvemonkeys.imageio.plugins.pnm;
|
|||||||
import com.twelvemonkeys.imageio.util.ImageWriterAbstractTest;
|
import com.twelvemonkeys.imageio.util.ImageWriterAbstractTest;
|
||||||
|
|
||||||
import javax.imageio.spi.ImageWriterSpi;
|
import javax.imageio.spi.ImageWriterSpi;
|
||||||
import java.awt.image.*;
|
import java.awt.image.BufferedImage;
|
||||||
|
import java.awt.image.RenderedImage;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@@ -16,12 +17,10 @@ public class PNMImageWriterTest extends ImageWriterAbstractTest<PNMImageWriter>
|
|||||||
@Override
|
@Override
|
||||||
protected List<? extends RenderedImage> getTestData() {
|
protected List<? extends RenderedImage> getTestData() {
|
||||||
return Arrays.asList(
|
return Arrays.asList(
|
||||||
new BufferedImage(100, 100, BufferedImage.TYPE_BYTE_BINARY),
|
|
||||||
new BufferedImage(100, 100, BufferedImage.TYPE_3BYTE_BGR),
|
new BufferedImage(100, 100, BufferedImage.TYPE_3BYTE_BGR),
|
||||||
new BufferedImage(100, 100, BufferedImage.TYPE_BYTE_GRAY),
|
new BufferedImage(100, 100, BufferedImage.TYPE_BYTE_GRAY),
|
||||||
new BufferedImage(100, 100, BufferedImage.TYPE_USHORT_GRAY),
|
new BufferedImage(100, 100, BufferedImage.TYPE_USHORT_GRAY),
|
||||||
new BufferedImage(100, 100, BufferedImage.TYPE_INT_BGR),
|
new BufferedImage(100, 100, BufferedImage.TYPE_4BYTE_ABGR)
|
||||||
new BufferedImage(10, 10, BufferedImage.TYPE_INT_BGR)
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -4,7 +4,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>com.twelvemonkeys.imageio</groupId>
|
<groupId>com.twelvemonkeys.imageio</groupId>
|
||||||
<artifactId>imageio</artifactId>
|
<artifactId>imageio</artifactId>
|
||||||
<version>3.10.2-SNAPSHOT</version>
|
<version>3.9.2</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';
|
|
||||||
}
|
}
|
||||||
|
|||||||
+14
-20
@@ -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.. ;-)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -950,7 +944,7 @@ public final class PSDImageReader extends ImageReaderBase {
|
|||||||
if (metadata.layerInfo == null) {
|
if (metadata.layerInfo == null) {
|
||||||
while (imageInput.getStreamPosition() + 12 < metadata.layerAndMaskInfoStart + layerAndMaskInfoLength) {
|
while (imageInput.getStreamPosition() + 12 < metadata.layerAndMaskInfoStart + layerAndMaskInfoLength) {
|
||||||
int resSig = imageInput.readInt();
|
int resSig = imageInput.readInt();
|
||||||
if (resSig != PSD.RESOURCE_TYPE && resSig != PSD.RESOURCE_TYPE_LONG) {
|
if (resSig != PSD.RESOURCE_TYPE) {
|
||||||
processWarningOccurred(String.format("Bad resource alignment, expected: '8BIM' was '%s'", PSDUtil.intToStr(resSig)));
|
processWarningOccurred(String.format("Bad resource alignment, expected: '8BIM' was '%s'", PSDUtil.intToStr(resSig)));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -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) {
|
||||||
|
|||||||
+5
-10
@@ -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;
|
||||||
@@ -104,12 +103,10 @@ final class PSDUtil {
|
|||||||
final int[] byteCounts, long compressedLength) throws IOException {
|
final int[] byteCounts, long compressedLength) throws IOException {
|
||||||
switch (compression) {
|
switch (compression) {
|
||||||
case PSD.COMPRESSION_NONE:
|
case PSD.COMPRESSION_NONE:
|
||||||
long streamLength = stream.length();
|
return new SubImageInputStream(stream, stream.length());
|
||||||
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 +123,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 +137,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);
|
||||||
|
|||||||
-25
@@ -31,12 +31,10 @@
|
|||||||
package com.twelvemonkeys.imageio.plugins.psd;
|
package com.twelvemonkeys.imageio.plugins.psd;
|
||||||
|
|
||||||
import com.twelvemonkeys.imageio.stream.ByteArrayImageInputStream;
|
import com.twelvemonkeys.imageio.stream.ByteArrayImageInputStream;
|
||||||
import com.twelvemonkeys.imageio.stream.DirectImageInputStream;
|
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import javax.imageio.stream.ImageInputStream;
|
import javax.imageio.stream.ImageInputStream;
|
||||||
import java.io.ByteArrayInputStream;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
import static com.twelvemonkeys.imageio.plugins.psd.PSDUtil.createDecompressorStream;
|
import static com.twelvemonkeys.imageio.plugins.psd.PSDUtil.createDecompressorStream;
|
||||||
@@ -67,29 +65,6 @@ public class PSDUtilDecompressorStreamTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testUncompressedUnknownLength() throws IOException {
|
|
||||||
// Data represents 3 x 3 raster with 8 bit samples, all 0x7f's
|
|
||||||
byte[] data = new byte[] {
|
|
||||||
0x7f, 0x7f, 0x7f,
|
|
||||||
0x7f, 0x7f, 0x7f,
|
|
||||||
0x7f, 0x7f, 0x7f
|
|
||||||
};
|
|
||||||
try (ImageInputStream input = createDecompressorStream(new DirectImageInputStream(new ByteArrayInputStream(data)), PSD.COMPRESSION_NONE, 3, 8, null, 9)) {
|
|
||||||
byte[] row = new byte[3];
|
|
||||||
|
|
||||||
for (int y = 0; y < 3; y++) {
|
|
||||||
input.readFully(row);
|
|
||||||
|
|
||||||
for (byte b : row) {
|
|
||||||
assertEquals((byte) 0x7f, b);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
assertEquals(-1, input.read());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testPackBits() throws IOException {
|
public void testPackBits() throws IOException {
|
||||||
// Data represents 3 x 3 raster with 8 bit samples, all 42's
|
// Data represents 3 x 3 raster with 8 bit samples, all 42's
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user