Compare commits

..

7 Commits

Author SHA1 Message Date
Harald Kuhr 9875de0383 [maven-release-plugin] prepare release twelvemonkeys-3.9.1 2022-10-19 20:56:08 +02:00
Harald Kuhr 6ed858a4ca #704 Tiny performance improvement + code clean-up
(cherry picked from commit 61424f33b6)
2022-10-19 20:46:45 +02:00
Harald Kuhr 38192ae835 Code clean-up.
(cherry picked from commit c7b9b1fadd)
2022-10-19 20:46:45 +02:00
Harald Kuhr b5e8853e6b Set versions for 3.9 bugfix branch. 2022-10-18 20:49:43 +02:00
Harald Kuhr a98224e652 #705 No longer closes streams we didn't open
(cherry picked from commit ab08ec1e0d)
2022-10-18 20:34:27 +02:00
Harald Kuhr 73a58266be ...and removed System.out.. Ouch...
(cherry picked from commit cbe78dc67f)
2022-10-18 20:34:26 +02:00
Harald Kuhr edd523534c Fixed typo...
(cherry picked from commit c9e11f171f)
2022-10-18 20:34:26 +02:00
145 changed files with 1215 additions and 3183 deletions
-13
View File
@@ -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"
+17 -56
View File
@@ -1,14 +1,6 @@
name: CI
on:
push:
branches:
- '**'
- '!dependabot/**'
pull_request:
branches: [ 'master' ]
permissions: read-all
on: [ push, pull_request ]
jobs:
test:
@@ -17,68 +9,37 @@ jobs:
fail-fast: false
matrix:
os: [ ubuntu-latest, windows-latest, macos-latest ]
java: [ 11, 17, 21 ]
java: [ 8, 11, 17, 18 ]
runs-on: ${{ matrix.os }}
permissions:
checks: write
steps:
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- uses: actions/setup-java@2dfa2011c5b2a0f1489bf9e433881c92c1631f88 # v4.3.0
- uses: actions/checkout@v3
- uses: actions/setup-java@v3
with:
distribution: 'temurin'
java-version: ${{ matrix.java }}
java-package: jdk
cache: 'maven'
- name: Run Tests
run: mvn --batch-mode --no-transfer-progress test
run: mvn test
- name: Publish Test Report
uses: mikepenz/action-junit-report@db71d41eb79864e25ab0337e395c352e84523afe # v4.3.1
uses: mikepenz/action-junit-report@v3
if: ${{ !cancelled() }}
with:
report_paths: "**/target/surefire-reports/TEST*.xml"
check_name: Unit Test Results for OpenJDK ${{ matrix.java }} on ${{ matrix.os }}
test-jdk8:
name: Test OpenJDK ${{ matrix.java }} on ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ ubuntu-latest, windows-latest, macos-13 ]
java: [ 8 ]
runs-on: ${{ matrix.os }}
permissions:
checks: write
steps:
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- uses: actions/setup-java@2dfa2011c5b2a0f1489bf9e433881c92c1631f88 # v4.3.0
with:
distribution: 'temurin'
java-version: ${{ matrix.java }}
java-package: jdk
cache: 'maven'
- name: Run Tests
run: mvn --batch-mode --no-transfer-progress test
- name: Publish Test Report
uses: mikepenz/action-junit-report@db71d41eb79864e25ab0337e395c352e84523afe # v4.3.1
if: ${{ !cancelled() }}
with:
report_paths: "**/target/surefire-reports/TEST*.xml"
check_name: Unit Test Results for OpenJDK ${{ matrix.java }} on ${{ matrix.os }}
test-oracle:
test_oracle:
name: Test Oracle JDK 8 with KCMS=${{ matrix.kcms }}
runs-on: ubuntu-latest
permissions:
checks: write
strategy:
matrix:
kcms: [ true, false ]
steps:
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- uses: actions/checkout@v3
- run: |
download_url="https://javadl.oracle.com/webapps/download/AutoDL?BundleId=245038_d3c52aa6bfa54d3ca74e617f18309292"
wget -O $RUNNER_TEMP/java_package.tar.gz $download_url
- uses: actions/setup-java@2dfa2011c5b2a0f1489bf9e433881c92c1631f88 # v4.3.0
- uses: actions/setup-java@v3
with:
distribution: 'jdkfile'
jdkFile: ${{ runner.temp }}/java_package.tar.gz
@@ -91,9 +52,9 @@ jobs:
- name: Display Java version
run: java -version
- name: Run Tests
run: mvn --batch-mode --no-transfer-progress test
run: mvn test
- name: Publish Test Report
uses: mikepenz/action-junit-report@db71d41eb79864e25ab0337e395c352e84523afe # v4.3.1
uses: mikepenz/action-junit-report@v3
if: ${{ !cancelled() }}
with:
report_paths: "**/target/surefire-reports/TEST*.xml"
@@ -101,13 +62,13 @@ jobs:
release:
name: Deploy
needs: [ test, test-jdk8, test-oracle ]
needs: [ test, test_oracle ]
if: github.ref == 'refs/heads/master' # only perform on latest master
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- uses: actions/checkout@v3
- name: Set up Maven Central
uses: actions/setup-java@2dfa2011c5b2a0f1489bf9e433881c92c1631f88 # v4.3.0
uses: actions/setup-java@v3
with: # running setup-java again overwrites the settings.xml
distribution: 'temurin'
java-version: '8'
@@ -119,11 +80,11 @@ jobs:
gpg-passphrase: MAVEN_CENTRAL_GPG_PASSPHRASE # env variable for GPG private key passphrase (3)
- name: Get Project Version
run: |
echo "PROJECT_VERSION=$(mvn --batch-mode help:evaluate -Dexpression=project.version -q -DforceStdout)" >> $GITHUB_ENV
echo "PROJECT_VERSION=$(mvn help:evaluate -Dexpression=project.version -q -DforceStdout)" >> $GITHUB_ENV
- name: Publish to Maven Central
if: ${{ endsWith(env.PROJECT_VERSION, '-SNAPSHOT') }}
run: mvn --batch-mode --no-transfer-progress deploy -P release -DskipTests
run: mvn deploy -P release -DskipTests
env:
MAVEN_CENTRAL_USERNAME: ${{ secrets.SONATYPE_USERNAME }} # must be the same env variable name as (1)
MAVEN_CENTRAL_PASSWORD: ${{ secrets.SONATYPE_PASSWORD }} # must be the same env variable name as (2)
MAVEN_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)
-69
View File
@@ -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@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@8214744c546c1e5c8f03dde8fab3a7353211988d # v3.26.7
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@8214744c546c1e5c8f03dde8fab3a7353211988d # v3.26.7
# ℹ️ 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@8214744c546c1e5c8f03dde8fab3a7353211988d # v3.26.7
with:
category: "/language:${{matrix.language}}"
-62
View File
@@ -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@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
with:
persist-credentials: false
- name: "Run analysis"
uses: ossf/scorecard-action@62b2cac7ed8198b15735ed49ab1e5cf35480ba46 # v2.4.0
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@50769540e7f4bd5e21e526ee35c689e35e0d6874 # v4.4.0
with:
name: SARIF file
path: results.sarif
retention-days: 5
# Upload the results to GitHub's code scanning dashboard.
- name: "Upload to code-scanning"
uses: github/codeql-action/upload-sarif@8214744c546c1e5c8f03dde8fab3a7353211988d # v3.26.7
with:
sarif_file: results.sarif
-1
View File
@@ -15,4 +15,3 @@ private
profiles.xml
Thumbs.db
.DS_Store
/.metadata/
+75 -75
View File
@@ -1,15 +1,9 @@
[![CI](https://github.com/haraldk/TwelveMonkeys/actions/workflows/ci.yml/badge.svg)](https://github.com/haraldk/TwelveMonkeys/actions/workflows/ci.yml)
[![CodeQL](https://github.com/haraldk/TwelveMonkeys/actions/workflows/codeql.yml/badge.svg)](https://github.com/haraldk/TwelveMonkeys/actions/workflows/codeql.yml)
[![OpenSSF Scorecard](https://api.securityscorecards.dev/projects/github.com/haraldk/TwelveMonkeys/badge)](https://securityscorecards.dev/viewer/?uri=github.com/haraldk/TwelveMonkeys)
[![OpenSSF Best Practices](https://www.bestpractices.dev/projects/7900/badge)](https://www.bestpractices.dev/projects/7900)
[![Maven Central](https://img.shields.io/maven-central/v/com.twelvemonkeys.imageio/imageio?color=slateblue)](https://search.maven.org/search?q=g:com.twelvemonkeys.imageio)
[![Maven Snapshot](https://img.shields.io/nexus/s/com.twelvemonkeys.imageio/imageio?label=development&server=https%3A%2F%2Foss.sonatype.org&color=slateblue)](https://oss.sonatype.org/content/repositories/snapshots/com/twelvemonkeys/)
[![StackOverflow](https://img.shields.io/badge/stack_overflow-twelvemonkeys-orange.svg)](https://stackoverflow.com/questions/tagged/twelvemonkeys)
[![Donate](https://img.shields.io/badge/donate-PayPal-blue.svg)](https://paypal.me/haraldk76/100)
![Logo](logo.png)
## About
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>
<groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio-jpeg</artifactId>
<version>3.10.1</version>
<version>3.8.1</version>
</dependency>
<dependency>
<groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio-tiff</artifactId>
<version>3.10.1</version>
<version>3.8.1</version>
</dependency>
<!--
@@ -293,7 +287,7 @@ To depend on the JPEG and TIFF plugin using Maven, add the following to your POM
<dependency>
<groupId>com.twelvemonkeys.servlet</groupId>
<artifactId>servlet</artifactId>
<version>3.10.1</version>
<version>3.8.1</version>
</dependency>
<!--
@@ -302,7 +296,7 @@ To depend on the JPEG and TIFF plugin using Maven, add the following to your POM
<dependency>
<groupId>com.twelvemonkeys.servlet</groupId>
<artifactId>servlet</artifactId>
<version>3.10.1</version>
<version>3.8.1</version>
<classifier>jakarta</classifier>
</dependency>
</dependencies>
@@ -312,18 +306,18 @@ To depend on the JPEG and TIFF plugin using Maven, add the following to your POM
To depend on the JPEG and TIFF plugin in your IDE or program, add all of the following JARs to your class path:
twelvemonkeys-common-lang-3.10.1.jar
twelvemonkeys-common-io-3.10.1.jar
twelvemonkeys-common-image-3.10.1.jar
twelvemonkeys-imageio-core-3.10.1.jar
twelvemonkeys-imageio-metadata-3.10.1.jar
twelvemonkeys-imageio-jpeg-3.10.1.jar
twelvemonkeys-imageio-tiff-3.10.1.jar
twelvemonkeys-common-lang-3.8.1.jar
twelvemonkeys-common-io-3.8.1.jar
twelvemonkeys-common-image-3.8.1.jar
twelvemonkeys-imageio-core-3.8.1.jar
twelvemonkeys-imageio-metadata-3.8.1.jar
twelvemonkeys-imageio-jpeg-3.8.1.jar
twelvemonkeys-imageio-tiff-3.8.1.jar
#### Deploying the plugins in a web app
Because the `ImageIO` plugin registry (the `IIORegistry`) is "VM global", it does not work well with
servlet contexts as-is. This is especially evident if you load plugins from the `WEB-INF/lib` or `classes` folder.
Because the `ImageIO` plugin registry (the `IIORegistry`) is "VM global", it doesn't by default work well with
servlet contexts. This is especially evident if you load plugins from the `WEB-INF/lib` or `classes` folder.
Unless you add `ImageIO.scanForPlugins()` somewhere in your code, the plugins might never be available at all.
In addition, servlet contexts dynamically loads and unloads classes (using a new class loader per context).
@@ -359,16 +353,6 @@ or other ImageIO plugins as well.
Another safe option, is to place the JAR files in the application server's shared or common lib folder.
##### Jakarta Servlet Support
For those transitioning from the old `javax.servlet` to the new `jakarta.servlet` package, there is a separate
dependency available. It contains exactly the same servlet classes as mentioned above, but built against the new Jakarta EE
packages. The dependency has the same group name and identifier as before, but a `jakarta` *classifier* appended, to
distinguish it from the non-Jakarta package.
See the [Maven dependency example](#maven-dependency-example) for how to enable it with Maven.
Gradle or other build tools will have similar options.
#### Including the plugins in a "fat" JAR
The recommended way to use the plugins, is just to include the JARs as-is in your project, through a Maven dependency or similar.
@@ -394,50 +378,81 @@ Other "fat" JAR bundlers will probably have similar mechanisms to merge entries
### Links to prebuilt binaries
##### Latest version (3.10.1)
##### Latest version (3.8.1)
The latest version that will run on Java 7 is 3.9.4. Later versions will require Java 8 or later.
Requires Java 7 or later.
Common dependencies
* [common-lang-3.10.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/common/common-lang/3.10.1/common-lang-3.10.1.jar)
* [common-io-3.10.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/common/common-io/3.10.1/common-io-3.10.1.jar)
* [common-image-3.10.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/common/common-image/3.10.1/common-image-3.10.1.jar)
* [common-lang-3.8.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/common/common-lang/3.8.1/common-lang-3.8.1.jar)
* [common-io-3.8.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/common/common-io/3.8.1/common-io-3.8.1.jar)
* [common-image-3.8.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/common/common-image/3.8.1/common-image-3.8.1.jar)
ImageIO dependencies
* [imageio-core-3.10.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-core/3.10.1/imageio-core-3.10.1.jar)
* [imageio-metadata-3.10.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-metadata/3.10.1/imageio-metadata-3.10.1.jar)
* [imageio-core-3.8.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-core/3.8.1/imageio-core-3.8.1.jar)
* [imageio-metadata-3.8.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-metadata/3.8.1/imageio-metadata-3.8.1.jar)
ImageIO plugins
* [imageio-bmp-3.10.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-bmp/3.10.1/imageio-bmp-3.10.1.jar)
* [imageio-hdr-3.10.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-hdr/3.10.1/imageio-hdr-3.10.1.jar)
* [imageio-icns-3.10.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-icns/3.10.1/imageio-icns-3.10.1.jar)
* [imageio-iff-3.10.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-iff/3.10.1/imageio-iff-3.10.1.jar)
* [imageio-jpeg-3.10.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-jpeg/3.10.1/imageio-jpeg-3.10.1.jar)
* [imageio-pcx-3.10.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-pcx/3.10.1/imageio-pcx-3.10.1.jar)
* [imageio-pict-3.10.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-pict/3.10.1/imageio-pict-3.10.1.jar)
* [imageio-pnm-3.10.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-pnm/3.10.1/imageio-pnm-3.10.1.jar)
* [imageio-psd-3.10.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-psd/3.10.1/imageio-psd-3.10.1.jar)
* [imageio-sgi-3.10.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-sgi/3.10.1/imageio-sgi-3.10.1.jar)
* [imageio-tga-3.10.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-tga/3.10.1/imageio-tga-3.10.1.jar)
* [imageio-thumbsdb-3.10.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-thumbsdb/3.10.1/imageio-thumbsdb-3.10.1.jar)
* [imageio-tiff-3.10.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-tiff/3.10.1/imageio-tiff-3.10.1.jar)
* [imageio-webp-3.10.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-webp/3.10.1/imageio-webp-3.10.1.jar)
* [imageio-xwd-3.10.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-xwd/3.10.1/imageio-xwd-3.10.1.jar)
* [imageio-bmp-3.8.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-bmp/3.8.1/imageio-bmp-3.8.1.jar)
* [imageio-hdr-3.8.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-hdr/3.8.1/imageio-hdr-3.8.1.jar)
* [imageio-icns-3.8.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-icns/3.8.1/imageio-icns-3.8.1.jar)
* [imageio-iff-3.8.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-iff/3.8.1/imageio-iff-3.8.1.jar)
* [imageio-jpeg-3.8.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-jpeg/3.8.1/imageio-jpeg-3.8.1.jar)
* [imageio-pcx-3.8.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-pcx/3.8.1/imageio-pcx-3.8.1.jar)
* [imageio-pict-3.8.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-pict/3.8.1/imageio-pict-3.8.1.jar)
* [imageio-pnm-3.8.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-pnm/3.8.1/imageio-pnm-3.8.1.jar)
* [imageio-psd-3.8.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-psd/3.8.1/imageio-psd-3.8.1.jar)
* [imageio-sgi-3.8.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-sgi/3.8.1/imageio-sgi-3.8.1.jar)
* [imageio-tga-3.8.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-tga/3.8.1/imageio-tga-3.8.1.jar)
* [imageio-thumbsdb-3.8.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-thumbsdb/3.8.1/imageio-thumbsdb-3.8.1.jar)
* [imageio-tiff-3.8.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-tiff/3.8.1/imageio-tiff-3.8.1.jar)
* [imageio-webp-3.8.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-webp/3.8.1/imageio-webp-3.8.1.jar)
* [imageio-xwd-3.8.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-xwd/3.8.1/imageio-xwd-3.8.1.jar)
ImageIO plugins requiring 3rd party libs
* [imageio-batik-3.10.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-batik/3.10.1/imageio-batik-3.10.1.jar)
* [imageio-batik-3.8.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-batik/3.8.1/imageio-batik-3.8.1.jar)
Photoshop Path support for ImageIO
* [imageio-clippath-3.10.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-clippath/3.10.1/imageio-clippath-3.10.1.jar)
* [imageio-clippath-3.8.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-clippath/3.8.1/imageio-clippath-3.8.1.jar)
Servlet support
* [servlet-3.10.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/servlet/servlet/3.10.1/servlet-3.10.1.jar)
* [servlet-3.8.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/servlet/servlet/3.8.1/servlet-3.8.1.jar)
##### Old version (3.0.x)
Use this version for projects that requires Java 6 or need the JMagick support. *Does not support Java 8 or later*.
Common dependencies
* [common-lang-3.0.2.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/common/common-lang/3.0.2/common-lang-3.0.2.jar)
* [common-io-3.0.2.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/common/common-io/3.0.2/common-io-3.0.2.jar)
* [common-image-3.0.2.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/common/common-image/3.0.2/common-image-3.0.2.jar)
ImageIO dependencies
* [imageio-core-3.0.2.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-core/3.0.2/imageio-core-3.0.2.jar)
* [imageio-metadata-3.0.2.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-metadata/3.0.2/imageio-metadata-3.0.2.jar)
ImageIO plugins
* [imageio-jpeg-3.0.2.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-jpeg/3.0.2/imageio-jpeg-3.0.2.jar)
* [imageio-tiff-3.0.2.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-tiff/3.0.2/imageio-tiff-3.0.2.jar)
* [imageio-psd-3.0.2.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-psd/3.0.2/imageio-psd-3.0.2.jar)
* [imageio-pict-3.0.2.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-pict/3.0.2/imageio-pict-3.0.2.jar)
* [imageio-iff-3.0.2.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-iff/3.0.2/imageio-iff-3.0.2.jar)
* [imageio-icns-3.0.2.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-icns/3.0.2/imageio-icns-3.0.2.jar)
* [imageio-ico-3.0.2.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-ico/3.0.2/imageio-ico-3.0.2.jar)
* [imageio-thumbsdb-3.0.2.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-thumbsdb/3.0.2/imageio-thumbsdb-3.0.2.jar)
ImageIO plugins requiring 3rd party libs
* [imageio-batik-3.0.2.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-batik/3.0.2/imageio-batik-3.0.2.jar)
* [imageio-jmagick-3.0.2.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-jmagick/3.0.2/imageio-jmagick-3.0.2.jar)
Servlet support
* [servlet-3.0.2.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/servlet/servlet/3.0.2/servlet-3.0.2.jar)
## License
This project is provided under the OSI approved [BSD license](https://opensource.org/licenses/BSD-3-Clause):
Copyright (c) 2008-2022, Harald Kuhr
Copyright (c) 2008-2020, Harald Kuhr
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -469,9 +484,8 @@ This project is provided under the OSI approved [BSD license](https://opensource
q: How do I use it?
a: The easiest way is to build your own project using Maven, Gradle or other build tool with dependency management,
and just add dependencies to the specific plug-ins you need.
If you don't use such a build tool, make sure you have all the necessary JARs in classpath. See the Install section above.
a: The easiest way is to build your own project using Maven, and just add dependencies to the specific plug-ins you need.
If you don't use Maven, make sure you have all the necessary JARs in classpath. See the Install section above.
q: What changes do I have to make to my code in order to use the plug-ins?
@@ -489,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.
All you have to do, is to make sure you have the TwelveMonkeys ImageIO JARs in your classpath.
All you have have to do, is to make sure you have the TwelveMonkeys JARs in your classpath.
You can read more about the registry and the lookup mechanism in the [IIORegistry API doc](https://docs.oracle.com/javase/7/docs/api/javax/imageio/spi/IIORegistry.html).
The fine print: The TwelveMonkeys service providers for JPEG, BMP and TIFF, overrides the onRegistration method, and
utilizes the pairwise partial ordering mechanism of the `IIOServiceRegistry` to make sure it is installed before
the Sun/Oracle provided `JPEGImageReader`, `BMPImageReader` `TIFFImageReader`, and the Apple provided `TIFFImageReader` on OS X,
the Sun/Oracle provided `JPEGImageReader` and `BMPImageReader`, and the Apple provided `TIFFImageReader` on OS X,
respectively. Using the pairwise ordering will not remove any functionality form these implementations, but in most
cases you'll end up using the TwelveMonkeys plug-ins instead.
q: Why is there no support for common formats like GIF or PNG?
a: The short answer is simply that the built-in support in ImageIO for these formats are considered good enough as-is.
a: The short answer is simply that the built-in support in ImageIO for these formats are good enough as-is.
If you are looking for better PNG write performance on Java 7 and 8, see [JDK9 PNG Writer Backport](https://github.com/gredler/jdk9-png-writer-backport).
q: When is the next release? What is the current release schedule?
a: The goal is to make monthly releases, containing bug fixes and minor new features.
And quarterly releases with more "major" features.
q: I love this project! How can I help?
a: Have a look at the open issues, and see if there are any issues you can help fix, or provide sample file or create test cases for.
It is also possible for you or your organization to become a sponsor, through GitHub Sponsors.
Providing funding will allow us to spend more time on fixing bugs and implementing new features.
q: What about JAI? Several of the formats are already supported by JAI.
a: While JAI (and jai-imageio in particular) have support for some of the same formats, JAI has some major issues.
-5
View File
@@ -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
View File
@@ -5,7 +5,7 @@
<parent>
<groupId>com.twelvemonkeys</groupId>
<artifactId>twelvemonkeys</artifactId>
<version>3.11.1-SNAPSHOT</version>
<version>3.9.1</version>
</parent>
<groupId>com.twelvemonkeys.bom</groupId>
+2 -11
View File
@@ -4,13 +4,13 @@
<parent>
<groupId>com.twelvemonkeys.common</groupId>
<artifactId>common</artifactId>
<version>3.11.1-SNAPSHOT</version>
<version>3.9.1</version>
</parent>
<artifactId>common-image</artifactId>
<packaging>jar</packaging>
<name>TwelveMonkeys :: Common :: Image</name>
<description>
TwelveMonkeys Common image support classes.
The TwelveMonkeys Common Image support
</description>
<properties>
@@ -36,13 +36,4 @@
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
@@ -79,7 +79,7 @@ public final class BufferedImageFactory {
private int scanSize;
private ColorModel sourceColorModel;
private Hashtable<?, ?> sourceProperties; // ImageConsumer API dictates Hashtable
private Hashtable sourceProperties; // ImageConsumer API dictates Hashtable
private Object sourcePixels;
@@ -91,21 +91,21 @@ public final class BufferedImageFactory {
/**
* Creates a {@code BufferedImageFactory}.
* @param source the source image
* @throws IllegalArgumentException if {@code source == null}
* @param pSource the source image
* @throws IllegalArgumentException if {@code pSource == null}
*/
public BufferedImageFactory(final Image source) {
this(source != null ? source.getSource() : null);
public BufferedImageFactory(final Image pSource) {
this(pSource != null ? pSource.getSource() : null);
}
/**
* Creates a {@code BufferedImageFactory}.
* @param source the source image producer
* @throws IllegalArgumentException if {@code source == null}
* @param pSource the source image producer
* @throws IllegalArgumentException if {@code pSource == null}
*/
public BufferedImageFactory(final ImageProducer source) {
Validate.notNull(source, "source");
producer = source;
public BufferedImageFactory(final ImageProducer pSource) {
Validate.notNull(pSource, "source");
producer = pSource;
}
/**
@@ -155,44 +155,44 @@ public final class BufferedImageFactory {
/**
* Sets the source region (AOI) for the new image.
*
* @param region the source region
* @param pRegion the source region
*/
public void setSourceRegion(final Rectangle region) {
public void setSourceRegion(final Rectangle pRegion) {
// Re-fetch everything, if region changed
if (x != region.x || y != region.y || width != region.width || height != region.height) {
if (x != pRegion.x || y != pRegion.y || width != pRegion.width || height != pRegion.height) {
dispose();
}
x = region.x;
y = region.y;
width = region.width;
height = region.height;
x = pRegion.x;
y = pRegion.y;
width = pRegion.width;
height = pRegion.height;
}
/**
* Sets the source subsampling for the new image.
*
* @param xSubsampling horizontal subsampling factor
* @param ySubsampling vertical subsampling factor
* @param pXSub horizontal subsampling factor
* @param pYSub vertical subsampling factor
*/
public void setSourceSubsampling(int xSubsampling, int ySubsampling) {
public void setSourceSubsampling(int pXSub, int pYSub) {
// Re-fetch everything, if subsampling changed
if (xSub != xSubsampling || ySub != ySubsampling) {
if (xSub != pXSub || ySub != pYSub) {
dispose();
}
if (xSubsampling > 1) {
xSub = xSubsampling;
if (pXSub > 1) {
xSub = pXSub;
}
if (ySubsampling > 1) {
ySub = ySubsampling;
if (pYSub > 1) {
ySub = pYSub;
}
}
private synchronized void doFetch(final boolean colorModelOnly) throws ImageConversionException {
if (!fetching && (!colorModelOnly && buffered == null || buffered == null && sourceColorModel == null)) {
private synchronized void doFetch(boolean pColorModelOnly) throws ImageConversionException {
if (!fetching && (!pColorModelOnly && buffered == null || buffered == null && sourceColorModel == null)) {
// NOTE: Subsampling is only applied if extracting full image
if (!colorModelOnly && (xSub > 1 || ySub > 1)) {
if (!pColorModelOnly && (xSub > 1 || ySub > 1)) {
// If only sampling a region, the region must be scaled too
if (width > 0 && height > 0) {
width = (width + xSub - 1) / xSub;
@@ -207,41 +207,38 @@ public final class BufferedImageFactory {
// Start fetching
fetching = true;
readColorModelOnly = colorModelOnly;
readColorModelOnly = pColorModelOnly;
producer.startProduction(consumer); // Note: If single-thread (synchronous), this call will block
// Wait until the producer wakes us up, by calling imageComplete
while (fetching) {
try {
wait(200L);
wait(200l);
}
catch (InterruptedException e) {
throw new ImageConversionException("Image conversion aborted: " + e.getMessage(), e);
}
}
try {
if (consumerException != null) {
throw new ImageConversionException("Image conversion failed: " + consumerException.getMessage(), consumerException);
}
if (colorModelOnly) {
createColorModel();
}
else {
createBuffered();
}
if (consumerException != null) {
throw new ImageConversionException("Image conversion failed: " + consumerException.getMessage(), consumerException);
}
finally {
// Clean up, in case any objects are copied/cloned, so we can free resources
freeResources();
if (pColorModelOnly) {
createColorModel();
}
else {
createBuffered();
}
}
}
private void createColorModel() {
colorModel = sourceColorModel;
// Clean up, in case any objects are copied/cloned, so we can free resources
freeResources();
}
private void createBuffered() {
@@ -256,9 +253,8 @@ public final class BufferedImageFactory {
}
}
if (buffered == null) {
throw new ImageConversionException("Could not create BufferedImage");
}
// Clean up, in case any objects are copied/cloned, so we can free resources
freeResources();
}
private void freeResources() {
@@ -284,27 +280,27 @@ public final class BufferedImageFactory {
/**
* Adds a progress listener to this factory.
*
* @param listener the progress listener
* @param pListener the progress listener
*/
public void addProgressListener(ProgressListener listener) {
if (listener == null) {
public void addProgressListener(ProgressListener pListener) {
if (pListener == null) {
return;
}
if (listeners == null) {
listeners = new CopyOnWriteArrayList<>();
listeners = new CopyOnWriteArrayList<ProgressListener>();
}
listeners.add(listener);
listeners.add(pListener);
}
/**
* Removes a progress listener from this factory.
*
* @param listener the progress listener
* @param pListener the progress listener
*/
public void removeProgressListener(ProgressListener listener) {
if (listener == null) {
public void removeProgressListener(ProgressListener pListener) {
if (pListener == null) {
return;
}
@@ -312,7 +308,7 @@ public final class BufferedImageFactory {
return;
}
listeners.remove(listener);
listeners.remove(pListener);
}
/**
@@ -328,22 +324,21 @@ public final class BufferedImageFactory {
* Converts an array of {@code int} pixels to an array of {@code short}
* pixels. The conversion is done, by masking out the
* <em>higher 16 bits</em> of the {@code int}.
* <p>
*
* For any given {@code int}, the {@code short} value is computed as
* follows:
* <blockquote>{@code
* short value = (short) (intValue & 0x0000ffff);
* }</blockquote>
* </p>
*
* @param inputPixels the pixel data to convert
* @return an array of {@code short}s, same length as {@code inputPixels}
* @param pPixels the pixel data to convert
* @return an array of {@code short}s, same lenght as {@code pPixels}
*/
private static short[] toShortPixels(int[] inputPixels) {
short[] pixels = new short[inputPixels.length];
private static short[] toShortPixels(int[] pPixels) {
short[] pixels = new short[pPixels.length];
for (int i = 0; i < pixels.length; i++) {
pixels[i] = (short) (inputPixels[i] & 0xffff);
pixels[i] = (short) (pPixels[i] & 0xffff);
}
return pixels;
@@ -356,17 +351,17 @@ public final class BufferedImageFactory {
* @see BufferedImageFactory#addProgressListener
* @see BufferedImageFactory#removeProgressListener
*/
public interface ProgressListener extends EventListener {
public static interface ProgressListener extends EventListener {
/**
* Reports progress to this listener.
* Invoked by the {@code BufferedImageFactory} to report progress in
* the image decoding.
*
* @param factory the factory reporting the progress
* @param percentage the percentage of progress
* @param pFactory the factory reporting the progress
* @param pPercentage the percentage of progress
*/
void progress(BufferedImageFactory factory, float percentage);
void progress(BufferedImageFactory pFactory, float pPercentage);
}
private class Consumer implements ImageConsumer {
@@ -451,18 +446,18 @@ public final class BufferedImageFactory {
processProgress(pY + pHeight);
}
public void setPixels(int x, int y, int width, int height, ColorModel colorModel, short[] pixels, int offset, int scanSize) {
setPixelsImpl(x, y, width, height, colorModel, pixels, offset, scanSize);
public void setPixels(int pX, int pY, int pWidth, int pHeight, ColorModel pModel, short[] pPixels, int pOffset, int pScanSize) {
setPixelsImpl(pX, pY, pWidth, pHeight, pModel, pPixels, pOffset, pScanSize);
}
private void setColorModelOnce(final ColorModel colorModel) {
private void setColorModelOnce(final ColorModel pModel) {
// NOTE: There seems to be a "bug" in AreaAveragingScaleFilter, as it
// first passes the original color model through in setColorModel, then
// later replaces it with the default RGB in the first setPixels call
// (this is probably allowed according to the spec, but it's a waste of time and space).
if (sourceColorModel != colorModel) {
if (sourcePixels == null) {
sourceColorModel = colorModel;
if (sourceColorModel != pModel) {
if (/*sourceColorModel == null ||*/ sourcePixels == null) {
sourceColorModel = pModel;
}
else {
throw new IllegalStateException("Change of ColorModel after pixel delivery not supported");
@@ -475,16 +470,17 @@ public final class BufferedImageFactory {
}
}
@Override
public void imageComplete(int status) {
public void imageComplete(int pStatus) {
fetching = false;
if (producer != null) {
producer.removeConsumer(this);
}
if (status == ImageConsumer.IMAGEERROR) {
consumerException = new ImageConversionException("ImageConsumer.IMAGEERROR");
switch (pStatus) {
case ImageConsumer.IMAGEERROR:
consumerException = new ImageConversionException("ImageConsumer.IMAGEERROR");
break;
}
synchronized (BufferedImageFactory.this) {
@@ -492,18 +488,16 @@ public final class BufferedImageFactory {
}
}
@Override
public void setColorModel(ColorModel colorModel) {
setColorModelOnce(colorModel);
public void setColorModel(ColorModel pModel) {
setColorModelOnce(pModel);
}
@Override
public void setDimensions(int w, int h) {
public void setDimensions(int pWidth, int pHeight) {
if (width < 0) {
width = w - x;
width = pWidth - x;
}
if (height < 0) {
height = h - y;
height = pHeight - y;
}
// Hmm.. Special case, but is it a good idea?
@@ -512,31 +506,27 @@ public final class BufferedImageFactory {
}
}
@Override
public void setHints(int hintFlags) {
public void setHints(int pHintflags) {
// ignore
}
@Override
public void setPixels(int x, int y, int width, int height, ColorModel colorModel, byte[] pixels, int offset, int scanSize) {
setPixelsImpl(x, y, width, height, colorModel, pixels, offset, scanSize);
public void setPixels(int pX, int pY, int pWidth, int pHeight, ColorModel pModel, byte[] pPixels, int pOffset, int pScanSize) {
setPixelsImpl(pX, pY, pWidth, pHeight, pModel, pPixels, pOffset, pScanSize);
}
@Override
public void setPixels(int x, int y, int width, int height, ColorModel colorModel, int[] pixels, int offset, int scanSize) {
if (colorModel.getTransferType() == DataBuffer.TYPE_USHORT) {
public void setPixels(int pX, int pY, int pWeigth, int pHeight, ColorModel pModel, int[] pPixels, int pOffset, int pScanSize) {
if (pModel.getTransferType() == DataBuffer.TYPE_USHORT) {
// NOTE: Workaround for limitation in ImageConsumer API
// Convert int[] to short[], to be compatible with the ColorModel
setPixelsImpl(x, y, width, height, colorModel, toShortPixels(pixels), offset, scanSize);
setPixelsImpl(pX, pY, pWeigth, pHeight, pModel, toShortPixels(pPixels), pOffset, pScanSize);
}
else {
setPixelsImpl(x, y, width, height, colorModel, pixels, offset, scanSize);
setPixelsImpl(pX, pY, pWeigth, pHeight, pModel, pPixels, pOffset, pScanSize);
}
}
@Override
public void setProperties(Hashtable properties) {
sourceProperties = properties;
public void setProperties(Hashtable pProperties) {
sourceProperties = pProperties;
}
}
@@ -844,7 +844,7 @@ public final class ImageUtil {
return false;
}
for (int i = 0; i < mapSize1; i++) {
for (int i = 0; i > mapSize1; i++) {
if (icm1.getRGB(i) != icm2.getRGB(i)) {
return false;
}
@@ -34,13 +34,14 @@ import org.junit.Ignore;
import org.junit.Test;
import java.awt.*;
import java.awt.color.*;
import java.awt.image.*;
import java.awt.color.ColorSpace;
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import java.awt.image.ImageProducer;
import java.awt.image.IndexColorModel;
import java.net.URL;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.*;
/**
* BufferedImageFactoryTestCase
@@ -259,9 +260,9 @@ public class BufferedImageFactoryTest {
// Listener should abort ASAP
factory.addProgressListener(new BufferedImageFactory.ProgressListener() {
public void progress(BufferedImageFactory factory, float percentage) {
if (percentage > 5) {
factory.abort();
public void progress(BufferedImageFactory pFactory, float pPercentage) {
if (pPercentage > 5) {
pFactory.abort();
}
}
});
@@ -342,7 +343,7 @@ public class BufferedImageFactoryTest {
VerifyingListener listener = new VerifyingListener(factory);
factory.addProgressListener(listener);
factory.removeProgressListener(new BufferedImageFactory.ProgressListener() {
public void progress(BufferedImageFactory factory, float percentage) {
public void progress(BufferedImageFactory pFactory, float pPercentage) {
}
});
factory.getBufferedImage();
@@ -379,11 +380,11 @@ public class BufferedImageFactoryTest {
this.factory = factory;
}
public void progress(BufferedImageFactory factory, float percentage) {
assertEquals(this.factory, factory);
assertTrue(percentage >= progress && percentage <= 100f);
public void progress(BufferedImageFactory pFactory, float pPercentage) {
assertEquals(factory, pFactory);
assertTrue(pPercentage >= progress && pPercentage <= 100f);
progress = percentage;
progress = pPercentage;
}
+2 -10
View File
@@ -4,13 +4,13 @@
<parent>
<groupId>com.twelvemonkeys.common</groupId>
<artifactId>common</artifactId>
<version>3.11.1-SNAPSHOT</version>
<version>3.9.1</version>
</parent>
<artifactId>common-io</artifactId>
<packaging>jar</packaging>
<name>TwelveMonkeys :: Common :: IO</name>
<description>
TwelveMonkeys Common I/O support classes.
The TwelveMonkeys Common IO support
</description>
<properties>
@@ -31,12 +31,4 @@
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
@@ -56,8 +56,8 @@ public class CompoundReader extends Reader {
private int currentReader;
private int markedReader;
private long mark;
private long next;
private int mark;
private int mNext;
/**
* Create a new compound reader.
@@ -76,7 +76,7 @@ public class CompoundReader extends Reader {
finalLock = pReaders; // NOTE: It's ok to sync on pReaders, as the
// reference can't change, only it's elements
readers = new ArrayList<>();
readers = new ArrayList<Reader>();
boolean markSupported = true;
while (pReaders.hasNext()) {
@@ -101,7 +101,7 @@ public class CompoundReader extends Reader {
}
// NOTE: Reset mNext for every reader, and record marked reader in mark/reset methods!
next = 0;
mNext = 0;
return current;
}
@@ -135,7 +135,7 @@ public class CompoundReader extends Reader {
synchronized (finalLock) {
ensureOpen();
mark = next;
mark = mNext;
markedReader = currentReader;
current.mark(pReadLimit);
@@ -158,7 +158,7 @@ public class CompoundReader extends Reader {
}
current.reset();
next = mark;
mNext = mark;
}
}
@@ -177,13 +177,13 @@ public class CompoundReader extends Reader {
return read(); // In case of 0-length readers
}
next++;
mNext++;
return read;
}
}
public int read(char[] pBuffer, int pOffset, int pLength) throws IOException {
public int read(char pBuffer[], int pOffset, int pLength) throws IOException {
synchronized (finalLock) {
int read = current.read(pBuffer, pOffset, pLength);
@@ -192,7 +192,7 @@ public class CompoundReader extends Reader {
return read(pBuffer, pOffset, pLength); // In case of 0-length readers
}
next += read;
mNext += read;
return read;
}
@@ -213,7 +213,7 @@ public class CompoundReader extends Reader {
return skip(pChars); // In case of 0-length readers
}
next += skipped;
mNext += skipped;
return skipped;
}
@@ -50,8 +50,8 @@ public class StringArrayReader extends StringReader {
protected final Object finalLock;
private int currentSting;
private int markedString;
private long mark;
private long next;
private int mark;
private int next;
/**
* Create a new string array reader.
@@ -151,7 +151,7 @@ public class StringArrayReader extends StringReader {
}
}
public int read(char[] pBuffer, int pOffset, int pLength) throws IOException {
public int read(char pBuffer[], int pOffset, int pLength) throws IOException {
synchronized (finalLock) {
int read = current.read(pBuffer, pOffset, pLength);
@@ -41,20 +41,21 @@ import java.io.InputStream;
* underlying stream.
*
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-core/src/main/java/com/twelvemonkeys/io/SubStream.java#2 $
*/
public final class SubStream extends FilterInputStream {
private long bytesLeft;
private int markLimit;
/**
* Creates a {@code SubStream} of the given {@code stream}.
* Creates a {@code SubStream} of the given {@code pStream}.
*
* @param stream the underlying input stream
* @param length maximum number of bytes to read from this stream
* @param pStream the underlying input stream
* @param pLength maximum number of bytes to read drom this stream
*/
public SubStream(final InputStream stream, final long length) {
super(Validate.notNull(stream, "stream"));
bytesLeft = Validate.isTrue(length >= 0, length, "length < 0: %s");
public SubStream(final InputStream pStream, final long pLength) {
super(Validate.notNull(pStream, "stream"));
bytesLeft = pLength;
}
/**
@@ -63,23 +64,22 @@ public final class SubStream extends FilterInputStream {
*/
@Override
public void close() throws IOException {
// NOTE: Do not close the underlying stream, but consume it
// NOTE: Do not close the underlying stream
while (bytesLeft > 0) {
if (skip(bytesLeft) <= 0 && read() < 0) {
break;
}
//noinspection ResultOfMethodCallIgnored
skip(bytesLeft);
}
}
@Override
public int available() throws IOException {
return (int) findMaxLen(super.available());
return (int) Math.min(super.available(), bytesLeft);
}
@Override
public void mark(int readLimit) {
super.mark(readLimit);// This either succeeds or does nothing...
markLimit = readLimit;
public void mark(int pReadLimit) {
super.mark(pReadLimit);// This either succeeds or does nothing...
markLimit = pReadLimit;
}
@Override
@@ -93,42 +93,44 @@ public final class SubStream extends FilterInputStream {
if (bytesLeft-- <= 0) {
return -1;
}
return super.read();
}
@Override
public int read(byte[] bytes) throws IOException {
return read(bytes, 0, bytes.length);
public final int read(byte[] pBytes) throws IOException {
return read(pBytes, 0, pBytes.length);
}
@Override
public int read(final byte[] bytes, final int off, final int len) throws IOException {
public int read(final byte[] pBytes, final int pOffset, final int pLength) throws IOException {
if (bytesLeft <= 0) {
return -1;
}
int read = super.read(bytes, off, (int) findMaxLen(len));
int read = super.read(pBytes, pOffset, (int) findMaxLen(pLength));
bytesLeft = read < 0 ? 0 : bytesLeft - read;
return read;
}
@Override
public long skip(long length) throws IOException {
long skipped = super.skip(findMaxLen(length)); // Skips 0 or more, never -1
bytesLeft -= skipped;
return skipped;
}
/**
* Finds the maximum number of bytes we can read or skip, from this stream.
*
* @param length the requested length
* @param pLength the requested length
* @return the maximum number of bytes to read
*/
private long findMaxLen(long length) {
return bytesLeft < length ? Math.max(bytesLeft, 0) : length;
private long findMaxLen(long pLength) {
if (bytesLeft < pLength) {
return (int) Math.max(bytesLeft, 0);
}
else {
return pLength;
}
}
@Override
public long skip(long pLength) throws IOException {
long skipped = super.skip(findMaxLen(pLength));// Skips 0 or more, never -1
bytesLeft -= skipped;
return skipped;
}
}
@@ -59,7 +59,7 @@ public final class DecoderStream extends FilterInputStream {
* @see java.io.FilterInputStream#in
*/
public DecoderStream(final InputStream stream, final Decoder decoder) {
// TODO: Let the decoder decide preferred buffer size
// TODO: Let the decoder decide preferred buffer size
this(stream, decoder, 1024);
}
@@ -77,7 +77,7 @@ public final class DecoderStream extends FilterInputStream {
super(stream);
this.decoder = decoder;
buffer = ByteBuffer.allocate(bufferSize); // TODO: Allow decoder to specify minimum buffer size
buffer = ByteBuffer.allocate(bufferSize);
buffer.flip();
}
@@ -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());
}
}
+2 -10
View File
@@ -4,25 +4,17 @@
<parent>
<groupId>com.twelvemonkeys.common</groupId>
<artifactId>common</artifactId>
<version>3.11.1-SNAPSHOT</version>
<version>3.9.1</version>
</parent>
<artifactId>common-lang</artifactId>
<packaging>jar</packaging>
<name>TwelveMonkeys :: Common :: Language support</name>
<description>
TwelveMonkeys Common language support classes.
The TwelveMonkeys Common Language support
</description>
<properties>
<project.jpms.module.name>com.twelvemonkeys.common.lang</project.jpms.module.name>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
@@ -904,7 +904,7 @@ public final class StringUtil {
}
catch (ParseException pe) {
// Wrap in RuntimeException
throw new IllegalArgumentException(pe.getMessage() + " at pos " + pe.getErrorOffset());
throw new IllegalArgumentException(pe.getMessage());
}
}
@@ -593,8 +593,8 @@ public class StringUtilTest {
cal.clear();
cal.set(Calendar.HOUR, 1);
cal.set(Calendar.MINUTE, 2);
format = new SimpleDateFormat("HH:mm");
date = StringUtil.toDate("1:02", format);
date = StringUtil.toDate("1:02 am",
DateFormat.getTimeInstance(DateFormat.SHORT, Locale.US));
assertNotNull(date);
assertEquals(cal.getTime(), date);
}
+2 -2
View File
@@ -4,7 +4,7 @@
<parent>
<groupId>com.twelvemonkeys</groupId>
<artifactId>twelvemonkeys</artifactId>
<version>3.11.1-SNAPSHOT</version>
<version>3.9.1</version>
</parent>
<groupId>com.twelvemonkeys.common</groupId>
<artifactId>common</artifactId>
@@ -47,7 +47,7 @@
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<version>4.13.1</version>
<scope>test</scope>
</dependency>
</dependencies>
+3 -12
View File
@@ -4,13 +4,13 @@
<parent>
<groupId>com.twelvemonkeys</groupId>
<artifactId>twelvemonkeys</artifactId>
<version>3.11.1-SNAPSHOT</version>
<version>3.9.1</version>
</parent>
<groupId>com.twelvemonkeys.contrib</groupId>
<artifactId>contrib</artifactId>
<name>TwelveMonkeys :: Contrib</name>
<description>
Contributions to TwelveMonkeys and code that doesn't fit anywhere else.
Contributions to TwelveMonkeys which are not matching into the ImageIO plug-ins.
</description>
<dependencies>
@@ -65,17 +65,8 @@
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<version>4.13.1</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
+3 -15
View File
@@ -4,7 +4,7 @@
<parent>
<groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio</artifactId>
<version>3.11.1-SNAPSHOT</version>
<version>3.9.1</version>
</parent>
<artifactId>imageio-batik</artifactId>
<name>TwelveMonkeys :: ImageIO :: Batik Plugin</name>
@@ -17,7 +17,7 @@
<properties>
<project.jpms.module.name>com.twelvemonkeys.imageio.batik</project.jpms.module.name>
<batik.version>1.17</batik.version>
<batik.version>1.15</batik.version>
</properties>
<build>
@@ -33,18 +33,6 @@
</systemPropertyVariables>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<configuration>
<instructions>
<Provide-Capability>
osgi.serviceloader;
osgi.serviceloader=javax.imageio.spi.ImageReaderSpi
</Provide-Capability>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
@@ -63,7 +51,7 @@
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.17.0</version>
<version>2.11.0</version>
<scope>provided</scope>
</dependency>
@@ -33,7 +33,6 @@ package com.twelvemonkeys.imageio.plugins.svg;
import com.twelvemonkeys.image.ImageUtil;
import com.twelvemonkeys.imageio.ImageReaderBase;
import com.twelvemonkeys.imageio.util.IIOUtil;
import com.twelvemonkeys.imageio.util.ImageTypeSpecifiers;
import com.twelvemonkeys.lang.StringUtil;
import org.apache.batik.anim.dom.SVGDOMImplementation;
@@ -92,10 +91,10 @@ public class SVGImageReader extends ImageReaderBase {
/**
* Creates an {@code SVGImageReader}.
*
* @param provider the provider
* @param pProvider the provider
*/
public SVGImageReader(final ImageReaderSpi provider) {
super(provider);
public SVGImageReader(final ImageReaderSpi pProvider) {
super(pProvider);
}
protected void resetMembers() {
@@ -109,20 +108,20 @@ public class SVGImageReader extends ImageReaderBase {
}
@Override
public void setInput(Object input, boolean seekForwardOnly, boolean ignoreMetadata) {
super.setInput(input, seekForwardOnly, ignoreMetadata);
public void setInput(Object pInput, boolean seekForwardOnly, boolean ignoreMetadata) {
super.setInput(pInput, seekForwardOnly, ignoreMetadata);
if (imageInput != null) {
TranscoderInput transcoderInput = new TranscoderInput(IIOUtil.createStreamAdapter(imageInput));
rasterizer.setInput(transcoderInput);
TranscoderInput input = new TranscoderInput(IIOUtil.createStreamAdapter(imageInput));
rasterizer.setInput(input);
}
}
public BufferedImage read(int imageIndex, ImageReadParam param) throws IOException {
checkBounds(imageIndex);
public BufferedImage read(int pIndex, ImageReadParam pParam) throws IOException {
checkBounds(pIndex);
if (param instanceof SVGReadParam) {
SVGReadParam svgParam = (SVGReadParam) param;
if (pParam instanceof SVGReadParam) {
SVGReadParam svgParam = (SVGReadParam) pParam;
// set the external-resource-resolution preference
allowExternalResources = svgParam.isAllowExternalResources();
@@ -140,17 +139,17 @@ public class SVGImageReader extends ImageReaderBase {
}
Dimension size = null;
if (param != null) {
size = param.getSourceRenderSize();
if (pParam != null) {
size = pParam.getSourceRenderSize();
}
if (size == null) {
size = new Dimension(getWidth(imageIndex), getHeight(imageIndex));
size = new Dimension(getWidth(pIndex), getHeight(pIndex));
}
BufferedImage destination = getDestination(param, getImageTypes(imageIndex), size.width, size.height);
BufferedImage destination = getDestination(pParam, getImageTypes(pIndex), size.width, size.height);
// Read in the image, using the Batik Transcoder
processImageStarted(imageIndex);
processImageStarted(pIndex);
BufferedImage image = rasterizer.getImage();
@@ -174,18 +173,18 @@ public class SVGImageReader extends ImageReaderBase {
return ex.getException() != null ? ex.getException() : ex;
}
private TranscodingHints paramsToHints(SVGReadParam param) throws IOException {
private TranscodingHints paramsToHints(SVGReadParam pParam) throws IOException {
TranscodingHints hints = new TranscodingHints();
// Note: We must allow generic ImageReadParams, so converting to
// TanscodingHints should be done outside the SVGReadParam class.
// Set dimensions
Dimension size = param.getSourceRenderSize();
Dimension size = pParam.getSourceRenderSize();
Rectangle viewBox = rasterizer.getViewBox();
if (size == null) {
// SVG is not a pixel based format, but we'll scale it, according to
// the subsampling for compatibility
size = getSourceRenderSizeFromSubsamping(param, viewBox.getSize());
size = getSourceRenderSizeFromSubsamping(pParam, viewBox.getSize());
}
if (size != null) {
@@ -194,7 +193,7 @@ public class SVGImageReader extends ImageReaderBase {
}
// Set area of interest
Rectangle region = param.getSourceRegion();
Rectangle region = pParam.getSourceRegion();
if (region != null) {
hints.put(ImageTranscoder.KEY_AOI, region);
@@ -218,7 +217,7 @@ public class SVGImageReader extends ImageReaderBase {
}
// Background color
Paint bg = param.getBackgroundColor();
Paint bg = pParam.getBackgroundColor();
if (bg != null) {
hints.put(ImageTranscoder.KEY_BACKGROUND_COLOR, bg);
}
@@ -226,10 +225,10 @@ public class SVGImageReader extends ImageReaderBase {
return hints;
}
private Dimension getSourceRenderSizeFromSubsamping(ImageReadParam param, Dimension origSize) {
if (param.getSourceXSubsampling() > 1 || param.getSourceYSubsampling() > 1) {
return new Dimension((int) (origSize.width / (float) param.getSourceXSubsampling()),
(int) (origSize.height / (float) param.getSourceYSubsampling()));
private Dimension getSourceRenderSizeFromSubsamping(ImageReadParam pParam, Dimension pOrigSize) {
if (pParam.getSourceXSubsampling() > 1 || pParam.getSourceYSubsampling() > 1) {
return new Dimension((int) (pOrigSize.width / (float) pParam.getSourceXSubsampling()),
(int) (pOrigSize.height / (float) pParam.getSourceYSubsampling()));
}
return null;
}
@@ -238,19 +237,19 @@ public class SVGImageReader extends ImageReaderBase {
return new SVGReadParam();
}
public int getWidth(int imageIndex) throws IOException {
checkBounds(imageIndex);
public int getWidth(int pIndex) throws IOException {
checkBounds(pIndex);
return rasterizer.getDefaultWidth();
}
public int getHeight(int imageIndex) throws IOException {
checkBounds(imageIndex);
public int getHeight(int pIndex) throws IOException {
checkBounds(pIndex);
return rasterizer.getDefaultHeight();
}
public Iterator<ImageTypeSpecifier> getImageTypes(int imageIndex) {
return Collections.singleton(ImageTypeSpecifiers.createFromRenderedImage(rasterizer.createImage(1, 1))).iterator();
return Collections.singleton(ImageTypeSpecifier.createFromRenderedImage(rasterizer.createImage(1, 1))).iterator();
}
/**
@@ -602,7 +601,6 @@ public class SVGImageReader extends ImageReaderBase {
initialized = true;
try {
super.addTranscodingHint(SVGAbstractTranscoder.KEY_ALLOW_EXTERNAL_RESOURCES, allowExternalResources);
super.transcode(transcoderInput, null);
}
catch (TranscoderException e) {
@@ -635,8 +633,8 @@ public class SVGImageReader extends ImageReaderBase {
return viewBox.getBounds();
}
void setInput(final TranscoderInput input) {
transcoderInput = input;
void setInput(final TranscoderInput pInput) {
transcoderInput = pInput;
}
@Override
@@ -60,22 +60,22 @@ public final class SVGImageReaderSpi extends ImageReaderSpiBase {
super(new SVGProviderInfo());
}
public boolean canDecodeInput(final Object source) throws IOException {
return source instanceof ImageInputStream && canDecode((ImageInputStream) source);
public boolean canDecodeInput(final Object pSource) throws IOException {
return pSource instanceof ImageInputStream && canDecode((ImageInputStream) pSource);
}
@SuppressWarnings("StatementWithEmptyBody")
private static boolean canDecode(final ImageInputStream input) throws IOException {
private static boolean canDecode(final ImageInputStream pInput) throws IOException {
// NOTE: This test is quite quick as it does not involve any parsing,
// however it may not recognize all kinds of SVG documents.
try {
input.mark();
pInput.mark();
// TODO: This is not ok for UTF-16 and other wide encodings
// TODO: Use an XML (encoding) aware Reader instance instead
// Need to figure out pretty fast if this is XML or not
int b;
while (Character.isWhitespace((char) (b = input.read()))) {
while (Character.isWhitespace((char) (b = pInput.read()))) {
// Skip over leading WS
}
@@ -95,30 +95,30 @@ public final class SVGImageReaderSpi extends ImageReaderSpiBase {
byte[] buffer = new byte[4];
while (true) {
input.readFully(buffer);
pInput.readFully(buffer);
if (buffer[0] == '?') {
// This is the XML declaration or a processing instruction
while (!((input.readByte() & 0xFF) == '?' && input.read() == '>')) {
while (!((pInput.readByte() & 0xFF) == '?' && pInput.read() == '>')) {
// Skip until end of XML declaration or processing instruction or EOF
}
}
else if (buffer[0] == '!') {
if (buffer[1] == '-' && buffer[2] == '-') {
// This is a comment
while (!((input.readByte() & 0xFF) == '-' && input.read() == '-' && input.read() == '>')) {
while (!((pInput.readByte() & 0xFF) == '-' && pInput.read() == '-' && pInput.read() == '>')) {
// Skip until end of comment or EOF
}
}
else if (buffer[1] == 'D' && buffer[2] == 'O' && buffer[3] == 'C'
&& input.read() == 'T' && input.read() == 'Y'
&& input.read() == 'P' && input.read() == 'E') {
&& pInput.read() == 'T' && pInput.read() == 'Y'
&& pInput.read() == 'P' && pInput.read() == 'E') {
// This is the DOCTYPE declaration
while (Character.isWhitespace((char) (b = input.read()))) {
while (Character.isWhitespace((char) (b = pInput.read()))) {
// Skip over WS
}
if (b == 's' && input.read() == 'v' && input.read() == 'g') {
if (b == 's' && pInput.read() == 'v' && pInput.read() == 'g') {
// It's SVG, identified by DOCTYPE
return true;
}
@@ -142,7 +142,7 @@ public final class SVGImageReaderSpi extends ImageReaderSpiBase {
return false;
}
while ((input.readByte() & 0xFF) != '<') {
while ((pInput.readByte() & 0xFF) != '<') {
// Skip over, until next begin tag or EOF
}
}
@@ -153,7 +153,7 @@ public final class SVGImageReaderSpi extends ImageReaderSpiBase {
}
finally {
//noinspection ThrowFromFinallyBlock
input.reset();
pInput.reset();
}
}
@@ -51,16 +51,16 @@ public class SVGReadParam extends ImageReadParam {
return background;
}
public void setBackgroundColor(Paint color) {
background = color;
public void setBackgroundColor(Paint pColor) {
background = pColor;
}
public String getBaseURI() {
return baseURI;
}
public void setBaseURI(String baseURI) {
this.baseURI = baseURI;
public void setBaseURI(String pBaseURI) {
baseURI = pBaseURI;
}
public void setAllowExternalResources(boolean allow) {
+1 -20
View File
@@ -4,7 +4,7 @@
<parent>
<groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio</artifactId>
<version>3.11.1-SNAPSHOT</version>
<version>3.9.1</version>
</parent>
<artifactId>imageio-bmp</artifactId>
<name>TwelveMonkeys :: ImageIO :: BMP plugin</name>
@@ -26,23 +26,4 @@
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<configuration>
<instructions>
<Provide-Capability>
osgi.serviceloader;
osgi.serviceloader=javax.imageio.spi.ImageReaderSpi,
osgi.serviceloader;
osgi.serviceloader=javax.imageio.spi.ImageWriterSpi
</Provide-Capability>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
</project>
@@ -81,8 +81,8 @@ public final class BMPImageReader extends ImageReaderBase {
super(new BMPImageReaderSpi());
}
BMPImageReader(final ImageReaderSpi provider) {
super(provider);
BMPImageReader(final ImageReaderSpi pProvider) {
super(pProvider);
}
@Override
@@ -129,7 +129,6 @@ public final class BMPImageReader extends ImageReaderBase {
// Read DIB header
header = DIBHeader.read(imageInput);
// System.out.println("header = " + header);
if (pixelOffset < header.size + DIB.BMP_FILE_HEADER_SIZE) {
throw new IIOException("Invalid pixel offset: " + pixelOffset);
@@ -187,30 +186,30 @@ public final class BMPImageReader extends ImageReaderBase {
}
@Override
public int getWidth(int imageIndex) throws IOException {
checkBounds(imageIndex);
public int getWidth(int pImageIndex) throws IOException {
checkBounds(pImageIndex);
return header.getWidth();
}
@Override
public int getHeight(int imageIndex) throws IOException {
checkBounds(imageIndex);
public int getHeight(int pImageIndex) throws IOException {
checkBounds(pImageIndex);
return header.getHeight();
}
@Override
public Iterator<ImageTypeSpecifier> getImageTypes(int imageIndex) throws IOException {
checkBounds(imageIndex);
public Iterator<ImageTypeSpecifier> getImageTypes(int pImageIndex) throws IOException {
checkBounds(pImageIndex);
// TODO: Better implementation, include INT_RGB types for 3BYTE_BGR and 4BYTE_ABGR for INT_ARGB
return Collections.singletonList(getRawImageType(imageIndex)).iterator();
return Collections.singletonList(getRawImageType(pImageIndex)).iterator();
}
@Override
public ImageTypeSpecifier getRawImageType(int imageIndex) throws IOException {
checkBounds(imageIndex);
public ImageTypeSpecifier getRawImageType(int pImageIndex) throws IOException {
checkBounds(pImageIndex);
if (header.getPlanes() != 1) {
throw new IIOException("Multiple planes not supported");
@@ -686,8 +685,8 @@ public final class BMPImageReader extends ImageReaderBase {
}
@SuppressWarnings({ "unchecked", "UnusedDeclaration", "SameParameterValue" })
static <T extends Throwable> void throwAs(final Class<T> type, final Throwable throwable) throws T {
throw (T) throwable;
static <T extends Throwable> void throwAs(final Class<T> pType, final Throwable pThrowable) throws T {
throw (T) pThrowable;
}
private class ListenerDelegator extends ProgressListenerBase implements IIOReadUpdateListener, IIOReadWarningListener {
@@ -65,16 +65,16 @@ public final class BMPImageReaderSpi extends ImageReaderSpiBase {
}
}
public boolean canDecodeInput(final Object source) throws IOException {
return source instanceof ImageInputStream && canDecode((ImageInputStream) source);
public boolean canDecodeInput(final Object pSource) throws IOException {
return pSource instanceof ImageInputStream && canDecode((ImageInputStream) pSource);
}
private static boolean canDecode(final ImageInputStream input) throws IOException {
private static boolean canDecode(final ImageInputStream pInput) throws IOException {
byte[] fileHeader = new byte[18]; // Strictly: file header (14 bytes) + BMP header size field (4 bytes)
try {
input.mark();
input.readFully(fileHeader);
pInput.mark();
pInput.readFully(fileHeader);
// Magic: BM
if (fileHeader[0] != 'B' || fileHeader[1] != 'M') {
@@ -112,15 +112,15 @@ public final class BMPImageReaderSpi extends ImageReaderSpiBase {
}
}
finally {
input.reset();
pInput.reset();
}
}
public ImageReader createReaderInstance(final Object extension) {
public ImageReader createReaderInstance(final Object pExtension) {
return new BMPImageReader(this);
}
public String getDescription(final Locale locale) {
public String getDescription(final Locale pLocale) {
return "Windows Device Independent Bitmap Format (BMP) Reader";
}
}
@@ -47,7 +47,7 @@ import java.nio.ByteOrder;
* BMPImageWriter
*/
public final class BMPImageWriter extends DIBImageWriter {
BMPImageWriter(ImageWriterSpi provider) {
protected BMPImageWriter(ImageWriterSpi provider) {
super(provider);
}
@@ -32,7 +32,6 @@ package com.twelvemonkeys.imageio.plugins.bmp;
import com.twelvemonkeys.imageio.AbstractMetadata;
import com.twelvemonkeys.lang.Validate;
import org.w3c.dom.Node;
import javax.imageio.metadata.IIOMetadataNode;
@@ -142,7 +141,7 @@ final class BMPMetadata extends AbstractMetadata {
@Override
protected IIOMetadataNode getStandardChromaNode() {
// NOTE: BMP files may contain a color map, even if true color...
// Not sure if this is a good idea to expose to the metadata,
// Not sure if this is a good idea to expose to the meta data,
// as it might be unexpected... Then again...
if (colorMap != null) {
IIOMetadataNode chroma = new IIOMetadataNode("Chroma");
@@ -29,11 +29,11 @@
*/
package com.twelvemonkeys.imageio.plugins.bmp;
import java.awt.image.*;
import java.io.IOException;
import static com.twelvemonkeys.lang.Validate.notNull;
import java.awt.image.BufferedImage;
import java.io.IOException;
/**
* Describes a bitmap structure.
*
@@ -47,9 +47,9 @@ abstract class BitmapDescriptor {
protected BufferedImage image;
protected BitmapMask mask;
public BitmapDescriptor(final DirectoryEntry entry, final DIBHeader header) {
this.entry = notNull(entry, "entry");
this.header = notNull(header, "header");
public BitmapDescriptor(final DirectoryEntry pEntry, final DIBHeader pHeader) {
entry = notNull(pEntry, "entry");;
header = notNull(pHeader, "header");
}
abstract public BufferedImage getImage() throws IOException;
@@ -75,7 +75,7 @@ abstract class BitmapDescriptor {
return getClass().getSimpleName() + "[" + entry + ", " + header + "]";
}
final void setMask(final BitmapMask mask) {
public final void setMask(final BitmapMask mask) {
this.mask = mask;
}
@@ -29,7 +29,10 @@
*/
package com.twelvemonkeys.imageio.plugins.bmp;
import java.awt.image.*;
import java.awt.image.BufferedImage;
import java.awt.image.DataBuffer;
import java.awt.image.IndexColorModel;
import java.awt.image.WritableRaster;
import java.util.Hashtable;
/**
@@ -38,13 +41,12 @@ import java.util.Hashtable;
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
* @version $Id: BitmapIndexed.java,v 1.0 25.feb.2006 00:29:44 haku Exp$
*/
final class BitmapIndexed extends BitmapDescriptor {
final int[] bits;
final int[] colors;
public BitmapIndexed(final DirectoryEntry entry, final DIBHeader header) {
super(entry, header);
class BitmapIndexed extends BitmapDescriptor {
protected final int[] bits;
protected final int[] colors;
public BitmapIndexed(final DirectoryEntry pEntry, final DIBHeader pHeader) {
super(pEntry, pHeader);
bits = new int[getWidth() * getHeight()];
// NOTE: We're adding space for one extra color, for transparency
@@ -57,16 +59,20 @@ final class BitmapIndexed extends BitmapDescriptor {
IndexColorModel icm = createColorModel();
// We add cursor hotspot as a property to images created from CUR format.
// This is slightly obscure, and should probably be moved...
// This is slightly obscure, and should probably be moved..
Hashtable<String, Object> properties = null;
if (entry instanceof DirectoryEntry.CUREntry) {
properties = new Hashtable<>(1);
properties.put("cursor_hotspot", ((DirectoryEntry.CUREntry) this.entry).getHotspot());
}
WritableRaster raster = icm.createCompatibleWritableRaster(getWidth(), getHeight());
BufferedImage image = new BufferedImage(icm, raster, icm.isAlphaPremultiplied(), properties);
BufferedImage image = new BufferedImage(
icm,
icm.createCompatibleWritableRaster(getWidth(), getHeight()),
icm.isAlphaPremultiplied(), properties
);
WritableRaster raster = image.getRaster();
// Make pixels transparent according to mask
final int trans = icm.getTransparentPixel();
@@ -99,7 +105,7 @@ final class BitmapIndexed extends BitmapDescriptor {
int index = findTransparentIndexMaybeRemap(this.colors, this.bits);
if (index == -1) {
// No duplicate found, increase bit count
// No duplicate found, increase bitcount
bits++;
transparent = this.colors.length - 1;
}
@@ -111,8 +117,10 @@ final class BitmapIndexed extends BitmapDescriptor {
}
// NOTE: Setting hasAlpha to true, makes things work on 1.2
return new IndexColorModel(bits, colors, this.colors, 0, true, transparent,
bits <= 8 ? DataBuffer.TYPE_BYTE : DataBuffer.TYPE_USHORT);
return new IndexColorModel(
bits, colors, this.colors, 0, true, transparent,
bits <= 8 ? DataBuffer.TYPE_BYTE : DataBuffer.TYPE_USHORT
);
}
private static int findTransparentIndexMaybeRemap(final int[] colors, final int[] bits) {
@@ -30,7 +30,7 @@
package com.twelvemonkeys.imageio.plugins.bmp;
import java.awt.image.*;
import java.awt.image.BufferedImage;
/**
@@ -39,17 +39,17 @@ import java.awt.image.*;
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
* @version $Id: BitmapMask.java,v 1.0 25.feb.2006 00:29:44 haku Exp$
*/
final class BitmapMask extends BitmapDescriptor {
final BitmapIndexed bitMask;
class BitmapMask extends BitmapDescriptor {
protected final BitmapIndexed bitMask;
public BitmapMask(final DirectoryEntry parent, final DIBHeader header) {
super(parent, header);
bitMask = new BitmapIndexed(parent, header);
public BitmapMask(final DirectoryEntry pParent, final DIBHeader pHeader) {
super(pParent, pHeader);
bitMask = new BitmapIndexed(pParent, pHeader);
}
boolean isTransparent(final int x, final int y) {
boolean isTransparent(final int pX, final int pY) {
// NOTE: 1: Fully transparent, 0: Opaque...
return bitMask.bits[x + y * getWidth()] != 0;
return bitMask.bits[pX + pY * getWidth()] != 0;
}
public BufferedImage getImage() {
@@ -31,7 +31,8 @@
package com.twelvemonkeys.imageio.plugins.bmp;
import java.awt.*;
import java.awt.image.*;
import java.awt.image.BufferedImage;
import java.awt.image.WritableRaster;
/**
* Describes an RGB/true color bitmap structure (16, 24 and 32 bits per pixel).
@@ -39,10 +40,10 @@ import java.awt.image.*;
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
* @version $Id: BitmapRGB.java,v 1.0 25.feb.2006 00:29:44 haku Exp$
*/
final class BitmapRGB extends BitmapDescriptor {
class BitmapRGB extends BitmapDescriptor {
public BitmapRGB(final DirectoryEntry entry, final DIBHeader header) {
super(entry, header);
public BitmapRGB(final DirectoryEntry pEntry, final DIBHeader pHeader) {
super(pEntry, pHeader);
}
@Override
@@ -70,7 +71,7 @@ final class BitmapRGB extends BitmapDescriptor {
WritableRaster alphaRaster = masked.getAlphaRaster();
byte[] trans = {0x00};
byte[] trans = {0x0};
for (int y = 0; y < getHeight(); y++) {
for (int x = 0; x < getWidth(); x++) {
if (mask.isTransparent(x, y)) {
@@ -30,10 +30,11 @@
package com.twelvemonkeys.imageio.plugins.bmp;
import javax.imageio.IIOException;
import java.awt.image.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import javax.imageio.IIOException;
/**
* Represents bitmap structures we can't read.
* Allows for deferred exception handling, and allowing clients to read all images that can be read.
@@ -41,13 +42,13 @@ import java.io.IOException;
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
* @version $Id: BitmapUnsupported.java,v 1.0 25.feb.2006 00:29:44 haku Exp$
*/
final class BitmapUnsupported extends BitmapDescriptor {
private final String message;
class BitmapUnsupported extends BitmapDescriptor {
private String message;
public BitmapUnsupported(final DirectoryEntry entry, DIBHeader header, final String message) {
super(entry, header);
public BitmapUnsupported(final DirectoryEntry pEntry, DIBHeader header, final String pMessage) {
super(pEntry, header);
this.message = message;
message = pMessage;
}
@Override
@@ -48,22 +48,22 @@ public final class CURImageReader extends DIBImageReader {
super(new CURImageReaderSpi());
}
CURImageReader(final ImageReaderSpi provider) {
super(provider);
protected CURImageReader(final ImageReaderSpi pProvider) {
super(pProvider);
}
/**
* Returns the hot spot location for the cursor.
*
* @param imageIndex the index of the cursor in the current input.
* @param pImageIndex the index of the cursor in the current input.
* @return the hot spot location for the cursor
*
* @throws java.io.IOException if an I/O exception occurs during reading of image meta data
* @throws IndexOutOfBoundsException if {@code pImageIndex} is less than {@code 0} or greater than/equal to
* the number of cursors in the file
*/
public Point getHotSpot(final int imageIndex) throws IOException {
DirectoryEntry.CUREntry entry = (DirectoryEntry.CUREntry) getEntry(imageIndex);
public final Point getHotSpot(final int pImageIndex) throws IOException {
DirectoryEntry.CUREntry entry = (DirectoryEntry.CUREntry) getEntry(pImageIndex);
return entry.getHotspot();
}
}
@@ -32,6 +32,7 @@ package com.twelvemonkeys.imageio.plugins.bmp;
import com.twelvemonkeys.imageio.spi.ImageReaderSpiBase;
import javax.imageio.ImageReader;
import javax.imageio.stream.ImageInputStream;
import java.io.IOException;
import java.util.Locale;
@@ -48,15 +49,15 @@ public final class CURImageReaderSpi extends ImageReaderSpiBase {
super(new CURProviderInfo());
}
public boolean canDecodeInput(final Object source) throws IOException {
return source instanceof ImageInputStream && ICOImageReaderSpi.canDecode((ImageInputStream) source, DIB.TYPE_CUR);
public boolean canDecodeInput(final Object pSource) throws IOException {
return pSource instanceof ImageInputStream && ICOImageReaderSpi.canDecode((ImageInputStream) pSource, DIB.TYPE_CUR);
}
public CURImageReader createReaderInstance(final Object extension) {
public ImageReader createReaderInstance(final Object pExtension) throws IOException {
return new CURImageReader(this);
}
public String getDescription(final Locale locale) {
public String getDescription(final Locale pLocale) {
return "Windows Cursor Format (CUR) Reader";
}
}
@@ -30,11 +30,12 @@
package com.twelvemonkeys.imageio.plugins.bmp;
import javax.imageio.IIOException;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import javax.imageio.IIOException;
/**
* Represents the DIB (Device Independent Bitmap) Information header structure.
*
@@ -90,17 +91,17 @@ abstract class DIBHeader {
protected DIBHeader() {
}
public static DIBHeader read(final DataInput stream) throws IOException {
int size = stream.readInt();
public static DIBHeader read(final DataInput pStream) throws IOException {
int size = pStream.readInt();
DIBHeader header = createHeader(size);
header.read(size, stream);
header.read(size, pStream);
return header;
}
private static DIBHeader createHeader(final int size) throws IOException {
switch (size) {
private static DIBHeader createHeader(final int pSize) throws IOException {
switch (pSize) {
case DIB.BITMAP_CORE_HEADER_SIZE:
return new BitmapCoreHeader();
case DIB.OS2_V2_HEADER_16_SIZE:
@@ -117,12 +118,11 @@ abstract class DIBHeader {
case DIB.BITMAP_V5_INFO_HEADER_SIZE:
return new BitmapV5InfoHeader();
default:
throw new IIOException(String.format("Unknown Bitmap Information Header (size: %s)", size));
throw new IIOException(String.format("Unknown Bitmap Information Header (size: %s)", pSize));
}
}
protected abstract void read(int size, DataInput stream) throws IOException;
protected abstract void write(final DataOutput stream) throws IOException;
protected abstract void read(int pSize, DataInput pStream) throws IOException;
public final int getSize() {
return size;
@@ -189,12 +189,12 @@ abstract class DIBHeader {
);
}
private static int[] readMasks(final DataInput stream, final boolean hasAlphaMask) throws IOException {
private static int[] readMasks(final DataInput pStream, final boolean hasAlphaMask) throws IOException {
int maskCount = hasAlphaMask ? 4 : 3;
int[] masks = new int[4];
for (int i = 0; i < maskCount; i++) {
masks[i] = stream.readInt();
masks[i] = pStream.readInt();
}
return masks;
@@ -205,30 +205,24 @@ abstract class DIBHeader {
// TODO: Get rid of code duplication below...
static final class BitmapCoreHeader extends DIBHeader {
@Override
protected void read(final int size, final DataInput stream) throws IOException {
if (size != DIB.BITMAP_CORE_HEADER_SIZE) {
throw new IIOException(String.format("Size: %s !=: %s", size, DIB.BITMAP_CORE_HEADER_SIZE));
protected void read(final int pSize, final DataInput pStream) throws IOException {
if (pSize != DIB.BITMAP_CORE_HEADER_SIZE) {
throw new IIOException(String.format("Size: %s !=: %s", pSize, DIB.BITMAP_CORE_HEADER_SIZE));
}
this.size = size;
size = pSize;
// NOTE: Unlike all other headers, width and height are unsigned SHORT values (16 bit)!
width = stream.readUnsignedShort();
height = stream.readShort();
width = pStream.readUnsignedShort();
height = pStream.readShort();
if (height < 0) {
height = -height;
topDown = true;
}
planes = stream.readUnsignedShort();
bitCount = stream.readUnsignedShort();
}
@Override
protected void write(DataOutput stream) {
throw new UnsupportedOperationException();
planes = pStream.readUnsignedShort();
bitCount = pStream.readUnsignedShort();
}
public String getBMPVersion() {
@@ -248,51 +242,45 @@ abstract class DIBHeader {
*/
static final class BitmapCoreHeaderV2 extends DIBHeader {
@SuppressWarnings("unused")
@Override
protected void read(final int size, final DataInput stream) throws IOException {
if (size != DIB.OS2_V2_HEADER_SIZE && size != DIB.OS2_V2_HEADER_16_SIZE) {
throw new IIOException(String.format("Size: %s !=: %s", size, DIB.OS2_V2_HEADER_SIZE));
protected void read(final int pSize, final DataInput pStream) throws IOException {
if (pSize != DIB.OS2_V2_HEADER_SIZE && pSize != DIB.OS2_V2_HEADER_16_SIZE) {
throw new IIOException(String.format("Size: %s !=: %s", pSize, DIB.OS2_V2_HEADER_SIZE));
}
this.size = size;
size = pSize;
width = stream.readInt();
height = stream.readInt();
width = pStream.readInt();
height = pStream.readInt();
if (height < 0) {
height = -height;
topDown = true;
}
planes = stream.readUnsignedShort();
bitCount = stream.readUnsignedShort();
planes = pStream.readUnsignedShort();
bitCount = pStream.readUnsignedShort();
if (size != DIB.OS2_V2_HEADER_16_SIZE) {
compression = stream.readInt();
if (pSize != DIB.OS2_V2_HEADER_16_SIZE) {
compression = pStream.readInt();
imageSize = stream.readInt();
imageSize = pStream.readInt();
xPixelsPerMeter = stream.readInt();
yPixelsPerMeter = stream.readInt();
xPixelsPerMeter = pStream.readInt();
yPixelsPerMeter = pStream.readInt();
colorsUsed = stream.readInt();
colorsImportant = stream.readInt();
colorsUsed = pStream.readInt();
colorsImportant = pStream.readInt();
}
// TODO: Use? These fields are not reflected in metadata as per now...
int units = stream.readShort();
int reserved = stream.readShort();
int recording = stream.readShort(); // Recording algorithm
int rendering = stream.readShort(); // Halftoning algorithm
int size1 = stream.readInt(); // Reserved for halftoning use
int size2 = stream.readInt(); // Reserved for halftoning use
int colorEncoding = stream.readInt(); // Color model used in bitmap
int identifier = stream.readInt(); // Reserved for application use
}
@Override
protected void write(DataOutput stream) {
throw new UnsupportedOperationException();
int units = pStream.readShort();
int reserved = pStream.readShort();
int recording = pStream.readShort(); // Recording algorithm
int rendering = pStream.readShort(); // Halftoning algorithm
int size1 = pStream.readInt(); // Reserved for halftoning use
int size2 = pStream.readInt(); // Reserved for halftoning use
int colorEncoding = pStream.readInt(); // Color model used in bitmap
int identifier = pStream.readInt(); // Reserved for application use
}
public String getBMPVersion() {
@@ -300,6 +288,7 @@ abstract class DIBHeader {
}
}
/**
* Represents the DIB (Device Independent Bitmap) Windows 3.0 Bitmap Information header structure.
* This is the common format for persistent DIB structures, even if Windows
@@ -315,46 +304,44 @@ abstract class DIBHeader {
* @see <a href="https://forums.adobe.com/message/3272950#3272950">BITMAPV3INFOHEADER</a>.
*/
static final class BitmapInfoHeader extends DIBHeader {
@Override
protected void read(final int size, final DataInput stream) throws IOException {
if (!(size == DIB.BITMAP_INFO_HEADER_SIZE || size == DIB.BITMAP_V2_INFO_HEADER_SIZE || size == DIB.BITMAP_V3_INFO_HEADER_SIZE)) {
throw new IIOException(String.format("Size: %s !=: %s", size, DIB.BITMAP_INFO_HEADER_SIZE));
protected void read(final int pSize, final DataInput pStream) throws IOException {
if (!(pSize == DIB.BITMAP_INFO_HEADER_SIZE || pSize == DIB.BITMAP_V2_INFO_HEADER_SIZE || pSize == DIB.BITMAP_V3_INFO_HEADER_SIZE)) {
throw new IIOException(String.format("Size: %s !=: %s", pSize, DIB.BITMAP_INFO_HEADER_SIZE));
}
this.size = size;
size = pSize;
width = stream.readInt();
height = stream.readInt();
width = pStream.readInt();
height = pStream.readInt();
if (height < 0) {
height = -height;
topDown = true;
}
planes = stream.readUnsignedShort();
bitCount = stream.readUnsignedShort();
compression = stream.readInt();
planes = pStream.readUnsignedShort();
bitCount = pStream.readUnsignedShort();
compression = pStream.readInt();
imageSize = stream.readInt();
imageSize = pStream.readInt();
xPixelsPerMeter = stream.readInt();
yPixelsPerMeter = stream.readInt();
xPixelsPerMeter = pStream.readInt();
yPixelsPerMeter = pStream.readInt();
colorsUsed = stream.readInt();
colorsImportant = stream.readInt();
colorsUsed = pStream.readInt();
colorsImportant = pStream.readInt();
// Read masks if we have V2 or V3
// or if we have compression BITFIELDS or ALPHA_BITFIELDS
if (this.size == DIB.BITMAP_V2_INFO_HEADER_SIZE || compression == DIB.COMPRESSION_BITFIELDS) {
masks = readMasks(stream, false);
if (size == DIB.BITMAP_V2_INFO_HEADER_SIZE || compression == DIB.COMPRESSION_BITFIELDS) {
masks = readMasks(pStream, false);
}
else if (this.size == DIB.BITMAP_V3_INFO_HEADER_SIZE || compression == DIB.COMPRESSION_ALPHA_BITFIELDS) {
masks = readMasks(stream, true);
else if (size == DIB.BITMAP_V3_INFO_HEADER_SIZE || compression == DIB.COMPRESSION_ALPHA_BITFIELDS) {
masks = readMasks(pStream, true);
}
}
@Override
protected void write(final DataOutput stream) throws IOException {
void write(final DataOutput stream) throws IOException {
stream.writeInt(DIB.BITMAP_INFO_HEADER_SIZE);
stream.writeInt(width);
@@ -372,7 +359,7 @@ abstract class DIBHeader {
stream.writeInt(colorsUsed);
stream.writeInt(colorsImportant);
// TODO: Write masks, if COMPRESSION_BITFIELDS/COMPRESSION_ALPHA_BITFIELDS
// TODO: Write masks, if bitfields
}
public String getBMPVersion() {
@@ -389,160 +376,105 @@ abstract class DIBHeader {
* Represents the BITMAPV4INFOHEADER structure.
*/
static final class BitmapV4InfoHeader extends DIBHeader {
@Override
protected void read(final int size, final DataInput stream) throws IOException {
if (size != DIB.BITMAP_V4_INFO_HEADER_SIZE) {
throw new IIOException(String.format("Size: %s !=: %s", size, DIB.BITMAP_V4_INFO_HEADER_SIZE));
protected void read(final int pSize, final DataInput pStream) throws IOException {
if (pSize != DIB.BITMAP_V4_INFO_HEADER_SIZE) {
throw new IIOException(String.format("Size: %s !=: %s", pSize, DIB.BITMAP_V4_INFO_HEADER_SIZE));
}
this.size = size;
size = pSize;
width = stream.readInt();
height = stream.readInt();
width = pStream.readInt();
height = pStream.readInt();
if (height < 0) {
height = -height;
topDown = true;
}
planes = stream.readUnsignedShort();
bitCount = stream.readUnsignedShort();
compression = stream.readInt();
planes = pStream.readUnsignedShort();
bitCount = pStream.readUnsignedShort();
compression = pStream.readInt();
imageSize = stream.readInt();
imageSize = pStream.readInt();
xPixelsPerMeter = stream.readInt();
yPixelsPerMeter = stream.readInt();
xPixelsPerMeter = pStream.readInt();
yPixelsPerMeter = pStream.readInt();
colorsUsed = stream.readInt();
colorsImportant = stream.readInt();
colorsUsed = pStream.readInt();
colorsImportant = pStream.readInt();
masks = readMasks(stream, true);
masks = readMasks(pStream, true);
colorSpaceType = stream.readInt(); // Should be 0 for V4
colorSpaceType = pStream.readInt(); // Should be 0 for V4
cieXYZEndpoints = new double[9];
for (int i = 0; i < cieXYZEndpoints.length; i++) {
cieXYZEndpoints[i] = stream.readInt(); // TODO: Hmmm...?
cieXYZEndpoints[i] = pStream.readInt(); // TODO: Hmmm...?
}
gamma = new int[3];
for (int i = 0; i < gamma.length; i++) {
gamma[i] = stream.readInt();
gamma[i] = pStream.readInt();
}
}
public String getBMPVersion() {
return "BMP v. 4.x";
}
@Override
protected void write(DataOutput stream) throws IOException {
stream.writeInt(DIB.BITMAP_V4_INFO_HEADER_SIZE);
stream.writeInt(width);
stream.writeInt(topDown ? -height : height);
stream.writeShort(planes);
stream.writeShort(bitCount);
stream.writeInt(compression);
stream.writeInt(imageSize);
stream.writeInt(xPixelsPerMeter);
stream.writeInt(yPixelsPerMeter);
stream.writeInt(colorsUsed);
stream.writeInt(colorsImportant);
// Red, Green, Blue, Alpha masks
stream.writeInt(masks[0]);
stream.writeInt(masks[1]);
stream.writeInt(masks[2]);
stream.writeInt(masks[3]);
// color space ("sRGB" LITTLE endian)
stream.writeInt(DIB.LCS_sRGB);
// 36 bytes CIE XYZ triples, unused for sRGB
stream.writeInt(0);
stream.writeInt(0);
stream.writeInt(0);
stream.writeInt(0);
stream.writeInt(0);
stream.writeInt(0);
stream.writeInt(0);
stream.writeInt(0);
stream.writeInt(0);
// Red gamma, unused for sRGB
// Green gamma, unused for sRGB
// Blue gamma, unused for sRGB
stream.writeInt(0);
stream.writeInt(0);
stream.writeInt(0);
}
}
/**
* Represents the BITMAPV5INFOHEADER structure.
*/
static final class BitmapV5InfoHeader extends DIBHeader {
protected void read(final int size, final DataInput stream) throws IOException {
if (size != DIB.BITMAP_V5_INFO_HEADER_SIZE) {
throw new IIOException(String.format("Size: %s !=: %s", size, DIB.BITMAP_V5_INFO_HEADER_SIZE));
protected void read(final int pSize, final DataInput pStream) throws IOException {
if (pSize != DIB.BITMAP_V5_INFO_HEADER_SIZE) {
throw new IIOException(String.format("Size: %s !=: %s", pSize, DIB.BITMAP_V5_INFO_HEADER_SIZE));
}
this.size = size;
size = pSize;
width = stream.readInt();
height = stream.readInt();
width = pStream.readInt();
height = pStream.readInt();
if (height < 0) {
height = -height;
topDown = true;
}
planes = stream.readUnsignedShort();
bitCount = stream.readUnsignedShort();
compression = stream.readInt();
planes = pStream.readUnsignedShort();
bitCount = pStream.readUnsignedShort();
compression = pStream.readInt();
imageSize = stream.readInt();
imageSize = pStream.readInt();
xPixelsPerMeter = stream.readInt();
yPixelsPerMeter = stream.readInt();
xPixelsPerMeter = pStream.readInt();
yPixelsPerMeter = pStream.readInt();
colorsUsed = stream.readInt();
colorsImportant = stream.readInt();
colorsUsed = pStream.readInt();
colorsImportant = pStream.readInt();
masks = readMasks(stream, true);
masks = readMasks(pStream, true);
colorSpaceType = stream.readInt();
colorSpaceType = pStream.readInt();
cieXYZEndpoints = new double[9];
for (int i = 0; i < cieXYZEndpoints.length; i++) {
cieXYZEndpoints[i] = stream.readInt(); // TODO: Hmmm...?
cieXYZEndpoints[i] = pStream.readInt(); // TODO: Hmmm...?
}
gamma = new int[3];
for (int i = 0; i < gamma.length; i++) {
gamma[i] = stream.readInt();
gamma[i] = pStream.readInt();
}
intent = stream.readInt(); // TODO: Verify if this is same as ICC intent
profileData = stream.readInt() & 0xffffffffL;
profileSize = stream.readInt() & 0xffffffffL;
stream.readInt(); // Reserved
}
@Override
protected void write(DataOutput stream) {
throw new UnsupportedOperationException();
intent = pStream.readInt(); // TODO: Verify if this is same as ICC intent
profileData = pStream.readInt() & 0xffffffffL;
profileSize = pStream.readInt() & 0xffffffffL;
pStream.readInt(); // Reserved
}
public String getBMPVersion() {
@@ -30,23 +30,10 @@
package com.twelvemonkeys.imageio.plugins.bmp;
import com.twelvemonkeys.image.ImageUtil;
import com.twelvemonkeys.imageio.ImageReaderBase;
import com.twelvemonkeys.imageio.stream.SubImageInputStream;
import com.twelvemonkeys.imageio.util.ImageTypeSpecifiers;
import com.twelvemonkeys.util.WeakWeakMap;
import javax.imageio.IIOException;
import javax.imageio.ImageIO;
import javax.imageio.ImageReadParam;
import javax.imageio.ImageReader;
import javax.imageio.ImageTypeSpecifier;
import javax.imageio.spi.ImageReaderSpi;
import javax.imageio.stream.ImageInputStream;
import javax.swing.*;
import java.awt.*;
import java.awt.color.*;
import java.awt.event.*;
import java.awt.color.ColorSpace;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.image.*;
import java.io.File;
import java.io.IOException;
@@ -57,6 +44,21 @@ import java.util.List;
import java.util.Map;
import java.util.WeakHashMap;
import javax.imageio.IIOException;
import javax.imageio.ImageIO;
import javax.imageio.ImageReadParam;
import javax.imageio.ImageReader;
import javax.imageio.ImageTypeSpecifier;
import javax.imageio.spi.ImageReaderSpi;
import javax.imageio.stream.ImageInputStream;
import javax.swing.*;
import com.twelvemonkeys.image.ImageUtil;
import com.twelvemonkeys.imageio.ImageReaderBase;
import com.twelvemonkeys.imageio.stream.SubImageInputStream;
import com.twelvemonkeys.imageio.util.ImageTypeSpecifiers;
import com.twelvemonkeys.util.WeakWeakMap;
/**
* ImageReader for Microsoft Windows ICO (icon) format.
* 1, 4, 8 bit palette support with bitmask transparency, and 16, 24 and 32 bit
@@ -79,13 +81,13 @@ abstract class DIBImageReader extends ImageReaderBase {
private Directory directory;
// TODO: Review these, make sure we don't have a memory leak
private final Map<DirectoryEntry, DIBHeader> headers = new WeakHashMap<>();
private final Map<DirectoryEntry, BitmapDescriptor> descriptors = new WeakWeakMap<>();
private Map<DirectoryEntry, DIBHeader> headers = new WeakHashMap<>();
private Map<DirectoryEntry, BitmapDescriptor> descriptors = new WeakWeakMap<>();
private ImageReader pngImageReader;
protected DIBImageReader(final ImageReaderSpi provider) {
super(provider);
protected DIBImageReader(final ImageReaderSpi pProvider) {
super(pProvider);
}
protected void resetMembers() {
@@ -100,8 +102,8 @@ abstract class DIBImageReader extends ImageReaderBase {
}
}
public Iterator<ImageTypeSpecifier> getImageTypes(final int imageIndex) throws IOException {
DirectoryEntry entry = getEntry(imageIndex);
public Iterator<ImageTypeSpecifier> getImageTypes(final int pImageIndex) throws IOException {
DirectoryEntry entry = getEntry(pImageIndex);
// NOTE: Delegate to PNG reader
if (isPNG(entry)) {
@@ -153,39 +155,39 @@ abstract class DIBImageReader extends ImageReaderBase {
return getDirectory().count();
}
public int getWidth(final int imageIndex) throws IOException {
return getEntry(imageIndex).getWidth();
public int getWidth(final int pImageIndex) throws IOException {
return getEntry(pImageIndex).getWidth();
}
public int getHeight(final int imageIndex) throws IOException {
return getEntry(imageIndex).getHeight();
public int getHeight(final int pImageIndex) throws IOException {
return getEntry(pImageIndex).getHeight();
}
public BufferedImage read(final int imageIndex, final ImageReadParam param) throws IOException {
checkBounds(imageIndex);
public BufferedImage read(final int pImageIndex, final ImageReadParam pParam) throws IOException {
checkBounds(pImageIndex);
processImageStarted(imageIndex);
processImageStarted(pImageIndex);
DirectoryEntry entry = getEntry(imageIndex);
DirectoryEntry entry = getEntry(pImageIndex);
BufferedImage destination;
if (isPNG(entry)) {
// NOTE: Special case for Windows Vista, 256x256 PNG encoded images, with no DIB header...
destination = readPNG(entry, param);
destination = readPNG(entry, pParam);
}
else {
// NOTE: If param does not have explicit destination, we'll try to create a BufferedImage later,
// to allow for storing the cursor hotspot for CUR images
destination = hasExplicitDestination(param) ?
getDestination(param, getImageTypes(imageIndex), getWidth(imageIndex), getHeight(imageIndex)) : null;
destination = hasExplicitDestination(pParam) ?
getDestination(pParam, getImageTypes(pImageIndex), getWidth(pImageIndex), getHeight(pImageIndex)) : null;
BufferedImage image = readBitmap(entry);
// TODO: Handle AOI and subsampling inline, probably not of big importance...
if (param != null) {
image = fakeAOI(image, param);
image = ImageUtil.toBuffered(fakeSubsampling(image, param));
if (pParam != null) {
image = fakeAOI(image, pParam);
image = ImageUtil.toBuffered(fakeSubsampling(image, pParam));
}
if (destination == null) {
@@ -211,10 +213,10 @@ abstract class DIBImageReader extends ImageReaderBase {
return destination;
}
private boolean isPNG(final DirectoryEntry entry) throws IOException {
private boolean isPNG(final DirectoryEntry pEntry) throws IOException {
long magic;
imageInput.seek(entry.getOffset());
imageInput.seek(pEntry.getOffset());
imageInput.setByteOrder(ByteOrder.BIG_ENDIAN);
try {
@@ -227,20 +229,22 @@ abstract class DIBImageReader extends ImageReaderBase {
return magic == DIB.PNG_MAGIC;
}
private BufferedImage readPNG(final DirectoryEntry entry, final ImageReadParam param) throws IOException {
private BufferedImage readPNG(final DirectoryEntry pEntry, final ImageReadParam pParam) throws IOException {
// TODO: Consider delegating listener calls
return initPNGReader(entry).read(0, param);
return initPNGReader(pEntry).read(0, pParam);
}
private Iterator<ImageTypeSpecifier> getImageTypesPNG(final DirectoryEntry entry) throws IOException {
return initPNGReader(entry).getImageTypes(0);
private Iterator<ImageTypeSpecifier> getImageTypesPNG(final DirectoryEntry pEntry) throws IOException {
return initPNGReader(pEntry).getImageTypes(0);
}
private ImageReader initPNGReader(final DirectoryEntry entry) throws IOException {
private ImageReader initPNGReader(final DirectoryEntry pEntry) throws IOException {
ImageReader pngReader = getPNGReader();
imageInput.seek(entry.getOffset());
ImageInputStream stream = new SubImageInputStream(imageInput, entry.getSize());
imageInput.seek(pEntry.getOffset());
// InputStream inputStream = IIOUtil.createStreamAdapter(imageInput, pEntry.getSize());
// ImageInputStream stream = ImageIO.createImageInputStream(inputStream);
ImageInputStream stream = new SubImageInputStream(imageInput, pEntry.getSize());
// NOTE: Will throw IOException on later reads if input is not PNG
pngReader.setInput(stream);
@@ -267,31 +271,31 @@ abstract class DIBImageReader extends ImageReaderBase {
return pngImageReader;
}
private DIBHeader getHeader(final DirectoryEntry entry) throws IOException {
if (!headers.containsKey(entry)) {
imageInput.seek(entry.getOffset());
private DIBHeader getHeader(final DirectoryEntry pEntry) throws IOException {
if (!headers.containsKey(pEntry)) {
imageInput.seek(pEntry.getOffset());
DIBHeader header = DIBHeader.read(imageInput);
headers.put(entry, header);
headers.put(pEntry, header);
}
return headers.get(entry);
return headers.get(pEntry);
}
private BufferedImage readBitmap(final DirectoryEntry entry) throws IOException {
private BufferedImage readBitmap(final DirectoryEntry pEntry) throws IOException {
// TODO: Get rid of the caching, as the images are mutable
BitmapDescriptor descriptor = descriptors.get(entry);
BitmapDescriptor descriptor = descriptors.get(pEntry);
if (descriptor == null || !descriptors.containsKey(entry)) {
DIBHeader header = getHeader(entry);
if (descriptor == null || !descriptors.containsKey(pEntry)) {
DIBHeader header = getHeader(pEntry);
int offset = entry.getOffset() + header.getSize();
int offset = pEntry.getOffset() + header.getSize();
if (offset != imageInput.getStreamPosition()) {
imageInput.seek(offset);
}
// TODO: Support this, it's already in the BMP reader, spec allows RLE4 and RLE8
if (header.getCompression() != DIB.COMPRESSION_RGB) {
descriptor = new BitmapUnsupported(entry, header, String.format("Unsupported compression: %d", header.getCompression()));
descriptor = new BitmapUnsupported(pEntry, header, String.format("Unsupported compression: %d", header.getCompression()));
}
else {
int bitCount = header.getBitCount();
@@ -301,75 +305,75 @@ abstract class DIBImageReader extends ImageReaderBase {
case 1:
case 4:
case 8: // TODO: Gray!
descriptor = new BitmapIndexed(entry, header);
descriptor = new BitmapIndexed(pEntry, header);
readBitmapIndexed((BitmapIndexed) descriptor);
break;
// RGB style
case 16:
descriptor = new BitmapRGB(entry, header);
descriptor = new BitmapRGB(pEntry, header);
readBitmap16(descriptor);
break;
case 24:
descriptor = new BitmapRGB(entry, header);
descriptor = new BitmapRGB(pEntry, header);
readBitmap24(descriptor);
break;
case 32:
descriptor = new BitmapRGB(entry, header);
descriptor = new BitmapRGB(pEntry, header);
readBitmap32(descriptor);
break;
default:
descriptor = new BitmapUnsupported(entry, header, String.format("Unsupported bit count %d", bitCount));
descriptor = new BitmapUnsupported(pEntry, header, String.format("Unsupported bit count %d", bitCount));
}
}
descriptors.put(entry, descriptor);
descriptors.put(pEntry, descriptor);
}
return descriptor.getImage();
}
private void readBitmapIndexed(final BitmapIndexed bitmap) throws IOException {
readColorMap(bitmap);
private void readBitmapIndexed(final BitmapIndexed pBitmap) throws IOException {
readColorMap(pBitmap);
switch (bitmap.getBitCount()) {
switch (pBitmap.getBitCount()) {
case 1:
readBitmapIndexed1(bitmap, false);
readBitmapIndexed1(pBitmap, false);
break;
case 4:
readBitmapIndexed4(bitmap);
readBitmapIndexed4(pBitmap);
break;
case 8:
readBitmapIndexed8(bitmap);
readBitmapIndexed8(pBitmap);
break;
}
BitmapMask mask = new BitmapMask(bitmap.entry, bitmap.header);
BitmapMask mask = new BitmapMask(pBitmap.entry, pBitmap.header);
readBitmapIndexed1(mask.bitMask, true);
bitmap.setMask(mask);
pBitmap.setMask(mask);
}
private void readColorMap(final BitmapIndexed bitmap) throws IOException {
int colorCount = bitmap.getColorCount();
private void readColorMap(final BitmapIndexed pBitmap) throws IOException {
int colorCount = pBitmap.getColorCount();
for (int i = 0; i < colorCount; i++) {
// aRGB (a is "Reserved")
bitmap.colors[i] = (imageInput.readInt() & 0xffffff) | 0xff000000;
pBitmap.colors[i] = (imageInput.readInt() & 0xffffff) | 0xff000000;
}
}
private void readBitmapIndexed1(final BitmapIndexed bitmap, final boolean asMask) throws IOException {
int width = adjustToPadding((bitmap.getWidth() + 7) >> 3);
private void readBitmapIndexed1(final BitmapIndexed pBitmap, final boolean pAsMask) throws IOException {
int width = adjustToPadding((pBitmap.getWidth() + 7) >> 3);
byte[] row = new byte[width];
for (int y = 0; y < bitmap.getHeight(); y++) {
for (int y = 0; y < pBitmap.getHeight(); y++) {
imageInput.readFully(row, 0, width);
int rowPos = 0;
int xOrVal = 0x80;
int pos = (bitmap.getHeight() - y - 1) * bitmap.getWidth();
int pos = (pBitmap.getHeight() - y - 1) * pBitmap.getWidth();
for (int x = 0; x < bitmap.getWidth(); x++) {
bitmap.bits[pos++] = ((row[rowPos] & xOrVal) / xOrVal) & 0xFF;
for (int x = 0; x < pBitmap.getWidth(); x++) {
pBitmap.bits[pos++] = ((row[rowPos] & xOrVal) / xOrVal) & 0xFF;
if (xOrVal == 1) {
xOrVal = 0x80;
@@ -380,29 +384,29 @@ abstract class DIBImageReader extends ImageReaderBase {
}
}
// NOTE: If we are reading the mask, we can't abort or report progress
if (!asMask) {
// NOTE: If we are reading the mask, we don't abort or report progress
if (!pAsMask) {
if (abortRequested()) {
processReadAborted();
break;
}
processImageProgress(100 * y / (float) bitmap.getHeight());
processImageProgress(100 * y / (float) pBitmap.getHeight());
}
}
}
private void readBitmapIndexed4(final BitmapIndexed bitmap) throws IOException {
int width = adjustToPadding((bitmap.getWidth() + 1) >> 1);
private void readBitmapIndexed4(final BitmapIndexed pBitmap) throws IOException {
int width = adjustToPadding((pBitmap.getWidth() + 1) >> 1);
byte[] row = new byte[width];
for (int y = 0; y < bitmap.getHeight(); y++) {
for (int y = 0; y < pBitmap.getHeight(); y++) {
imageInput.readFully(row, 0, width);
int rowPos = 0;
boolean high4 = true;
int pos = (bitmap.getHeight() - y - 1) * bitmap.getWidth();
int pos = (pBitmap.getHeight() - y - 1) * pBitmap.getWidth();
for (int x = 0; x < bitmap.getWidth(); x++) {
for (int x = 0; x < pBitmap.getWidth(); x++) {
int value;
if (high4) {
@@ -413,7 +417,7 @@ abstract class DIBImageReader extends ImageReaderBase {
rowPos++;
}
bitmap.bits[pos++] = value & 0xFF;
pBitmap.bits[pos++] = value & 0xFF;
high4 = !high4;
}
@@ -422,22 +426,22 @@ abstract class DIBImageReader extends ImageReaderBase {
break;
}
processImageProgress(100 * y / (float) bitmap.getHeight());
processImageProgress(100 * y / (float) pBitmap.getHeight());
}
}
private void readBitmapIndexed8(final BitmapIndexed bitmap) throws IOException {
int width = adjustToPadding(bitmap.getWidth());
private void readBitmapIndexed8(final BitmapIndexed pBitmap) throws IOException {
int width = adjustToPadding(pBitmap.getWidth());
byte[] row = new byte[width];
for (int y = 0; y < bitmap.getHeight(); y++) {
for (int y = 0; y < pBitmap.getHeight(); y++) {
imageInput.readFully(row, 0, width);
int rowPos = 0;
int pos = (bitmap.getHeight() - y - 1) * bitmap.getWidth();
int pos = (pBitmap.getHeight() - y - 1) * pBitmap.getWidth();
for (int x = 0; x < bitmap.getWidth(); x++) {
bitmap.bits[pos++] = row[rowPos++] & 0xFF;
for (int x = 0; x < pBitmap.getWidth(); x++) {
pBitmap.bits[pos++] = row[rowPos++] & 0xFF;
}
if (abortRequested()) {
@@ -445,41 +449,40 @@ abstract class DIBImageReader extends ImageReaderBase {
break;
}
processImageProgress(100 * y / (float) bitmap.getHeight());
processImageProgress(100 * y / (float) pBitmap.getHeight());
}
}
/**
* @param width Bytes per scan line (i.e., 1BPP, width = 9 -> bytes = 2)
* @param pWidth Bytes per scan line (i.e., 1BPP, width = 9 -> bytes = 1)
* @return padded width
*/
private static int adjustToPadding(final int width) {
if ((width & 0x03) != 0) {
return (width & ~0x03) + 4;
private static int adjustToPadding(final int pWidth) {
if ((pWidth & 0x03) != 0) {
return (pWidth & ~0x03) + 4;
}
return width;
return pWidth;
}
private void readBitmap16(final BitmapDescriptor bitmap) throws IOException {
short[] pixels = new short[bitmap.getWidth() * bitmap.getHeight()];
private void readBitmap16(final BitmapDescriptor pBitmap) throws IOException {
short[] pixels = new short[pBitmap.getWidth() * pBitmap.getHeight()];
// TODO: Support TYPE_USHORT_565 and the RGB 444/ARGB 4444 layouts
// Will create TYPE_USHORT_555
DirectColorModel cm = new DirectColorModel(16, 0x7C00, 0x03E0, 0x001F);
DataBuffer buffer = new DataBufferUShort(pixels, pixels.length);
WritableRaster raster = Raster.createPackedRaster(
buffer, bitmap.getWidth(), bitmap.getHeight(), bitmap.getWidth(), cm.getMasks(), null
buffer, pBitmap.getWidth(), pBitmap.getHeight(), pBitmap.getWidth(), cm.getMasks(), null
);
bitmap.image = new BufferedImage(cm, raster, cm.isAlphaPremultiplied(), null);
pBitmap.image = new BufferedImage(cm, raster, cm.isAlphaPremultiplied(), null);
for (int y = 0; y < bitmap.getHeight(); y++) {
int offset = (bitmap.getHeight() - y - 1) * bitmap.getWidth();
imageInput.readFully(pixels, offset, bitmap.getWidth());
for (int y = 0; y < pBitmap.getHeight(); y++) {
int offset = (pBitmap.getHeight() - y - 1) * pBitmap.getWidth();
imageInput.readFully(pixels, offset, pBitmap.getWidth());
// Skip to 32 bit boundary
if (bitmap.getWidth() % 2 != 0) {
if (pBitmap.getWidth() % 2 != 0) {
imageInput.readShort();
}
@@ -488,14 +491,14 @@ abstract class DIBImageReader extends ImageReaderBase {
break;
}
processImageProgress(100 * y / (float) bitmap.getHeight());
processImageProgress(100 * y / (float) pBitmap.getHeight());
}
// TODO: Might be mask!?
}
private void readBitmap24(final BitmapDescriptor bitmap) throws IOException {
byte[] pixels = new byte[bitmap.getWidth() * bitmap.getHeight() * 3];
private void readBitmap24(final BitmapDescriptor pBitmap) throws IOException {
byte[] pixels = new byte[pBitmap.getWidth() * pBitmap.getHeight() * 3];
// Create TYPE_3BYTE_BGR
DataBuffer buffer = new DataBufferByte(pixels, pixels.length);
@@ -506,17 +509,17 @@ abstract class DIBImageReader extends ImageReaderBase {
cs, nBits, false, false, Transparency.OPAQUE, DataBuffer.TYPE_BYTE
);
int scanlineStride = bitmap.getWidth() * 3;
int scanlineStride = pBitmap.getWidth() * 3;
// BMP rows are padded to 4 byte boundary
int rowSizeBytes = ((8 * scanlineStride + 31) / 32) * 4;
WritableRaster raster = Raster.createInterleavedRaster(
buffer, bitmap.getWidth(), bitmap.getHeight(), scanlineStride, 3, bOffs, null
buffer, pBitmap.getWidth(), pBitmap.getHeight(), scanlineStride, 3, bOffs, null
);
bitmap.image = new BufferedImage(cm, raster, cm.isAlphaPremultiplied(), null);
pBitmap.image = new BufferedImage(cm, raster, cm.isAlphaPremultiplied(), null);
for (int y = 0; y < bitmap.getHeight(); y++) {
int offset = (bitmap.getHeight() - y - 1) * scanlineStride;
for (int y = 0; y < pBitmap.getHeight(); y++) {
int offset = (pBitmap.getHeight() - y - 1) * scanlineStride;
imageInput.readFully(pixels, offset, scanlineStride);
imageInput.skipBytes(rowSizeBytes - scanlineStride);
@@ -525,38 +528,38 @@ abstract class DIBImageReader extends ImageReaderBase {
break;
}
processImageProgress(100 * y / (float) bitmap.getHeight());
processImageProgress(100 * y / (float) pBitmap.getHeight());
}
// 24 bit icons usually have a bit mask
if (bitmap.hasMask()) {
BitmapMask mask = new BitmapMask(bitmap.entry, bitmap.header);
if (pBitmap.hasMask()) {
BitmapMask mask = new BitmapMask(pBitmap.entry, pBitmap.header);
readBitmapIndexed1(mask.bitMask, true);
bitmap.setMask(mask);
pBitmap.setMask(mask);
}
}
private void readBitmap32(final BitmapDescriptor bitmap) throws IOException {
int[] pixels = new int[bitmap.getWidth() * bitmap.getHeight()];
private void readBitmap32(final BitmapDescriptor pBitmap) throws IOException {
int[] pixels = new int[pBitmap.getWidth() * pBitmap.getHeight()];
// Will create TYPE_INT_ARGB
DirectColorModel cm = (DirectColorModel) ColorModel.getRGBdefault();
DataBuffer buffer = new DataBufferInt(pixels, pixels.length);
WritableRaster raster = Raster.createPackedRaster(
buffer, bitmap.getWidth(), bitmap.getHeight(), bitmap.getWidth(), cm.getMasks(), null
buffer, pBitmap.getWidth(), pBitmap.getHeight(), pBitmap.getWidth(), cm.getMasks(), null
);
bitmap.image = new BufferedImage(cm, raster, cm.isAlphaPremultiplied(), null);
pBitmap.image = new BufferedImage(cm, raster, cm.isAlphaPremultiplied(), null);
for (int y = 0; y < bitmap.getHeight(); y++) {
int offset = (bitmap.getHeight() - y - 1) * bitmap.getWidth();
imageInput.readFully(pixels, offset, bitmap.getWidth());
for (int y = 0; y < pBitmap.getHeight(); y++) {
int offset = (pBitmap.getHeight() - y - 1) * pBitmap.getWidth();
imageInput.readFully(pixels, offset, pBitmap.getWidth());
if (abortRequested()) {
processReadAborted();
break;
}
processImageProgress(100 * y / (float) bitmap.getHeight());
processImageProgress(100 * y / (float) pBitmap.getHeight());
}
// There might be a mask here as well, but we'll ignore it,
@@ -587,18 +590,18 @@ abstract class DIBImageReader extends ImageReaderBase {
directory = Directory.read(type, imageCount, imageInput);
}
final DirectoryEntry getEntry(final int imageIndex) throws IOException {
final DirectoryEntry getEntry(final int pImageIndex) throws IOException {
Directory directory = getDirectory();
if (imageIndex < 0 || imageIndex >= directory.count()) {
throw new IndexOutOfBoundsException(String.format("Index: %d, ImageCount: %d", imageIndex, directory.count()));
if (pImageIndex < 0 || pImageIndex >= directory.count()) {
throw new IndexOutOfBoundsException(String.format("Index: %d, ImageCount: %d", pImageIndex, directory.count()));
}
return directory.getEntry(imageIndex);
return directory.getEntry(pImageIndex);
}
/// Test code below, ignore.. :-)
public static void main(final String[] args) throws IOException {
if (args.length == 0) {
public static void main(final String[] pArgs) throws IOException {
if (pArgs.length == 0) {
System.err.println("Please specify the icon file name");
System.exit(1);
}
@@ -610,7 +613,7 @@ abstract class DIBImageReader extends ImageReaderBase {
// Ignore
}
String title = new File(args[0]).getName();
String title = new File(pArgs[0]).getName();
JFrame frame = createWindow(title);
JPanel root = new JPanel(new FlowLayout());
JScrollPane scroll =
@@ -626,7 +629,7 @@ abstract class DIBImageReader extends ImageReaderBase {
ImageReader reader = readers.next();
for (String arg : args) {
for (String arg : pArgs) {
JPanel panel = new JPanel(null);
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
readImagesInFile(arg, reader, panel);
@@ -637,28 +640,28 @@ abstract class DIBImageReader extends ImageReaderBase {
frame.setVisible(true);
}
private static void readImagesInFile(String fileName, ImageReader reader, final Container container) throws IOException {
File file = new File(fileName);
private static void readImagesInFile(String pFileName, ImageReader pReader, final Container pContainer) throws IOException {
File file = new File(pFileName);
if (!file.isFile()) {
System.err.println(fileName + " not found, or is no file");
System.err.println(pFileName + " not found, or is no file");
}
reader.setInput(ImageIO.createImageInputStream(file));
int imageCount = reader.getNumImages(true);
pReader.setInput(ImageIO.createImageInputStream(file));
int imageCount = pReader.getNumImages(true);
for (int i = 0; i < imageCount; i++) {
try {
addImage(container, reader, i);
addImage(pContainer, pReader, i);
}
catch (Exception e) {
System.err.println("FileName: " + fileName);
System.err.println("FileName: " + pFileName);
System.err.println("Icon: " + i);
e.printStackTrace();
}
}
}
private static JFrame createWindow(final String title) {
JFrame frame = new JFrame(title);
private static JFrame createWindow(final String pTitle) {
JFrame frame = new JFrame(pTitle);
frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
frame.addWindowListener(new WindowAdapter() {
public void windowClosed(WindowEvent e) {
@@ -668,15 +671,15 @@ abstract class DIBImageReader extends ImageReaderBase {
return frame;
}
private static void addImage(final Container parent, final ImageReader reader, final int imageNo) throws IOException {
private static void addImage(final Container pParent, final ImageReader pReader, final int pImageNo) throws IOException {
final JButton button = new JButton();
BufferedImage image = reader.read(imageNo);
BufferedImage image = pReader.read(pImageNo);
button.setIcon(new ImageIcon(image) {
TexturePaint texture;
private void createTexture(final GraphicsConfiguration graphicsConfiguration) {
BufferedImage pattern = graphicsConfiguration.createCompatibleImage(20, 20);
private void createTexture(final GraphicsConfiguration pGraphicsConfiguration) {
BufferedImage pattern = pGraphicsConfiguration.createCompatibleImage(20, 20);
Graphics2D g = pattern.createGraphics();
try {
g.setColor(Color.LIGHT_GRAY);
@@ -711,6 +714,6 @@ abstract class DIBImageReader extends ImageReaderBase {
String.valueOf(((IndexColorModel) image.getColorModel()).getMapSize()) :
"TrueColor"));
parent.add(button);
pParent.add(button);
}
}
@@ -44,25 +44,24 @@ import java.util.List;
class Directory {
private final List<DirectoryEntry> entries;
private Directory(int imageCount) {
entries = Arrays.asList(new DirectoryEntry[imageCount]);
private Directory(int pImageCount) {
entries = Arrays.asList(new DirectoryEntry[pImageCount]);
}
public static Directory read(final int type, final int imageCount, final DataInput stream) throws IOException {
Directory directory = new Directory(imageCount);
directory.readEntries(type, stream);
public static Directory read(final int pType, final int pImageCount, final DataInput pStream) throws IOException {
Directory directory = new Directory(pImageCount);
directory.readEntries(pType, pStream);
return directory;
}
private void readEntries(final int type, final DataInput stream) throws IOException {
private void readEntries(final int pType, final DataInput pStream) throws IOException {
for (int i = 0; i < entries.size(); i++) {
entries.set(i, DirectoryEntry.read(type, stream));
entries.set(i, DirectoryEntry.read(pType, pStream));
}
}
public DirectoryEntry getEntry(final int entryIndex) {
return entries.get(entryIndex);
public DirectoryEntry getEntry(final int pEntryIndex) {
return entries.get(pEntryIndex);
}
public int count() {
@@ -32,7 +32,8 @@ package com.twelvemonkeys.imageio.plugins.bmp;
import javax.imageio.IIOException;
import java.awt.*;
import java.awt.image.*;
import java.awt.image.ColorModel;
import java.awt.image.IndexColorModel;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
@@ -57,43 +58,47 @@ abstract class DirectoryEntry {
DirectoryEntry() {
}
public static DirectoryEntry read(final int type, final DataInput stream) throws IOException {
DirectoryEntry entry = createEntry(type);
entry.read(stream);
public static DirectoryEntry read(final int pType, final DataInput pStream) throws IOException {
DirectoryEntry entry = createEntry(pType);
entry.read(pStream);
return entry;
}
private static DirectoryEntry createEntry(int type) throws IIOException {
switch (type) {
private static DirectoryEntry createEntry(int pType) throws IIOException {
switch (pType) {
case DIB.TYPE_ICO:
return new ICOEntry();
case DIB.TYPE_CUR:
return new CUREntry();
default:
throw new IIOException(String.format("Unknown DIB type: %s, expected: %s (ICO) or %s (CUR)", type, DIB.TYPE_ICO, DIB.TYPE_CUR));
throw new IIOException(
String.format(
"Unknown DIB type: %s, expected: %s (ICO) or %s (CUR)",
pType, DIB.TYPE_ICO, DIB.TYPE_CUR
)
);
}
}
protected void read(final DataInput stream) throws IOException {
protected void read(final DataInput pStream) throws IOException {
// Width/height = 0, means 256
int w = stream.readUnsignedByte();
int w = pStream.readUnsignedByte();
width = w == 0 ? 256 : w;
int h = stream.readUnsignedByte();
int h = pStream.readUnsignedByte();
height = h == 0 ? 256 : h;
// Color count = 0, means 256 or more colors
colorCount = stream.readUnsignedByte();
colorCount = pStream.readUnsignedByte();
// Ignore. Should be 0, but .NET (System.Drawing.Icon.Save) sets this value to 255, according to Wikipedia
stream.readUnsignedByte();
pStream.readUnsignedByte();
planes = stream.readUnsignedShort(); // Should be 0 or 1 for ICO, x hotspot for CUR
bitCount = stream.readUnsignedShort(); // bit count for ICO, y hotspot for CUR
planes = pStream.readUnsignedShort(); // Should be 0 or 1 for ICO, x hotspot for CUR
bitCount = pStream.readUnsignedShort(); // bit count for ICO, y hotspot for CUR
// Size of bitmap in bytes
size = stream.readInt();
offset = stream.readInt();
size = pStream.readInt();
offset = pStream.readInt();
}
void write(final DataOutput output) throws IOException {
@@ -152,8 +157,8 @@ abstract class DirectoryEntry {
private int yHotspot;
@Override
protected void read(final DataInput stream) throws IOException {
super.read(stream);
protected void read(final DataInput pStream) throws IOException {
super.read(pStream);
// NOTE: This is a hack...
xHotspot = planes;
@@ -46,7 +46,7 @@ public final class ICOImageReader extends DIBImageReader {
super(new ICOImageReaderSpi());
}
ICOImageReader(final ImageReaderSpi provider) {
super(provider);
protected ICOImageReader(final ImageReaderSpi pProvider) {
super(pProvider);
}
}
@@ -32,6 +32,7 @@ package com.twelvemonkeys.imageio.plugins.bmp;
import com.twelvemonkeys.imageio.spi.ImageReaderSpiBase;
import javax.imageio.ImageReader;
import javax.imageio.stream.ImageInputStream;
import java.io.IOException;
import java.util.Locale;
@@ -48,32 +49,32 @@ public final class ICOImageReaderSpi extends ImageReaderSpiBase {
super(new ICOProviderInfo());
}
public boolean canDecodeInput(final Object source) throws IOException {
return source instanceof ImageInputStream && canDecode((ImageInputStream) source, DIB.TYPE_ICO);
public boolean canDecodeInput(final Object pSource) throws IOException {
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];
try {
input.mark();
input.readFully(signature);
pInput.mark();
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);
}
finally {
input.reset();
pInput.reset();
}
}
public ICOImageReader createReaderInstance(final Object extension) {
public ImageReader createReaderInstance(final Object pExtension) throws IOException {
return new ICOImageReader(this);
}
public String getDescription(final Locale locale) {
public String getDescription(final Locale pLocale) {
return "Windows Icon Format (ICO) Reader";
}
}
@@ -33,19 +33,15 @@ package com.twelvemonkeys.imageio.plugins.bmp;
import com.twelvemonkeys.imageio.stream.SubImageOutputStream;
import com.twelvemonkeys.imageio.util.ProgressListenerBase;
import javax.imageio.IIOException;
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.*;
import javax.imageio.event.IIOWriteWarningListener;
import javax.imageio.metadata.IIOMetadata;
import javax.imageio.spi.ImageWriterSpi;
import javax.imageio.stream.ImageInputStream;
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.IOException;
import java.util.Iterator;
@@ -68,7 +64,7 @@ public final class ICOImageWriter extends DIBImageWriter {
private ImageWriter pngDelegate;
ICOImageWriter(final ImageWriterSpi provider) {
protected ICOImageWriter(final ImageWriterSpi provider) {
super(provider);
}
@@ -128,7 +124,7 @@ public final class ICOImageWriter extends DIBImageWriter {
}
@Override
public void endWriteSequence() {
public void endWriteSequence() throws IOException {
assertOutput();
if (sequenceIndex < 0) {
@@ -30,14 +30,24 @@
package com.twelvemonkeys.imageio.plugins.bmp;
import com.twelvemonkeys.imageio.util.ImageReaderAbstractTest;
import com.twelvemonkeys.xml.XMLSerializer;
import static org.junit.Assert.*;
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 org.junit.Test;
import org.mockito.InOrder;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
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.ImageIO;
@@ -47,25 +57,16 @@ import javax.imageio.ImageTypeSpecifier;
import javax.imageio.event.IIOReadProgressListener;
import javax.imageio.metadata.IIOMetadata;
import javax.imageio.metadata.IIOMetadataNode;
import javax.imageio.spi.IIORegistry;
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 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 org.junit.Test;
import org.mockito.InOrder;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import com.twelvemonkeys.imageio.util.ImageReaderAbstractTest;
import com.twelvemonkeys.xml.XMLSerializer;
/**
* BMPImageReaderTest
@@ -325,8 +326,10 @@ public class BMPImageReaderTest extends ImageReaderAbstractTest<BMPImageReader>
public void testMetadataEqualsJRE() throws IOException {
ImageReader jreReader;
try {
ImageReaderSpi provider = (ImageReaderSpi) IIORegistry.getDefaultInstance().getServiceProviderByClass(Class.forName("com.sun.imageio.plugins.bmp.BMPImageReaderSpi"));
jreReader = provider.createReaderInstance();
@SuppressWarnings("unchecked")
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) {
e.printStackTrace();
+1 -10
View File
@@ -4,7 +4,7 @@
<parent>
<groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio</artifactId>
<version>3.11.1-SNAPSHOT</version>
<version>3.9.1</version>
</parent>
<artifactId>imageio-clippath</artifactId>
<name>TwelveMonkeys :: ImageIO :: Photoshop Path Support</name>
@@ -32,13 +32,4 @@
<artifactId>imageio-metadata</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
@@ -42,7 +42,6 @@ import com.twelvemonkeys.imageio.metadata.tiff.TIFF;
import com.twelvemonkeys.imageio.metadata.tiff.TIFFReader;
import com.twelvemonkeys.imageio.stream.ByteArrayImageInputStream;
import com.twelvemonkeys.imageio.stream.SubImageInputStream;
import com.twelvemonkeys.imageio.util.ImageTypeSpecifiers;
import javax.imageio.*;
import javax.imageio.metadata.IIOMetadata;
@@ -308,7 +307,7 @@ public final class Paths {
throw new IllegalArgumentException("output == null!");
}
ImageTypeSpecifier type = ImageTypeSpecifiers.createFromRenderedImage(image);
ImageTypeSpecifier type = ImageTypeSpecifier.createFromRenderedImage(image);
Iterator<ImageWriter> writers = ImageIO.getImageWriters(type, formatName);
if (writers.hasNext()) {
+1 -20
View File
@@ -4,13 +4,10 @@
<parent>
<groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio</artifactId>
<version>3.11.1-SNAPSHOT</version>
<version>3.9.1</version>
</parent>
<artifactId>imageio-core</artifactId>
<name>TwelveMonkeys :: ImageIO :: Core</name>
<description>
TwelveMonkeys ImageIO core support classes.
</description>
<properties>
<project.jpms.module.name>com.twelvemonkeys.imageio.core</project.jpms.module.name>
@@ -31,20 +28,4 @@
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<configuration>
<instructions>
<Provide-Capability>
osgi.serviceloader;
osgi.serviceloader=javax.imageio.spi.ImageInputStreamSpi
</Provide-Capability>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
</project>
@@ -188,7 +188,7 @@ public final class ColorSpaces {
// Will throw IllegalArgumentException or CMMException if the profile is bad
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
cs.getProfile().getData();
}
@@ -17,12 +17,8 @@ final class MemoryCache implements Cache {
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 ReadableByteChannel channel;
private int maxBlock = Integer.MAX_VALUE;
private long length;
private long position;
private long start;
@@ -38,14 +34,12 @@ final class MemoryCache implements Cache {
byte[] fetchBlock() throws IOException {
long currPos = position;
long index = currPos / BLOCK_SIZE;
if (index >= Integer.MAX_VALUE) {
throw new IOException("Memory cache max size exceeded");
}
if (index > maxBlock) {
return NULL_BLOCK;
}
while (index >= cache.size()) {
byte[] block;
@@ -57,14 +51,7 @@ final class MemoryCache implements Cache {
}
cache.add(block);
int bytesRead = readBlock(block);
length += bytesRead;
if (bytesRead < BLOCK_SIZE) {
// Last block, EOF found
maxBlock = (int) index;
return block;
}
length += readBlock(block);
}
return cache.get((int) index);
@@ -76,7 +63,7 @@ final class MemoryCache implements Cache {
while (wrapped.hasRemaining()) {
int count = channel.read(wrapped);
if (count == -1) {
// Last block, EOF found
// Last block
break;
}
}
@@ -97,12 +84,12 @@ final class MemoryCache implements Cache {
@Override
public int read(ByteBuffer dest) throws IOException {
byte[] buffer = fetchBlock();
int bufferPos = (int) (position % BLOCK_SIZE);
if (position >= length) {
return -1;
}
int bufferPos = (int) (position % BLOCK_SIZE);
int len = min(dest.remaining(), (int) min(BLOCK_SIZE - bufferPos, length - position));
dest.put(buffer, bufferPos, len);
@@ -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.
*
* @param stream the underlying stream
* @param length the maximum length to read from the stream.
* Note that {@code stream} may contain less than this maximum number of bytes.
* @param pStream the underlying stream
* @param pLength the maximum length to read from the stream.
* 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 IllegalArgumentException if {@code stream == null} or {@code length < 0}
* @throws IOException if {@code pStream}'s position can't be determined.
* @throws IllegalArgumentException if {@code pStream == null} or {@code pLength < 0}
*/
public SubImageInputStream(final ImageInputStream stream, final long length) throws IOException {
Validate.notNull(stream, "stream");
Validate.isTrue(length >= 0, length, "length < 0: %d");
public SubImageInputStream(final ImageInputStream pStream, final long pLength) throws IOException {
Validate.notNull(pStream, "stream");
Validate.isTrue(pLength >= 0, pLength, "length < 0: %d");
this.stream = stream;
this.startPos = stream.getStreamPosition();
this.length = length;
stream = pStream;
startPos = pStream.getStreamPosition();
length = pLength;
}
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
return -1;
}
// Safe cast, as len can never cause int overflow
int length = (int) Math.min(len, this.length - streamPos);
int count = stream.read(bytes, off, length);
// Safe cast, as pLength can never cause int overflow
int length = (int) Math.min(pLength, this.length - streamPos);
int count = stream.read(pBytes, pOffset, length);
if (count >= 0) {
streamPos += count;
@@ -113,18 +113,18 @@ public final class SubImageInputStream extends ImageInputStreamImpl {
}
@Override
public void seek(final long position) throws IOException {
if (position < getFlushedPosition()) {
public void seek(final long pPosition) throws IOException {
if (pPosition < getFlushedPosition()) {
throw new IndexOutOfBoundsException("pos < flushedPosition");
}
stream.seek(startPos + position);
streamPos = position;
stream.seek(startPos + pPosition);
streamPos = pPosition;
}
@SuppressWarnings("MethodDoesntCallSuperMethod")
@SuppressWarnings({"FinalizeDoesntCallSuperFinalize"})
@Override
protected void finalize() {
protected void finalize() throws Throwable {
// Empty finalizer (for improved performance; no need to call super.finalize() in this case)
}
}
@@ -37,14 +37,14 @@ import java.io.IOException;
import static com.twelvemonkeys.lang.Validate.notNull;
/**
* ImageOutputStream that writes through a delegate, but keeps local position and bit offset.
* ImageInputStream that writes through a delegate, but keeps local position and bit offset.
* Note: Flushing or closing this stream will *not* have an effect on the delegate.
*
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
* @author last modified by $Author: harald.kuhr$
* @version $Id: SubImageOutputStream.java,v 1.0 30/03/15 harald.kuhr Exp$
*/
public final class SubImageOutputStream extends ImageOutputStreamImpl {
public class SubImageOutputStream extends ImageOutputStreamImpl {
private final ImageOutputStream stream;
private final long startPos;
@@ -40,7 +40,7 @@ import javax.imageio.spi.ServiceRegistry;
import javax.imageio.stream.ImageInputStream;
import javax.imageio.stream.ImageOutputStream;
import java.awt.*;
import java.awt.image.*;
import java.awt.image.BufferedImage;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.InputStream;
@@ -283,7 +283,7 @@ public final class IIOUtil {
"bitsPerSample must be > 0 and <= 16 and a power of 2");
Validate.isTrue(samplesPerPixel > 0, "samplesPerPixel must be > 0");
Validate.isTrue(samplesPerPixel * bitsPerSample <= 16 || samplesPerPixel * bitsPerSample % 16 == 0,
"samplesPerPixel * bitsPerSample must be < 16 or a multiple of 16");
"samplesPerPixel * bitsPerSample must be < 16 or a multiple of 16 ");
int pixelStride = bitsPerSample * samplesPerPixel / 16;
for (int x = 0; x < srcWidth * pixelStride; x += samplePeriod * pixelStride) {
@@ -305,7 +305,7 @@ public final class IIOUtil {
"bitsPerSample must be > 0 and <= 32 and a power of 2");
Validate.isTrue(samplesPerPixel > 0, "samplesPerPixel must be > 0");
Validate.isTrue(samplesPerPixel * bitsPerSample <= 32 || samplesPerPixel * bitsPerSample % 32 == 0,
"samplesPerPixel * bitsPerSample must be < 32 or a multiple of 32");
"samplesPerPixel * bitsPerSample must be < 32 or a multiple of 32 ");
int pixelStride = bitsPerSample * samplesPerPixel / 32;
for (int x = 0; x < srcWidth * pixelStride; x += samplePeriod * pixelStride) {
@@ -322,7 +322,7 @@ public final class IIOUtil {
"bitsPerSample must be > 0 and <= 32 and a power of 2");
Validate.isTrue(samplesPerPixel > 0, "samplesPerPixel must be > 0");
Validate.isTrue(samplesPerPixel * bitsPerSample <= 32 || samplesPerPixel * bitsPerSample % 32 == 0,
"samplesPerPixel * bitsPerSample must be < 32 or a multiple of 32");
"samplesPerPixel * bitsPerSample must be < 32 or a multiple of 32 ");
int pixelStride = bitsPerSample * samplesPerPixel / 32;
for (int x = 0; x < srcWidth * pixelStride; x += samplePeriod * pixelStride) {
@@ -330,21 +330,4 @@ public final class IIOUtil {
System.arraycopy(srcRow, srcPos + x, destRow, destPos + x / samplePeriod, pixelStride);
}
}
public static void subsampleRow(double[] srcRow, int srcPos, int srcWidth,
double[] destRow, int destPos,
int samplesPerPixel, int bitsPerSample, int samplePeriod) {
Validate.isTrue(samplePeriod > 1, "samplePeriod must be > 1"); // Period == 1 could be a no-op...
Validate.isTrue(bitsPerSample > 0 && bitsPerSample <= 64 && (bitsPerSample == 1 || bitsPerSample % 2 == 0),
"bitsPerSample must be > 0 and <= 64 and a power of 2");
Validate.isTrue(samplesPerPixel > 0, "samplesPerPixel must be > 0");
Validate.isTrue(samplesPerPixel * bitsPerSample <= 64 || samplesPerPixel * bitsPerSample % 64 == 0,
"samplesPerPixel * bitsPerSample must be < 64 or a multiple of 64");
int pixelStride = bitsPerSample * samplesPerPixel / 64;
for (int x = 0; x < srcWidth * pixelStride; x += samplePeriod * pixelStride) {
// System.arraycopy should be intrinsic, but consider using direct array access for pixelStride == 1
System.arraycopy(srcRow, srcPos + x, destRow, destPos + x / samplePeriod, pixelStride);
}
}
}
@@ -257,18 +257,18 @@ public final class ImageTypeSpecifiers {
return createFromIndexColorModel(new IndexColorModel(bits, colors.length, colors, 0, hasAlpha, transIndex, dataType));
}
public static ImageTypeSpecifier createFromIndexColorModel(final IndexColorModel colorModel) {
return new IndexedImageTypeSpecifier(colorModel);
public static ImageTypeSpecifier createFromIndexColorModel(final IndexColorModel pColorModel) {
return new IndexedImageTypeSpecifier(pColorModel);
}
public static ImageTypeSpecifier createDiscreteAlphaIndexedFromIndexColorModel(final IndexColorModel colorModel) {
ColorModel discreteAlphaIndexColorModel = new DiscreteAlphaIndexColorModel(colorModel);
return new ImageTypeSpecifier(discreteAlphaIndexColorModel, discreteAlphaIndexColorModel.createCompatibleSampleModel(1, 1));
public static ImageTypeSpecifier createDiscreteAlphaIndexedFromIndexColorModel(final IndexColorModel pColorModel) {
ColorModel colorModel = new DiscreteAlphaIndexColorModel(pColorModel);
return new ImageTypeSpecifier(colorModel, colorModel.createCompatibleSampleModel(1, 1));
}
public static ImageTypeSpecifier createDiscreteExtraSamplesIndexedFromIndexColorModel(final IndexColorModel colorModel, int extraSamples, boolean hasAlpha) {
ColorModel discreteAlphaIndexColorModel = new DiscreteAlphaIndexColorModel(colorModel, extraSamples, hasAlpha);
return new ImageTypeSpecifier(discreteAlphaIndexColorModel, discreteAlphaIndexColorModel.createCompatibleSampleModel(1, 1));
public static ImageTypeSpecifier createDiscreteExtraSamplesIndexedFromIndexColorModel(final IndexColorModel pColorModel, int extraSamples, boolean hasAlpha) {
ColorModel colorModel = new DiscreteAlphaIndexColorModel(pColorModel, extraSamples, hasAlpha);
return new ImageTypeSpecifier(colorModel, colorModel.createCompatibleSampleModel(1, 1));
}
public static ImageTypeSpecifier createFromRenderedImage(RenderedImage image) {
@@ -279,9 +279,7 @@ public final class ImageTypeSpecifiers {
if (image instanceof BufferedImage) {
int bufferedImageType = ((BufferedImage) image).getType();
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) {
if (bufferedImageType != BufferedImage.TYPE_CUSTOM) {
return createFromBufferedImageType(bufferedImageType);
}
}
@@ -52,12 +52,12 @@ final class IndexedImageTypeSpecifier extends ImageTypeSpecifier {
}
@Override
public BufferedImage createBufferedImage(final int width, final int height) {
public final BufferedImage createBufferedImage(final int pWidth, final int pHeight) {
try {
// 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
// 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);
}
catch (NegativeArraySizeException e) {
@@ -17,7 +17,6 @@ import java.util.Arrays;
import java.util.Calendar;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
@@ -171,7 +170,7 @@ public class StandardImageMetadataSupportTest {
@Test
public void withTextValuesMap() {
Map<String, String> entries = new LinkedHashMap<>();
Map<String, String> entries = new HashMap<>();
entries.put("foo", "bar");
entries.put("bar", "xyzzy");
@@ -36,11 +36,9 @@ import java.awt.color.ColorSpace;
import java.awt.color.ICC_ColorSpace;
import java.awt.color.ICC_Profile;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.Arrays;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assume.assumeFalse;
import static org.mockito.Mockito.*;
public class KCMSSanitizerStrategyTest {
@@ -58,8 +56,6 @@ public class KCMSSanitizerStrategyTest {
@Test
public void testFixProfileUpdateHeader() throws Exception {
assumeICC_ProfileNotSealed(); // Ignores test for JDK 19+
byte[] header = new byte[128];
header[ICC_Profile.icHdrRenderingIntent + 3] = 1;
ICC_Profile profile = mock(ICC_Profile.class);
@@ -73,17 +69,6 @@ public class KCMSSanitizerStrategyTest {
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
public void testFixProfileCorbisRGB() throws IOException {
// TODO: Consider re-writing this using mocks, to avoid dependencies on the CMS implementation
@@ -34,7 +34,6 @@ import org.junit.Test;
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.verifyNoMoreInteractions;
@@ -47,8 +46,6 @@ public class LCMSSanitizerStrategyTest {
@Test
public void testFixProfile() throws Exception {
assumeICC_ProfileNotSealed(); // Ignores test for JDK 19+
ICC_Profile profile = mock(ICC_Profile.class);
new LCMSSanitizerStrategy().fixProfile(profile);
@@ -402,24 +402,6 @@ public class BufferedChannelImageInputStreamMemoryCacheTest {
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
public void testClose() throws IOException {
@@ -31,7 +31,6 @@
package com.twelvemonkeys.imageio.util;
import com.twelvemonkeys.imageio.stream.URLImageInputStreamSpi;
import com.twelvemonkeys.lang.Validate;
import org.junit.Ignore;
import org.junit.Test;
@@ -39,18 +38,14 @@ import org.mockito.InOrder;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import javax.imageio.IIOException;
import javax.imageio.ImageIO;
import javax.imageio.ImageReadParam;
import javax.imageio.ImageReader;
import javax.imageio.ImageTypeSpecifier;
import javax.imageio.*;
import javax.imageio.event.IIOReadProgressListener;
import javax.imageio.metadata.IIOMetadata;
import javax.imageio.spi.IIORegistry;
import javax.imageio.spi.ImageReaderSpi;
import javax.imageio.stream.ImageInputStream;
import java.awt.*;
import java.awt.geom.*;
import java.awt.geom.AffineTransform;
import java.awt.image.*;
import java.io.File;
import java.io.IOException;
@@ -58,7 +53,6 @@ import java.lang.reflect.ParameterizedType;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
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);
}
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();
try (ImageInputStream inputStream = data.getInputStream()) {
reader.setInput(inputStream);
@@ -1834,51 +1828,52 @@ public abstract class ImageReaderAbstractTest<T extends ImageReader> {
private final List<Dimension> sizes;
private final List<BufferedImage> images;
public TestData(final Object input, final Dimension... dimensions) {
this(input, Arrays.asList(dimensions), null);
public TestData(final Object pInput, final Dimension... pSizes) {
this(pInput, Arrays.asList(pSizes), null);
}
public TestData(final Object input, final BufferedImage... images) {
this(input, null, Arrays.asList(images));
public TestData(final Object pInput, final BufferedImage... pImages) {
this(pInput, null, Arrays.asList(pImages));
}
public TestData(final Object input, final List<Dimension> dimensions, final List<BufferedImage> images) {
Validate.notNull(input, "input");
Validate.isTrue(dimensions != null || images != null, "Need either dimensions or image");
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);
public TestData(final Object pInput, final List<Dimension> pSizes, final List<BufferedImage> pImages) {
if (pInput == null) {
throw new IllegalArgumentException("input == null");
}
this.sizes = Collections.unmodifiableList(combinedDimensions);
sizes = new ArrayList<>();
images = new ArrayList<>();
this.images = images != null
? Collections.unmodifiableList(new ArrayList<>(images))
: Collections.<BufferedImage>emptyList();
List<Dimension> sizes = pSizes;
if (sizes == null) {
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() {
@@ -1903,13 +1898,13 @@ public abstract class ImageReaderAbstractTest<T extends ImageReader> {
return sizes.size();
}
public Dimension getDimension(final int index) {
return sizes.get(index);
public Dimension getDimension(final int pIndex) {
return sizes.get(pIndex);
}
@SuppressWarnings("unused")
public BufferedImage getImage(final int index) {
return images.get(index);
public BufferedImage getImage(final int pIndex) {
return images.get(pIndex);
}
@Override
@@ -39,7 +39,6 @@ import java.awt.color.*;
import java.awt.image.*;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertSame;
public class ImageTypeSpecifiersTest {
@@ -737,7 +736,6 @@ public class ImageTypeSpecifiersTest {
ImageTypeSpecifier fromType = ImageTypeSpecifiers.createFromBufferedImageType(type);
assertEquals(fromConstructor.getColorModel(), fromType.getColorModel());
assertEquals(fromConstructor.getSampleModel(), fromType.getSampleModel());
}
}
@@ -749,43 +747,13 @@ public class ImageTypeSpecifiersTest {
ImageTypeSpecifier fromImage = ImageTypeSpecifiers.createFromRenderedImage(image);
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) {
byte[] lut = new byte[count];
for (int i = 0; i < count; i++) {
lut[i] = (byte) (i * 255 / count);
lut[i] = (byte) count;
}
return lut;
}
@@ -794,8 +762,7 @@ public class ImageTypeSpecifiersTest {
int[] lut = new int[count];
for (int i = 0; i < count; i++) {
int val = (i * 255 / count);
lut[i] = 0xff000000 | val << 16 | val << 8 | val;
lut[i] = 0xff000000 | count << 16 | count << 8 | count;
}
return lut;
@@ -43,17 +43,15 @@ import javax.imageio.spi.IIORegistry;
import javax.imageio.spi.ImageWriterSpi;
import javax.imageio.stream.ImageOutputStream;
import java.awt.*;
import java.awt.image.*;
import java.awt.image.BufferedImage;
import java.awt.image.RenderedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.lang.reflect.ParameterizedType;
import java.net.URL;
import java.util.List;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.junit.Assert.*;
import static org.mockito.Mockito.*;
/**
@@ -110,8 +108,8 @@ public abstract class ImageWriterAbstractTest<T extends ImageWriter> {
return getTestData().get(index);
}
protected URL getClassLoaderResource(final String name) {
return getClass().getResource(name);
protected URL getClassLoaderResource(final String pName) {
return getClass().getResource(pName);
}
@Test
+1 -18
View File
@@ -4,7 +4,7 @@
<parent>
<groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio</artifactId>
<version>3.11.1-SNAPSHOT</version>
<version>3.9.1</version>
</parent>
<artifactId>imageio-hdr</artifactId>
<name>TwelveMonkeys :: ImageIO :: HDR plugin</name>
@@ -32,21 +32,4 @@
<artifactId>imageio-metadata</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<configuration>
<instructions>
<Provide-Capability>
osgi.serviceloader;
osgi.serviceloader=javax.imageio.spi.ImageReaderSpi
</Provide-Capability>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
</project>
@@ -59,7 +59,7 @@ public final class HDRImageReader extends ImageReaderBase {
private HDRHeader header;
HDRImageReader(final ImageReaderSpi provider) {
protected HDRImageReader(final ImageReaderSpi provider) {
super(provider);
}
@@ -196,7 +196,7 @@ public final class HDRImageReader extends ImageReaderBase {
int ySub = param != null ? param.getSourceYSubsampling() : 1;
byte[] rowRGBE = new byte[width * 4];
byte[] pixelRGBE = new byte[4];
byte[] pixelRGBE = new byte[width];
processImageStarted(imageIndex);
@@ -231,7 +231,7 @@ public final class HDRImageReader extends ImageReaderBase {
processImageComplete();
return raster;
return destination.getRaster();
}
@Override
@@ -5,7 +5,7 @@ import com.twelvemonkeys.imageio.StandardImageMetadataSupport;
import javax.imageio.ImageTypeSpecifier;
import javax.imageio.metadata.IIOMetadataNode;
final class HDRMetadata extends StandardImageMetadataSupport {
public class HDRMetadata extends StandardImageMetadataSupport {
public HDRMetadata(ImageTypeSpecifier type, HDRHeader header) {
super(builder(type)
.withCompressionTypeName("RLE")
+1 -20
View File
@@ -4,7 +4,7 @@
<parent>
<groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio</artifactId>
<version>3.11.1-SNAPSHOT</version>
<version>3.9.1</version>
</parent>
<artifactId>imageio-icns</artifactId>
<name>TwelveMonkeys :: ImageIO :: ICNS plugin</name>
@@ -26,23 +26,4 @@
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<configuration>
<instructions>
<Provide-Capability>
osgi.serviceloader;
osgi.serviceloader=javax.imageio.spi.ImageReaderSpi,
osgi.serviceloader;
osgi.serviceloader=javax.imageio.spi.ImageWriterSpi
</Provide-Capability>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
</project>
+2 -21
View File
@@ -4,12 +4,12 @@
<parent>
<groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio</artifactId>
<version>3.11.1-SNAPSHOT</version>
<version>3.9.1</version>
</parent>
<artifactId>imageio-iff</artifactId>
<name>TwelveMonkeys :: ImageIO :: IFF plugin</name>
<description>
ImageIO plugin for Amiga/Electronic Arts Interchange File Format (IFF)
ImageIO plugin for Amiga/Electronic Arts Interchange Filed Format (IFF)
type ILBM and PBM format.
</description>
@@ -29,23 +29,4 @@
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<configuration>
<instructions>
<Provide-Capability>
osgi.serviceloader;
osgi.serviceloader=javax.imageio.spi.ImageReaderSpi,
osgi.serviceloader;
osgi.serviceloader=javax.imageio.spi.ImageWriterSpi
</Provide-Capability>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
</project>
+1 -1
View File
@@ -4,7 +4,7 @@
<parent>
<groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio</artifactId>
<version>3.11.1-SNAPSHOT</version>
<version>3.9.1</version>
</parent>
<artifactId>imageio-jpeg-jai-interop</artifactId>
<name>TwelveMonkeys :: ImageIO :: JPEG/JAI TIFF Interop</name>
+1 -1
View File
@@ -4,7 +4,7 @@
<parent>
<groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio</artifactId>
<version>3.11.1-SNAPSHOT</version>
<version>3.9.1</version>
</parent>
<artifactId>imageio-jpeg-jep262-interop</artifactId>
<name>TwelveMonkeys :: ImageIO :: JPEG/JEP-262 Interop</name>
+1 -20
View File
@@ -4,7 +4,7 @@
<parent>
<groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio</artifactId>
<version>3.11.1-SNAPSHOT</version>
<version>3.9.1</version>
</parent>
<artifactId>imageio-jpeg</artifactId>
<name>TwelveMonkeys :: ImageIO :: JPEG plugin</name>
@@ -32,23 +32,4 @@
<artifactId>imageio-metadata</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<configuration>
<instructions>
<Provide-Capability>
osgi.serviceloader;
osgi.serviceloader=javax.imageio.spi.ImageReaderSpi,
osgi.serviceloader;
osgi.serviceloader=javax.imageio.spi.ImageWriterSpi
</Provide-Capability>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
</project>
@@ -53,7 +53,7 @@ final class AdobeDCT extends Application {
final int transform;
private AdobeDCT(int version, int flags0, int flags1, int transform) {
super(JPEG.APP14, "Adobe", new byte[]{'A', 'd', 'o', 'b', 'e', (byte) (version >> 8), (byte) (version & 0xff), (byte) (flags0 >> 8), (byte) (flags0 & 0xff), (byte) (flags1 >> 8), (byte) (flags1 & 0xff), (byte) transform});
super(JPEG.APP14, "Adobe", new byte[]{'A', 'd', 'o', 'b', 'e', 0, (byte) version, (byte) (flags0 >> 8), (byte) (flags0 & 0xff), (byte) (flags1 >> 8), (byte) (flags1 & 0xff), (byte) transform});
this.version = version; // 100 or 101
this.flags0 = flags0;
@@ -72,11 +72,11 @@ final class AdobeDCT extends Application {
public static AdobeDCT read(final DataInput data, final int length) throws IOException {
// TODO: Investigate http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6355567: 33/35 byte Adobe APP14 markers
data.skipBytes(5); // A, d, o, b, e
data.skipBytes(6); // A, d, o, b, e, \0
// version (2 bytes), flags (4bytes), color transform (byte: 0=unknown, 1=YCC, 2=YCCK)
// version (byte), flags (4bytes), color transform (byte: 0=unknown, 1=YCC, 2=YCCK)
return new AdobeDCT(
data.readUnsignedShort(),
data.readUnsignedByte(),
data.readUnsignedShort(),
data.readUnsignedShort(),
data.readUnsignedByte()
@@ -145,8 +145,8 @@ final class HuffmanTable extends Segment {
}
int c = temp >> 4;
if (c > 1) {
throw new IIOException("Unexpected JPEG Huffman Table class (> 1): " + c);
if (c > 2) {
throw new IIOException("Unexpected JPEG Huffman Table class (> 2): " + c);
}
table.tc[t][c] = true;
@@ -888,21 +888,20 @@ public final class JPEGImageReader extends ImageReaderBase {
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 {
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{
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 {
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 {
@@ -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$
*/
public final class JPEGImageReaderSpi extends ImageReaderSpiBase {
ImageReaderSpi delegateProvider;
protected ImageReaderSpi delegateProvider;
/**
* Constructor for use by {@link javax.imageio.spi.IIORegistry} only.
@@ -32,21 +32,19 @@ package com.twelvemonkeys.imageio.plugins.jpeg;
import com.twelvemonkeys.imageio.ImageWriterBase;
import com.twelvemonkeys.imageio.metadata.jpeg.JPEG;
import com.twelvemonkeys.imageio.util.ImageTypeSpecifiers;
import com.twelvemonkeys.imageio.util.ProgressListenerBase;
import org.w3c.dom.NodeList;
import javax.imageio.IIOImage;
import javax.imageio.ImageTypeSpecifier;
import javax.imageio.ImageWriteParam;
import javax.imageio.ImageWriter;
import javax.imageio.event.IIOWriteWarningListener;
import javax.imageio.metadata.IIOInvalidTreeException;
import javax.imageio.metadata.IIOMetadata;
import javax.imageio.metadata.IIOMetadataNode;
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.io.IOException;
import java.nio.charset.StandardCharsets;
@@ -163,7 +161,7 @@ public final class JPEGImageWriter extends ImageWriterBase {
else {
// If the image metadata is our substitute, convert it back to native com.sun format
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);
JPEGImage10Metadata metadata = (JPEGImage10Metadata) image.getMetadata();
@@ -186,67 +184,23 @@ public final class JPEGImageWriter extends ImageWriterBase {
RenderedImage renderedImage = image.getRenderedImage();
boolean overrideDestination = param != null && param.getDestinationType() != null;
ImageTypeSpecifier destinationType = overrideDestination
? param.getDestinationType()
: ImageTypeSpecifiers.createFromRenderedImage(renderedImage);
? param.getDestinationType()
: 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);
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");
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");
app14Adobe.setAttribute("transform", "0"); // 0 for CMYK, 2 for YCCK
markerSequence.appendChild(app14Adobe);
ColorSpace cmykCS = destinationType.getColorModel().getColorSpace();
if (cmykCS instanceof ICC_ColorSpace) {
ICC_Profile profile = ((ICC_ColorSpace) cmykCS).getProfile();
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);
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
@@ -38,13 +38,7 @@ import com.twelvemonkeys.imageio.util.ImageWriterAbstractTest;
import org.junit.Test;
import org.w3c.dom.NodeList;
import javax.imageio.IIOImage;
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.*;
import javax.imageio.metadata.IIOMetadata;
import javax.imageio.metadata.IIOMetadataFormatImpl;
import javax.imageio.metadata.IIOMetadataNode;
@@ -54,7 +48,8 @@ import javax.imageio.stream.ImageInputStream;
import javax.imageio.stream.ImageOutputStream;
import javax.imageio.stream.MemoryCacheImageOutputStream;
import java.awt.*;
import java.awt.color.*;
import java.awt.color.ColorSpace;
import java.awt.color.ICC_Profile;
import java.awt.image.*;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
@@ -216,7 +211,7 @@ public class JPEGImageWriterTest extends ImageWriterAbstractTest<JPEGImageWriter
// Test APP2/ICC_PROFILE segments form native metadata
IIOMetadataNode nativeMeta = (IIOMetadataNode) metadata.getAsTree(JPEGImage10Metadata.JAVAX_IMAGEIO_JPEG_IMAGE_1_0);
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);
@@ -243,6 +238,7 @@ public class JPEGImageWriterTest extends ImageWriterAbstractTest<JPEGImageWriter
ImageWriter writer = createWriter();
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);
reader.reset();
@@ -263,7 +259,7 @@ public class JPEGImageWriterTest extends ImageWriterAbstractTest<JPEGImageWriter
// Test APP2/ICC_PROFILE segments form native metadata
IIOMetadataNode nativeMeta = (IIOMetadataNode) metadata.getAsTree(JPEGImage10Metadata.JAVAX_IMAGEIO_JPEG_IMAGE_1_0);
NodeList unknown = nativeMeta.getElementsByTagName("unknown");
assertEquals(3, unknown.getLength());
assertEquals(0, unknown.getLength());
}
// TODO: YCCK
+2 -11
View File
@@ -3,13 +3,13 @@
<parent>
<groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio</artifactId>
<version>3.11.1-SNAPSHOT</version>
<version>3.9.1</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>imageio-metadata</artifactId>
<name>TwelveMonkeys :: ImageIO :: Metadata</name>
<description>
TwelveMonkeys ImageIO metadata support classes.
ImageIO metadata module.
</description>
<properties>
@@ -28,13 +28,4 @@
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
@@ -43,17 +43,13 @@ import com.twelvemonkeys.imageio.stream.ByteArrayImageInputStream;
import javax.imageio.IIOException;
import javax.imageio.ImageIO;
import javax.imageio.stream.ImageInputStream;
import java.awt.color.*;
import java.awt.color.ICC_Profile;
import java.io.ByteArrayOutputStream;
import java.io.EOFException;
import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.*;
import static com.twelvemonkeys.lang.Validate.notNull;
@@ -148,10 +144,8 @@ public final class JPEGSegmentUtil {
}
static String asNullTerminatedAsciiString(final byte[] data, final int offset) {
// TODO: JPEG App segment identifiers are not always 0-terminated...
// Need to rewrite. For now, make sure we read only ASCII non-control chars.
for (int i = 0; i < data.length - offset; i++) {
if (data[offset + i] < 20 || i > 255) {
if (data[offset + i] == 0 || i > 255) {
return asAsciiString(data, offset, offset + i);
}
}
@@ -87,6 +87,11 @@ public final class Half extends Number implements Comparable<Half> {
}
else if (exponent != 0) { // Normalized value
exponent += 0x1c000; // exp - 15 + 127
// Smooth transition
if (mantissa == 0 && exponent > 0x1c400) {
return Float.intBitsToFloat((shortBits & 0x8000) << 16 | exponent << 13 | 0x3ff);
}
}
else if (mantissa != 0) { // && exp == 0 -> subnormal
exponent = 0x1c400; // Make it normal
@@ -1,16 +1,16 @@
package com.twelvemonkeys.imageio.metadata.tiff;
import com.twelvemonkeys.io.FastByteArrayOutputStream;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.Random;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import org.junit.Test;
import com.twelvemonkeys.io.FastByteArrayOutputStream;
/**
* HalfTest.
@@ -36,13 +36,6 @@ public class HalfTest {
}
}
@Test
public void testExactEncoding() {
for (short half = -2048; half < 2048; half++) {
assertEquals(String.valueOf(half), half, Half.shortBitsToFloat(Half.floatToShortBits(half)), 0);
}
}
@Test
public void testRoundTripBack() {
for (int i = 0; i < 1024; i++) {
@@ -35,11 +35,8 @@ import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
@@ -53,7 +50,6 @@ import java.util.Iterator;
import javax.imageio.ImageIO;
import javax.imageio.stream.ImageInputStream;
import com.twelvemonkeys.imageio.stream.DirectImageInputStream;
import org.junit.Test;
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"));
}
@Test(timeout = 2500L)
@Test(timeout = 1500L)
public void testNoExternalRequest() throws Exception {
String maliciousXML = resourceAsString("/xmp/xmp-jpeg-xxe.xml");
try (HTTPServer server = new HTTPServer()) {
String dynamicXML = maliciousXML.replace("http://localhost:7777/", "http://localhost:" + server.port() + "/");
try (DirectImageInputStream input = new DirectImageInputStream(new ByteArrayInputStream(dynamicXML.getBytes(StandardCharsets.UTF_8)));) {
createReader().read(input);
// TODO: Use dynamic port?
try (HTTPServer server = new HTTPServer(7777)) {
try {
createReader().read(getResourceAsIIS("/xmp/xmp-jpeg-xxe.xml"));
} catch (IOException ioe) {
if (ioe.getMessage().contains("501")) {
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 final ServerSocket server;
private final Thread thread;
HTTPServer() throws IOException {
server = new ServerSocket(0, 1);
HTTPServer(int port) throws IOException {
server = new ServerSocket(port, 1);
thread = new Thread(new Runnable() {
@Override public void run() {
serve();
@@ -542,10 +521,6 @@ public class XMPReaderTest extends MetadataReaderAbstractTest {
thread.start();
}
public final int port() {
return server.getLocalPort();
}
private void serve() {
try {
Socket client = server.accept();
+1 -18
View File
@@ -4,7 +4,7 @@
<parent>
<groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio</artifactId>
<version>3.11.1-SNAPSHOT</version>
<version>3.9.1</version>
</parent>
<artifactId>imageio-pcx</artifactId>
<name>TwelveMonkeys :: ImageIO :: PCX plugin</name>
@@ -28,21 +28,4 @@
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<configuration>
<instructions>
<Provide-Capability>
osgi.serviceloader;
osgi.serviceloader=javax.imageio.spi.ImageReaderSpi
</Provide-Capability>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
</project>
+1 -10
View File
@@ -4,7 +4,7 @@
<parent>
<groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio</artifactId>
<version>3.11.1-SNAPSHOT</version>
<version>3.9.1</version>
</parent>
<artifactId>imageio-pdf</artifactId>
<name>TwelveMonkeys :: ImageIO :: PDF plugin</name>
@@ -28,13 +28,4 @@
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
+1 -19
View File
@@ -4,7 +4,7 @@
<parent>
<groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio</artifactId>
<version>3.11.1-SNAPSHOT</version>
<version>3.9.1</version>
</parent>
<artifactId>imageio-pict</artifactId>
<name>TwelveMonkeys :: ImageIO :: PICT plugin</name>
@@ -27,22 +27,4 @@
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<configuration>
<instructions>
<Provide-Capability>
osgi.serviceloader;
osgi.serviceloader=javax.imageio.spi.ImageReaderSpi,
osgi.serviceloader;
osgi.serviceloader=javax.imageio.spi.ImageWriterSpi
</Provide-Capability>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
</project>
+1 -20
View File
@@ -4,7 +4,7 @@
<parent>
<groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio</artifactId>
<version>3.11.1-SNAPSHOT</version>
<version>3.9.1</version>
</parent>
<artifactId>imageio-pnm</artifactId>
<name>TwelveMonkeys :: ImageIO :: PNM plugin</name>
@@ -28,23 +28,4 @@
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<configuration>
<instructions>
<Provide-Capability>
osgi.serviceloader;
osgi.serviceloader=javax.imageio.spi.ImageReaderSpi,
osgi.serviceloader;
osgi.serviceloader=javax.imageio.spi.ImageWriterSpi
</Provide-Capability>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
</project>
@@ -30,6 +30,8 @@
package com.twelvemonkeys.imageio.plugins.pnm;
import com.twelvemonkeys.imageio.ImageWriterBase;
import org.w3c.dom.NodeList;
import javax.imageio.IIOImage;
@@ -38,7 +40,7 @@ import javax.imageio.metadata.IIOMetadataFormatImpl;
import javax.imageio.metadata.IIOMetadataNode;
import javax.imageio.spi.ImageWriterSpi;
import javax.imageio.stream.ImageOutputStream;
import java.awt.image.*;
import java.awt.image.DataBuffer;
import java.io.IOException;
import java.util.Locale;
@@ -51,7 +53,11 @@ abstract class HeaderWriter {
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")) {
return new PAMHeaderWriter(imageOutput);
}
@@ -77,36 +83,25 @@ abstract class HeaderWriter {
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) {
int transferType = getTransferType(image);
switch (transferType) {
case DataBuffer.TYPE_BYTE:
return PNM.MAX_VAL_8BIT;
case DataBuffer.TYPE_USHORT:
return PNM.MAX_VAL_16BIT;
case DataBuffer.TYPE_INT:
// We support TYPE_INT through conversion, if number of channels is 3 or 4 (TYPE_INT_RGB, TYPE_INT_ARGB)
SampleModel sampleModel = getSampleModel(image);
int numBands = sampleModel.getNumBands();
if (sampleModel instanceof SinglePixelPackedSampleModel && (numBands == 3 || numBands == 4)) {
return PNM.MAX_VAL_8BIT;
}
// ...else fall through
default:
throw new IllegalArgumentException("Unsupported data type: " + transferType);
if (transferType == DataBuffer.TYPE_BYTE) {
return PNM.MAX_VAL_8BIT;
}
else if (transferType == DataBuffer.TYPE_USHORT) {
return PNM.MAX_VAL_16BIT;
}
// else if (transferType == DataBuffer.TYPE_INT) {
// TODO: Support TYPE_INT through conversion, if number of channels is 3 or 4 (TYPE_INT_RGB, TYPE_INT_ARGB)
// }
else {
throw new IllegalArgumentException("Unsupported data type: " + transferType);
}
}
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 {
@@ -125,4 +120,5 @@ abstract class HeaderWriter {
}
}
}
}
@@ -30,8 +30,6 @@
package com.twelvemonkeys.imageio.plugins.pnm;
import com.twelvemonkeys.imageio.util.ImageTypeSpecifiers;
import javax.imageio.IIOImage;
import javax.imageio.spi.ImageWriterSpi;
import javax.imageio.stream.ImageOutputStream;
@@ -46,8 +44,6 @@ final class PAMHeaderWriter extends HeaderWriter {
@Override
public void writeHeader(final IIOImage image, final ImageWriterSpi provider) throws IOException {
TupleType tupleType = tupleType(image);
// Write PAM magic
imageOutput.writeShort(PNM.PAM);
imageOutput.write('\n');
@@ -56,19 +52,12 @@ final class PAMHeaderWriter extends HeaderWriter {
// 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("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));
// 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));
}
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;
}
}
@@ -45,11 +45,12 @@ public final class PAMImageWriterSpi extends ImageWriterSpiBase {
super(new PAMProviderInfo());
}
public boolean canEncodeImage(final ImageTypeSpecifier type) {
return TupleType.forPAM(type) != null;
public boolean canEncodeImage(final ImageTypeSpecifier pType) {
// TODO: FixMe
return true;
}
public ImageWriter createWriterInstance(final Object extension) {
public ImageWriter createWriterInstance(final Object pExtension) {
return new PNMImageWriter(this);
}
@@ -69,7 +69,7 @@ final class PFMHeaderParser extends HeaderParser {
public PNMHeader parse() throws IOException {
int width = 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<>();
@@ -77,7 +77,7 @@ final class PFMHeaderParser extends HeaderParser {
String line = input.readLine();
if (line == null) {
throw new IIOException("Unexpected end of stream");
throw new IIOException("Unexpeced end of stream");
}
int commentStart = line.indexOf('#');
@@ -30,8 +30,6 @@
package com.twelvemonkeys.imageio.plugins.pnm;
import com.twelvemonkeys.imageio.util.ImageTypeSpecifiers;
import javax.imageio.IIOImage;
import javax.imageio.spi.ImageWriterSpi;
import javax.imageio.stream.ImageOutputStream;
@@ -47,7 +45,8 @@ final class PNMHeaderWriter extends HeaderWriter {
@Override
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)
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.write('\n');
@@ -62,35 +61,4 @@ final class PNMHeaderWriter extends HeaderWriter {
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;
}
}
@@ -31,17 +31,14 @@
package com.twelvemonkeys.imageio.plugins.pnm;
import com.twelvemonkeys.imageio.ImageWriterBase;
import com.twelvemonkeys.imageio.util.RasterUtils;
import javax.imageio.IIOImage;
import javax.imageio.ImageIO;
import javax.imageio.ImageTypeSpecifier;
import javax.imageio.ImageWriteParam;
import javax.imageio.ImageWriter;
import javax.imageio.*;
import javax.imageio.metadata.IIOMetadata;
import javax.imageio.spi.ImageWriterSpi;
import javax.imageio.stream.ImageOutputStream;
import java.awt.image.*;
import java.awt.image.BufferedImage;
import java.awt.image.DataBuffer;
import java.awt.image.Raster;
import java.awt.image.SampleModel;
import java.io.File;
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 IIOImage contains thumbnails or other data we can't store?
writeHeader(image, this, imageOutput);
HeaderWriter.write(image, this, imageOutput);
// TODO: Sub region
// TODO: Subsampling
@@ -83,20 +80,16 @@ public final class PNMImageWriter extends ImageWriterBase {
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 {
// - 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!
// 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
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();
DataBuffer dataBuffer = tile.getDataBuffer();
int tileWidth = tile.getWidth();
@@ -48,11 +48,12 @@ public final class PNMImageWriterSpi extends ImageWriterSpiBase {
super(new PNMProviderInfo());
}
public boolean canEncodeImage(final ImageTypeSpecifier type) {
return TupleType.forPNM(type) != null;
public boolean canEncodeImage(final ImageTypeSpecifier pType) {
// 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);
}
@@ -30,10 +30,7 @@
package com.twelvemonkeys.imageio.plugins.pnm;
import javax.imageio.ImageTypeSpecifier;
import java.awt.*;
import java.awt.color.*;
import java.awt.image.*;
enum TupleType {
// Official:
@@ -83,150 +80,4 @@ enum TupleType {
public boolean isValidMaxSample(int maxSample) {
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;
}
}
@@ -30,23 +30,15 @@
package com.twelvemonkeys.imageio.plugins.pnm;
import com.twelvemonkeys.imageio.color.ColorSpaces;
import org.junit.Test;
import javax.imageio.ImageTypeSpecifier;
import javax.imageio.ImageWriter;
import javax.imageio.spi.ImageReaderSpi;
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.assertClassesExist;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
/**
* PAMImageWriterSpiTest.
@@ -73,85 +65,4 @@ public class PAMImageWriterSpiTest {
public void 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))));
}
}
@@ -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)
);
}
}
@@ -32,19 +32,13 @@ package com.twelvemonkeys.imageio.plugins.pnm;
import org.junit.Test;
import javax.imageio.ImageTypeSpecifier;
import javax.imageio.ImageWriter;
import javax.imageio.spi.ImageReaderSpi;
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.assertClassesExist;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
/**
* PNMImageWriterSpiTest.
@@ -71,70 +65,4 @@ public class PNMImageWriterSpiTest {
public void 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,7 +3,8 @@ package com.twelvemonkeys.imageio.plugins.pnm;
import com.twelvemonkeys.imageio.util.ImageWriterAbstractTest;
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.List;
@@ -16,12 +17,10 @@ public class PNMImageWriterTest extends ImageWriterAbstractTest<PNMImageWriter>
@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_INT_BGR),
new BufferedImage(10, 10, BufferedImage.TYPE_INT_BGR)
new BufferedImage(100, 100, BufferedImage.TYPE_4BYTE_ABGR)
);
}
}
+1 -20
View File
@@ -4,7 +4,7 @@
<parent>
<groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio</artifactId>
<version>3.11.1-SNAPSHOT</version>
<version>3.9.1</version>
</parent>
<artifactId>imageio-psd</artifactId>
<name>TwelveMonkeys :: ImageIO :: PSD plugin</name>
@@ -31,23 +31,4 @@
<artifactId>imageio-metadata</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<configuration>
<instructions>
<Provide-Capability>
osgi.serviceloader;
osgi.serviceloader=javax.imageio.spi.ImageReaderSpi,
osgi.serviceloader;
osgi.serviceloader=javax.imageio.spi.ImageWriterSpi
</Provide-Capability>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
</project>

Some files were not shown because too many files have changed in this diff Show More