Compare commits

..

3 Commits

Author SHA1 Message Date
Harald Kuhr fe591d9b6c Bump org.junit.jupiter:junit-jupiter-api from 5.12.2 to 5.13.0 2025-06-06 13:02:05 +02:00
Harald Kuhr 06d988377e Bump org.junit.jupiter:junit-jupiter-api from 5.12.2 to 5.13.0 2025-06-06 13:02:05 +02:00
Harald Kuhr 360b4e9bba Bump org.junit.jupiter:junit-jupiter-api from 5.12.2 to 5.13.0 2025-06-06 13:02:05 +02:00
77 changed files with 258 additions and 947 deletions
-4
View File
@@ -5,13 +5,9 @@ updates:
directory: "/" directory: "/"
schedule: schedule:
interval: "daily" interval: "daily"
cooldown:
default-days: 7
open-pull-requests-limit: 10 open-pull-requests-limit: 10
# GitHub actions updates # GitHub actions updates
- package-ecosystem: "github-actions" - package-ecosystem: "github-actions"
directory: "/.github/workflows" directory: "/.github/workflows"
schedule: schedule:
interval: "daily" interval: "daily"
cooldown:
default-days: 7
+24 -40
View File
@@ -17,16 +17,13 @@ jobs:
fail-fast: false fail-fast: false
matrix: matrix:
os: [ ubuntu-latest, windows-latest, macos-latest ] os: [ ubuntu-latest, windows-latest, macos-latest ]
java: [ 8, 11, 17, 21, 25 ] java: [ 11, 17, 21, 23 ]
exclude:
- os: macos-latest
java: 8
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
permissions: permissions:
checks: write checks: write
steps: steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0 - uses: actions/setup-java@c5195efecf7bdfc987ee8bae7a71cb8b11521c00 # v4.7.1
with: with:
distribution: 'temurin' distribution: 'temurin'
java-version: ${{ matrix.java }} java-version: ${{ matrix.java }}
@@ -35,29 +32,33 @@ jobs:
- name: Run Tests - name: Run Tests
run: mvn --batch-mode --no-transfer-progress test run: mvn --batch-mode --no-transfer-progress test
- name: Publish Test Report - name: Publish Test Report
uses: mikepenz/action-junit-report@74626db7353a25a20a72816467ebf035f674c5f8 # v5 uses: mikepenz/action-junit-report@65fe03598d8d251738592a497a9e8547a5c48eaa # v5
if: ${{ !cancelled() }} if: ${{ !cancelled() }}
with: with:
report_paths: "**/target/surefire-reports/TEST*.xml" report_paths: "**/target/surefire-reports/TEST*.xml"
check_name: Unit Test Results for OpenJDK ${{ matrix.java }} on ${{ matrix.os }} check_name: Unit Test Results for OpenJDK ${{ matrix.java }} on ${{ matrix.os }}
test-jdk8-macos: test-jdk8:
name: Test OpenJDK 8 on macos-14 name: Test OpenJDK ${{ matrix.java }} on ${{ matrix.os }}
runs-on: macos-14 strategy:
fail-fast: false
matrix:
os: [ ubuntu-latest, windows-latest, macos-13 ]
runs-on: ${{ matrix.os }}
permissions: permissions:
checks: write checks: write
steps: steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0 - uses: actions/setup-java@c5195efecf7bdfc987ee8bae7a71cb8b11521c00 # v4.7.1
with: with:
distribution: 'zulu' distribution: 'temurin'
java-version: '8' java-version: '8'
java-package: jdk java-package: jdk
cache: 'maven' cache: 'maven'
- name: Run Tests - name: Run Tests
run: mvn --batch-mode --no-transfer-progress test run: mvn --batch-mode --no-transfer-progress test
- name: Publish Test Report - name: Publish Test Report
uses: mikepenz/action-junit-report@74626db7353a25a20a72816467ebf035f674c5f8 # v5 uses: mikepenz/action-junit-report@65fe03598d8d251738592a497a9e8547a5c48eaa # v5
if: ${{ !cancelled() }} if: ${{ !cancelled() }}
with: with:
report_paths: "**/target/surefire-reports/TEST*.xml" report_paths: "**/target/surefire-reports/TEST*.xml"
@@ -72,11 +73,11 @@ jobs:
matrix: matrix:
kcms: [ true, false ] kcms: [ true, false ]
steps: steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- run: | - run: |
download_url="https://javadl.oracle.com/webapps/download/AutoDL?BundleId=245038_d3c52aa6bfa54d3ca74e617f18309292" download_url="https://javadl.oracle.com/webapps/download/AutoDL?BundleId=245038_d3c52aa6bfa54d3ca74e617f18309292"
wget -O $RUNNER_TEMP/java_package.tar.gz $download_url wget -O $RUNNER_TEMP/java_package.tar.gz $download_url
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0 - uses: actions/setup-java@c5195efecf7bdfc987ee8bae7a71cb8b11521c00 # v4.7.1
with: with:
distribution: 'jdkfile' distribution: 'jdkfile'
jdkFile: ${{ runner.temp }}/java_package.tar.gz jdkFile: ${{ runner.temp }}/java_package.tar.gz
@@ -91,43 +92,26 @@ jobs:
- name: Run Tests - name: Run Tests
run: mvn --batch-mode --no-transfer-progress test run: mvn --batch-mode --no-transfer-progress test
- name: Publish Test Report - name: Publish Test Report
uses: mikepenz/action-junit-report@74626db7353a25a20a72816467ebf035f674c5f8 # v5 uses: mikepenz/action-junit-report@65fe03598d8d251738592a497a9e8547a5c48eaa # v5
if: ${{ !cancelled() }} if: ${{ !cancelled() }}
with: with:
report_paths: "**/target/surefire-reports/TEST*.xml" report_paths: "**/target/surefire-reports/TEST*.xml"
check_name: Unit Test Results for Oracle JDK 8 with KCMS=${{ matrix.kcms }} check_name: Unit Test Results for Oracle JDK 8 with KCMS=${{ matrix.kcms }}
javadoc:
name: Build JavaDoc on OpenJDK ${{ matrix.java }}
runs-on: ubuntu-latest
strategy:
matrix:
java: [8, 11, 25 ] # We only need a few versions here
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0
with:
distribution: 'temurin'
java-version: ${{ matrix.java }}
java-package: jdk
cache: 'maven'
- name: Create JavaDoc
run: mvn --batch-mode --no-transfer-progress -DskipTests package javadoc:javadoc
release: release:
name: Deploy name: Deploy
needs: [ test, test-jdk8-macos, test-oracle, javadoc ] needs: [ test, test-jdk8, test-oracle ]
if: github.ref == 'refs/heads/master' # only perform on latest master if: github.ref == 'refs/heads/master' # only perform on latest master
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Set up Maven Central - name: Set up Maven Central
uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0 uses: actions/setup-java@c5195efecf7bdfc987ee8bae7a71cb8b11521c00 # v4.7.1
with: # running setup-java again overwrites the settings.xml with: # running setup-java again overwrites the settings.xml
distribution: 'temurin' distribution: 'temurin'
java-version: '8' java-version: '8'
java-package: jdk java-package: jdk
server-id: central # Value of the distributionManagement/repository/id field of the pom.xml server-id: ossrh # Value of the distributionManagement/repository/id field of the pom.xml
server-username: MAVEN_CENTRAL_USERNAME # env variable for username in deploy (1) server-username: MAVEN_CENTRAL_USERNAME # env variable for username in deploy (1)
server-password: MAVEN_CENTRAL_PASSWORD # env variable for token in deploy (2) server-password: MAVEN_CENTRAL_PASSWORD # env variable for token in deploy (2)
- name: Get Project Version - name: Get Project Version
@@ -137,7 +121,7 @@ jobs:
if: ${{ endsWith(env.PROJECT_VERSION, '-SNAPSHOT') }} if: ${{ endsWith(env.PROJECT_VERSION, '-SNAPSHOT') }}
run: mvn --batch-mode --no-transfer-progress deploy -P release -DskipTests -Dgpg.signer=bc run: mvn --batch-mode --no-transfer-progress deploy -P release -DskipTests -Dgpg.signer=bc
env: env:
MAVEN_CENTRAL_USERNAME: ${{ secrets.CENTRAL_USERNAME }} # must be the same env variable name as (1) MAVEN_CENTRAL_USERNAME: ${{ secrets.SONATYPE_USERNAME }} # must be the same env variable name as (1)
MAVEN_CENTRAL_PASSWORD: ${{ secrets.CENTRAL_PASSWORD }} # must be the same env variable name as (2) MAVEN_CENTRAL_PASSWORD: ${{ secrets.SONATYPE_PASSWORD }} # must be the same env variable name as (2)
MAVEN_GPG_KEY: ${{ secrets.GPG_KEY }} # Value of the GPG private key to import MAVEN_GPG_KEY: ${{ secrets.GPG_KEY }} # Value of the GPG private key to import
MAVEN_GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }} MAVEN_GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }}
+4 -4
View File
@@ -33,11 +33,11 @@ jobs:
steps: steps:
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
# Initializes the CodeQL tools for scanning. # Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL - name: Initialize CodeQL
uses: github/codeql-action/init@45cbd0c69e560cd9e7cd7f8c32362050c9b7ded2 # v4.32.2 uses: github/codeql-action/init@fca7ace96b7d713c7035871441bd52efbe39e27e # v3.28.19
with: with:
languages: ${{ matrix.language }} languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file. # If you wish to specify custom queries, you can do so here or in a config file.
@@ -51,7 +51,7 @@ jobs:
# Autobuild attempts to build any compiled languages (C/C++, C#, Go, Java, or Swift). # 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) # If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild - name: Autobuild
uses: github/codeql-action/autobuild@45cbd0c69e560cd9e7cd7f8c32362050c9b7ded2 # v4.32.2 uses: github/codeql-action/autobuild@fca7ace96b7d713c7035871441bd52efbe39e27e # v3.28.19
# ℹ️ Command-line programs to run using the OS shell. # ℹ️ 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 # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
@@ -64,6 +64,6 @@ jobs:
# ./location_of_script_within_repo/buildscript.sh # ./location_of_script_within_repo/buildscript.sh
- name: Perform CodeQL Analysis - name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@45cbd0c69e560cd9e7cd7f8c32362050c9b7ded2 # v4.32.2 uses: github/codeql-action/analyze@fca7ace96b7d713c7035871441bd52efbe39e27e # v3.28.19
with: with:
category: "/language:${{matrix.language}}" category: "/language:${{matrix.language}}"
+4 -4
View File
@@ -26,12 +26,12 @@ jobs:
steps: steps:
- name: "Checkout code" - name: "Checkout code"
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with: with:
persist-credentials: false persist-credentials: false
- name: "Run analysis" - name: "Run analysis"
uses: ossf/scorecard-action@4eaacf0543bb3f2c246792bd56e8cdeffafb205a # v2.4.3 uses: ossf/scorecard-action@05b42c624433fc40578a4040d5cf5e36ddca8cde # v2.4.2
with: with:
results_file: results.sarif results_file: results.sarif
results_format: sarif results_format: sarif
@@ -49,7 +49,7 @@ jobs:
# Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF # Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF
# format to the repository Actions tab. # format to the repository Actions tab.
- name: "Upload artifact" - name: "Upload artifact"
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with: with:
name: SARIF file name: SARIF file
path: results.sarif path: results.sarif
@@ -57,6 +57,6 @@ jobs:
# Upload the results to GitHub's code scanning dashboard. # Upload the results to GitHub's code scanning dashboard.
- name: "Upload to code-scanning" - name: "Upload to code-scanning"
uses: github/codeql-action/upload-sarif@45cbd0c69e560cd9e7cd7f8c32362050c9b7ded2 # v4.32.2 uses: github/codeql-action/upload-sarif@fca7ace96b7d713c7035871441bd52efbe39e27e # v3.28.19
with: with:
sarif_file: results.sarif sarif_file: results.sarif
+38 -38
View File
@@ -4,7 +4,7 @@
[![OpenSSF Best Practices](https://www.bestpractices.dev/projects/7900/badge)](https://www.bestpractices.dev/projects/7900) [![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 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/maven-metadata/v?metadataUrl=https%3A%2F%2Fcentral.sonatype.com%2Frepository%2Fmaven-snapshots%2Fcom%2Ftwelvemonkeys%2Fimageio%2Fimageio%2Fmaven-metadata.xml&label=development&server=https%3A%2F%2Foss.sonatype.org&color=slateblue)](https://central.sonatype.com/repository/maven-snapshots/com/twelvemonkeys/imageio/imageio/maven-metadata.xml) [![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) [![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) [![Donate](https://img.shields.io/badge/donate-PayPal-blue.svg)](https://paypal.me/haraldk76/100)
@@ -316,12 +316,12 @@ To depend on the JPEG and TIFF plugin using Maven, add the following to your POM
<dependency> <dependency>
<groupId>com.twelvemonkeys.imageio</groupId> <groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio-jpeg</artifactId> <artifactId>imageio-jpeg</artifactId>
<version>3.13.1</version> <version>3.12.0</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.twelvemonkeys.imageio</groupId> <groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio-tiff</artifactId> <artifactId>imageio-tiff</artifactId>
<version>3.13.1</version> <version>3.12.0</version>
</dependency> </dependency>
<!-- <!--
@@ -331,7 +331,7 @@ To depend on the JPEG and TIFF plugin using Maven, add the following to your POM
<dependency> <dependency>
<groupId>com.twelvemonkeys.servlet</groupId> <groupId>com.twelvemonkeys.servlet</groupId>
<artifactId>servlet</artifactId> <artifactId>servlet</artifactId>
<version>3.13.1</version> <version>3.12.0</version>
</dependency> </dependency>
<!-- <!--
@@ -340,7 +340,7 @@ To depend on the JPEG and TIFF plugin using Maven, add the following to your POM
<dependency> <dependency>
<groupId>com.twelvemonkeys.servlet</groupId> <groupId>com.twelvemonkeys.servlet</groupId>
<artifactId>servlet</artifactId> <artifactId>servlet</artifactId>
<version>3.13.1</version> <version>3.12.0</version>
<classifier>jakarta</classifier> <classifier>jakarta</classifier>
</dependency> </dependency>
</dependencies> </dependencies>
@@ -350,13 +350,13 @@ To depend on the JPEG and TIFF plugin using Maven, add the following to your POM
To depend on the JPEG and TIFF plugin in your IDE or program, add all of the following JARs to your class path: To depend on the JPEG and TIFF plugin in your IDE or program, add all of the following JARs to your class path:
twelvemonkeys-common-lang-3.13.1.jar twelvemonkeys-common-lang-3.12.0.jar
twelvemonkeys-common-io-3.13.1.jar twelvemonkeys-common-io-3.12.0.jar
twelvemonkeys-common-image-3.13.1.jar twelvemonkeys-common-image-3.12.0.jar
twelvemonkeys-imageio-core-3.13.1.jar twelvemonkeys-imageio-core-3.12.0.jar
twelvemonkeys-imageio-metadata-3.13.1.jar twelvemonkeys-imageio-metadata-3.12.0.jar
twelvemonkeys-imageio-jpeg-3.13.1.jar twelvemonkeys-imageio-jpeg-3.12.0.jar
twelvemonkeys-imageio-tiff-3.13.1.jar twelvemonkeys-imageio-tiff-3.12.0.jar
#### Deploying the plugins in a web app #### Deploying the plugins in a web app
@@ -432,46 +432,46 @@ Other "fat" JAR bundlers will probably have similar mechanisms to merge entries
### Links to prebuilt binaries ### Links to prebuilt binaries
##### Latest version (3.13.1) ##### Latest version (3.12.0)
The latest version that will run on Java 7 is 3.9.4. Later versions will require Java 8 or later. The latest version that will run on Java 7 is 3.9.4. Later versions will require Java 8 or later.
Common dependencies Common dependencies
* [common-lang-3.13.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/common/common-lang/3.13.1/common-lang-3.13.1.jar) * [common-lang-3.12.0.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/common/common-lang/3.12.0/common-lang-3.12.0.jar)
* [common-io-3.13.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/common/common-io/3.13.1/common-io-3.13.1.jar) * [common-io-3.12.0.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/common/common-io/3.12.0/common-io-3.12.0.jar)
* [common-image-3.13.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/common/common-image/3.13.1/common-image-3.13.1.jar) * [common-image-3.12.0.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/common/common-image/3.12.0/common-image-3.12.0.jar)
ImageIO dependencies ImageIO dependencies
* [imageio-core-3.13.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-core/3.13.1/imageio-core-3.13.1.jar) * [imageio-core-3.12.0.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-core/3.12.0/imageio-core-3.12.0.jar)
* [imageio-metadata-3.13.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-metadata/3.13.1/imageio-metadata-3.13.1.jar) * [imageio-metadata-3.12.0.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-metadata/3.12.0/imageio-metadata-3.12.0.jar)
ImageIO plugins ImageIO plugins
* [imageio-bmp-3.13.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-bmp/3.13.1/imageio-bmp-3.13.1.jar) * [imageio-bmp-3.12.0.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-bmp/3.12.0/imageio-bmp-3.12.0.jar)
* [imageio-dds-3.13.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-dds/3.13.1/imageio-dds-3.13.1.jar) * [imageio-dds-3.12.0.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-dds/3.12.0/imageio-dds-3.12.0.jar)
* [imageio-hdr-3.13.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-hdr/3.13.1/imageio-hdr-3.13.1.jar) * [imageio-hdr-3.12.0.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-hdr/3.12.0/imageio-hdr-3.12.0.jar)
* [imageio-icns-3.13.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-icns/3.13.1/imageio-icns-3.13.1.jar) * [imageio-icns-3.12.0.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-icns/3.12.0/imageio-icns-3.12.0.jar)
* [imageio-iff-3.13.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-iff/3.13.1/imageio-iff-3.13.1.jar) * [imageio-iff-3.12.0.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-iff/3.12.0/imageio-iff-3.12.0.jar)
* [imageio-jpeg-3.13.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-jpeg/3.13.1/imageio-jpeg-3.13.1.jar) * [imageio-jpeg-3.12.0.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-jpeg/3.12.0/imageio-jpeg-3.12.0.jar)
* [imageio-pcx-3.13.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-pcx/3.13.1/imageio-pcx-3.13.1.jar) * [imageio-pcx-3.12.0.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-pcx/3.12.0/imageio-pcx-3.12.0.jar)
* [imageio-pict-3.13.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-pict/3.13.1/imageio-pict-3.13.1.jar) * [imageio-pict-3.12.0.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-pict/3.12.0/imageio-pict-3.12.0.jar)
* [imageio-pnm-3.13.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-pnm/3.13.1/imageio-pnm-3.13.1.jar) * [imageio-pnm-3.12.0.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-pnm/3.12.0/imageio-pnm-3.12.0.jar)
* [imageio-psd-3.13.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-psd/3.13.1/imageio-psd-3.13.1.jar) * [imageio-psd-3.12.0.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-psd/3.12.0/imageio-psd-3.12.0.jar)
* [imageio-sgi-3.13.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-sgi/3.13.1/imageio-sgi-3.13.1.jar) * [imageio-sgi-3.12.0.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-sgi/3.12.0/imageio-sgi-3.12.0.jar)
* [imageio-tga-3.13.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-tga/3.13.1/imageio-tga-3.13.1.jar) * [imageio-tga-3.12.0.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-tga/3.12.0/imageio-tga-3.12.0.jar)
* [imageio-thumbsdb-3.13.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-thumbsdb/3.13.1/imageio-thumbsdb-3.13.1.jar) * [imageio-thumbsdb-3.12.0.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-thumbsdb/3.12.0/imageio-thumbsdb-3.12.0.jar)
* [imageio-tiff-3.13.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-tiff/3.13.1/imageio-tiff-3.13.1.jar) * [imageio-tiff-3.12.0.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-tiff/3.12.0/imageio-tiff-3.12.0.jar)
* [imageio-webp-3.13.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-webp/3.13.1/imageio-webp-3.13.1.jar) * [imageio-webp-3.12.0.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-webp/3.12.0/imageio-webp-3.12.0.jar)
* [imageio-xwd-3.13.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-xwd/3.13.1/imageio-xwd-3.13.1.jar) * [imageio-xwd-3.12.0.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-xwd/3.12.0/imageio-xwd-3.12.0.jar)
ImageIO plugins requiring 3rd party libs ImageIO plugins requiring 3rd party libs
* [imageio-batik-3.13.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-batik/3.13.1/imageio-batik-3.13.1.jar) * [imageio-batik-3.12.0.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-batik/3.12.0/imageio-batik-3.12.0.jar)
Photoshop Path support for ImageIO Photoshop Path support for ImageIO
* [imageio-clippath-3.13.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-clippath/3.13.1/imageio-clippath-3.13.1.jar) * [imageio-clippath-3.12.0.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-clippath/3.12.0/imageio-clippath-3.12.0.jar)
Servlet support Servlet support
* [servlet-3.13.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/servlet/servlet/3.13.1/servlet-3.13.1.jar) for legacy Java EE (javax.servlet) * [servlet-3.12.0.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/servlet/servlet/3.12.0/servlet-3.12.0.jar) for legacy Java EE (javax.servlet)
* [servlet-3.13.1-jakarta.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/servlet/servlet/3.13.1/servlet-3.13.1-jakrta.jar) for Jakarta EE (jakarta.servlet) * [servlet-3.12.0-jakarta.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/servlet/servlet/3.12.0/servlet-3.12.0-jakrta.jar) for Jakarta EE (jakarta.servlet)
## License ## License
+1 -1
View File
@@ -5,7 +5,7 @@
<parent> <parent>
<groupId>com.twelvemonkeys</groupId> <groupId>com.twelvemonkeys</groupId>
<artifactId>twelvemonkeys</artifactId> <artifactId>twelvemonkeys</artifactId>
<version>3.13.2-SNAPSHOT</version> <version>3.12.1-SNAPSHOT</version>
</parent> </parent>
<groupId>com.twelvemonkeys.bom</groupId> <groupId>com.twelvemonkeys.bom</groupId>
+1 -1
View File
@@ -4,7 +4,7 @@
<parent> <parent>
<groupId>com.twelvemonkeys.common</groupId> <groupId>com.twelvemonkeys.common</groupId>
<artifactId>common</artifactId> <artifactId>common</artifactId>
<version>3.13.2-SNAPSHOT</version> <version>3.12.1-SNAPSHOT</version>
</parent> </parent>
<artifactId>common-image</artifactId> <artifactId>common-image</artifactId>
<packaging>jar</packaging> <packaging>jar</packaging>
@@ -47,10 +47,10 @@ import java.util.Random;
* |3|5|1| * |3|5|1|
* - - --> * - - -->
* </p> * </p>
* <table border="1"> * <table border="1" cellpadding="4" cellspacing="0">
* <caption>Floyd-Steinberg error-diffusion weights</caption> * <caption>Floyd-Steinberg error-diffusion weights</caption>
* <tr><td style="background:#000000">&nbsp;</td><td class="TableHeadingColor" * <tr><td bgcolor="#000000">&nbsp;</td><td class="TableHeadingColor"
* style="text-align:center">x</td><td>7/16</td></tr> * align="center">x</td><td>7/16</td></tr>
* <tr><td>3/16</td><td>5/16</td><td>1/16</td></tr> * <tr><td>3/16</td><td>5/16</td><td>1/16</td></tr>
* </table> * </table>
* <p> * <p>
@@ -162,7 +162,7 @@ public final class ImageUtil {
/** /**
* The sharpen kernel. Uses the following 3 by 3 matrix: * The sharpen kernel. Uses the following 3 by 3 matrix:
* <table border="1"> * <table border="1" cellspacing="0">
* <caption>Sharpen Kernel Matrix</caption> * <caption>Sharpen Kernel Matrix</caption>
* <tr><td>0.0</td><td>-0.3</td><td>0.0</td></tr> * <tr><td>0.0</td><td>-0.3</td><td>0.0</td></tr>
* <tr><td>-0.3</td><td>2.2</td><td>-0.3</td></tr> * <tr><td>-0.3</td><td>2.2</td><td>-0.3</td></tr>
@@ -1078,7 +1078,7 @@ public final class ImageUtil {
/** /**
* Sharpens an image using a convolution matrix. * Sharpens an image using a convolution matrix.
* The sharpen kernel used, is defined by the following 3 by 3 matrix: * The sharpen kernel used, is defined by the following 3 by 3 matrix:
* <table border="1"> * <table border="1" cellspacing="0">
* <caption>Sharpen Kernel Matrix</caption> * <caption>Sharpen Kernel Matrix</caption>
* <tr><td>0.0</td><td>-0.3</td><td>0.0</td></tr> * <tr><td>0.0</td><td>-0.3</td><td>0.0</td></tr>
* <tr><td>-0.3</td><td>2.2</td><td>-0.3</td></tr> * <tr><td>-0.3</td><td>2.2</td><td>-0.3</td></tr>
@@ -1100,7 +1100,7 @@ public final class ImageUtil {
/** /**
* Sharpens an image using a convolution matrix. * Sharpens an image using a convolution matrix.
* The sharpen kernel used, is defined by the following 3 by 3 matrix: * The sharpen kernel used, is defined by the following 3 by 3 matrix:
* <table border="1"> * <table border="1" cellspacing="0">
* <caption>Sharpen Kernel Matrix</caption> * <caption>Sharpen Kernel Matrix</caption>
* <tr><td>0.0</td><td>-{@code pAmount}</td><td>0.0</td></tr> * <tr><td>0.0</td><td>-{@code pAmount}</td><td>0.0</td></tr>
* <tr><td>-{@code pAmount}</td> * <tr><td>-{@code pAmount}</td>
+1 -1
View File
@@ -4,7 +4,7 @@
<parent> <parent>
<groupId>com.twelvemonkeys.common</groupId> <groupId>com.twelvemonkeys.common</groupId>
<artifactId>common</artifactId> <artifactId>common</artifactId>
<version>3.13.2-SNAPSHOT</version> <version>3.12.1-SNAPSHOT</version>
</parent> </parent>
<artifactId>common-io</artifactId> <artifactId>common-io</artifactId>
<packaging>jar</packaging> <packaging>jar</packaging>
+1 -1
View File
@@ -4,7 +4,7 @@
<parent> <parent>
<groupId>com.twelvemonkeys.common</groupId> <groupId>com.twelvemonkeys.common</groupId>
<artifactId>common</artifactId> <artifactId>common</artifactId>
<version>3.13.2-SNAPSHOT</version> <version>3.12.1-SNAPSHOT</version>
</parent> </parent>
<artifactId>common-lang</artifactId> <artifactId>common-lang</artifactId>
<packaging>jar</packaging> <packaging>jar</packaging>
@@ -1765,11 +1765,12 @@ public final class StringUtil {
* expression. * expression.
* <p> * <p>
* An invocation of this method of the form * An invocation of this method of the form
* {@code matches(str, regex)} yields exactly the * <tt>matches(<i>str</i>, <i>regex</i>)</tt> yields exactly the
* same result as the expression * same result as the expression
* </p> * </p>
* <blockquote>{@link Pattern}. * <blockquote><tt> {@link Pattern}.
* {@link Pattern#matches(String, CharSequence) matches(regex, str)}</blockquote> * {@link Pattern#matches(String, CharSequence) matches}
* (<i>regex</i>, <i>str</i>)</tt></blockquote>
* *
* @param pString the string * @param pString the string
* @param pRegex the regular expression to which this string is to be matched * @param pRegex the regular expression to which this string is to be matched
@@ -1788,14 +1789,16 @@ public final class StringUtil {
* regular expression with the given pReplacement. * regular expression with the given pReplacement.
* <p> * <p>
* An invocation of this method of the form * An invocation of this method of the form
* {@code replaceFirst(str, regex, repl)} * <tt>
* replaceFirst(<i>str</i>, <i>regex</i>, <i>repl</i>)
* </tt>
* yields exactly the same result as the expression: * yields exactly the same result as the expression:
* </p> * </p>
* <blockquote> * <blockquote><tt>
* {@link Pattern#compile(String) Pattern.compile(regex)} * {@link Pattern}.{@link Pattern#compile(String) compile}(<i>regex</i>).
* {@link Pattern#matcher .matcher(str)} * {@link Pattern#matcher matcher}(<i>str</i>).
* {@link java.util.regex.Matcher#replaceFirst .replaceFirst(repl)} * {@link java.util.regex.Matcher#replaceFirst replaceFirst}(<i>repl</i>)
* </blockquote> * </tt></blockquote>
* *
* @param pString the string * @param pString the string
* @param pRegex the regular expression to which this string is to be matched * @param pRegex the regular expression to which this string is to be matched
@@ -1814,14 +1817,14 @@ public final class StringUtil {
* regular expression with the given pReplacement. * regular expression with the given pReplacement.
* <p> * <p>
* An invocation of this method of the form * An invocation of this method of the form
* {@code replaceAll(str, pRegex, repl)} * <tt>replaceAll(<i>str</i>, <i>pRegex</i>, <i>repl</i>)</tt>
* yields exactly the same result as the expression * yields exactly the same result as the expression
* </p> * </p>
* <blockquote> * <blockquote><tt>
* {@link Pattern#compile(String) Pattern.compile(pRegex)} * {@link Pattern}.{@link Pattern#compile(String) compile}(<i>pRegex</i>).
* {@link Pattern#matcher .matcher(str)} * {@link Pattern#matcher matcher}(<i>str</i>{@code ).
* {@link java.util.regex.Matcher#replaceAll .replaceAll(repl)} * {@link java.util.regex.Matcher#replaceAll replaceAll}(}<i>repl</i>{@code )}
* </blockquote> * </tt></blockquote>
* *
* @param pString the string * @param pString the string
* @param pRegex the regular expression to which this string is to be matched * @param pRegex the regular expression to which this string is to be matched
@@ -1859,12 +1862,12 @@ public final class StringUtil {
* </p> * </p>
* <p> * <p>
* An invocation of this method of the form * An invocation of this method of the form
* {@code split(str, regex, n)} * <tt>split(<i>str</i>, <i>regex</i>, <i>n</i>)</tt>
* yields the same result as the expression: * yields the same result as the expression:
* </p> * </p>
* <blockquote>{@link Pattern}. * <blockquote>{@link Pattern}.
* {@link Pattern#compile(String) compile(regex)}. * {@link Pattern#compile(String) compile}<tt>(<i>regex</i>).
* {@link Pattern#split(CharSequence,int) split(str, n)} * {@link Pattern#split(CharSequence,int) split}(<i>str</i>, <i>n</i>)</tt>
* </blockquote> * </blockquote>
* *
* @param pString the string * @param pString the string
+2 -2
View File
@@ -4,7 +4,7 @@
<parent> <parent>
<groupId>com.twelvemonkeys</groupId> <groupId>com.twelvemonkeys</groupId>
<artifactId>twelvemonkeys</artifactId> <artifactId>twelvemonkeys</artifactId>
<version>3.13.2-SNAPSHOT</version> <version>3.12.1-SNAPSHOT</version>
</parent> </parent>
<groupId>com.twelvemonkeys.common</groupId> <groupId>com.twelvemonkeys.common</groupId>
<artifactId>common</artifactId> <artifactId>common</artifactId>
@@ -21,7 +21,7 @@
</modules> </modules>
<properties> <properties>
<junit.jupiter.version>5.14.2</junit.jupiter.version> <junit.jupiter.version>5.13.0</junit.jupiter.version>
</properties> </properties>
<dependencyManagement> <dependencyManagement>
+2 -2
View File
@@ -4,7 +4,7 @@
<parent> <parent>
<groupId>com.twelvemonkeys</groupId> <groupId>com.twelvemonkeys</groupId>
<artifactId>twelvemonkeys</artifactId> <artifactId>twelvemonkeys</artifactId>
<version>3.13.2-SNAPSHOT</version> <version>3.12.1-SNAPSHOT</version>
</parent> </parent>
<groupId>com.twelvemonkeys.contrib</groupId> <groupId>com.twelvemonkeys.contrib</groupId>
<artifactId>contrib</artifactId> <artifactId>contrib</artifactId>
@@ -14,7 +14,7 @@
</description> </description>
<properties> <properties>
<junit.jupiter.version>5.14.2</junit.jupiter.version> <junit.jupiter.version>5.13.0</junit.jupiter.version>
</properties> </properties>
+2 -2
View File
@@ -4,7 +4,7 @@
<parent> <parent>
<groupId>com.twelvemonkeys.imageio</groupId> <groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio</artifactId> <artifactId>imageio</artifactId>
<version>3.13.2-SNAPSHOT</version> <version>3.12.1-SNAPSHOT</version>
</parent> </parent>
<artifactId>imageio-batik</artifactId> <artifactId>imageio-batik</artifactId>
<name>TwelveMonkeys :: ImageIO :: Batik Plugin</name> <name>TwelveMonkeys :: ImageIO :: Batik Plugin</name>
@@ -63,7 +63,7 @@
<dependency> <dependency>
<groupId>commons-io</groupId> <groupId>commons-io</groupId>
<artifactId>commons-io</artifactId> <artifactId>commons-io</artifactId>
<version>2.21.0</version> <version>2.19.0</version>
<scope>provided</scope> <scope>provided</scope>
</dependency> </dependency>
@@ -36,11 +36,9 @@ import com.twelvemonkeys.lang.SystemUtil;
import javax.imageio.ImageReader; import javax.imageio.ImageReader;
import javax.imageio.spi.ServiceRegistry; import javax.imageio.spi.ServiceRegistry;
import javax.imageio.stream.ImageInputStream; import javax.imageio.stream.ImageInputStream;
import java.io.ByteArrayOutputStream;
import java.io.EOFException; import java.io.EOFException;
import java.io.IOException; import java.io.IOException;
import java.util.Locale; import java.util.Locale;
import java.util.function.Predicate;
import static com.twelvemonkeys.imageio.util.IIOUtil.deregisterProvider; import static com.twelvemonkeys.imageio.util.IIOUtil.deregisterProvider;
@@ -136,42 +134,10 @@ public final class SVGImageReaderSpi extends ImageReaderSpiBase {
if (buffer[0] == 's' && buffer[1] == 'v' && buffer[2] == 'g' if (buffer[0] == 's' && buffer[1] == 'v' && buffer[2] == 'g'
&& (Character.isWhitespace((char) buffer[3]) || buffer[3] == ':')) { && (Character.isWhitespace((char) buffer[3]) || buffer[3] == ':')) {
// It's SVG, identified by root tag // It's SVG, identified by root tag
// TODO: Support svg with prefix + recognize namespace (http://www.w3.org/2000/svg)!
return true; return true;
} }
// Read the full tag name (may contain a prefix of any length)
final int MAX_TAG_NAME = 256;
ByteArrayOutputStream nameBuf = new ByteArrayOutputStream(MAX_TAG_NAME);
// We already have 4 bytes in 'buffer' (from input.readFully(buffer))
int consumedFromBuffer = 0;
for (; consumedFromBuffer < buffer.length; consumedFromBuffer++) {
byte bb = buffer[consumedFromBuffer];
if (bb == '>' || Character.isWhitespace((char) bb) || bb == '/') {
break;
}
nameBuf.write(bb);
}
// If tag name not terminated yet, keep reading bytes (within limit)
final boolean incompleteTagName = consumedFromBuffer == buffer.length;
readBuffer(input, nameBuf, output -> incompleteTagName && output.size() < MAX_TAG_NAME,
bb -> bb == '>' || Character.isWhitespace(bb) || bb == '/');
final String name = nameBuf.toString("US-ASCII");
if (name.toLowerCase(Locale.ENGLISH).endsWith(":svg")) {
// Scan the rest of the tag attributes until '>' to find the SVG namespace URI
ByteArrayOutputStream attrBuf = new ByteArrayOutputStream();
final int MAX_ATTR_SCAN = 1024; // safe upper bound to keep it fast
readBuffer(input, attrBuf, output -> output.size() < MAX_ATTR_SCAN, bb -> bb == '>');
// If the tag contains the SVG namespace, it's SVG.
if (attrBuf.toString("US-ASCII").matches(
".*xmlns:" + name.split(":")[0] + "\\s*=\\s*\"http://www.w3.org/2000/svg\".*")) {
return true;
}
}
// If the tag is not "svg", this isn't SVG // If the tag is not "svg", this isn't SVG
return false; return false;
} }
@@ -191,17 +157,6 @@ public final class SVGImageReaderSpi extends ImageReaderSpiBase {
} }
} }
private static void readBuffer(final ImageInputStream input, final ByteArrayOutputStream buffer,
final Predicate<ByteArrayOutputStream> loopCondition, Predicate<Byte> breakCondition) throws IOException {
while (loopCondition.test(buffer)) {
byte bb = input.readByte();
if (breakCondition.test(bb)) {
break;
}
buffer.write(bb);
}
}
public ImageReader createReaderInstance(final Object extension) throws IOException { public ImageReader createReaderInstance(final Object extension) throws IOException {
return new SVGImageReader(this); return new SVGImageReader(this);
} }
@@ -56,7 +56,7 @@ public class SVGImageReaderSpiTest {
"/svg/Android_robot.svg", // Minimal, no xml dec, no namespace "/svg/Android_robot.svg", // Minimal, no xml dec, no namespace
"/svg/batikLogo.svg", // xml dec, comments, namespace "/svg/batikLogo.svg", // xml dec, comments, namespace
"/svg/blue-square.svg", // xml dec, namespace "/svg/blue-square.svg", // xml dec, namespace
"/svg/red-square.svg", // prefixed namespace "/svg/red-square.svg",
}; };
private static final String[] INVALID_INPUTS = { private static final String[] INVALID_INPUTS = {
@@ -70,9 +70,6 @@ public class SVGImageReaderSpiTest {
"<!-- ", // #275 Infinite loop issue "<!-- ", // #275 Infinite loop issue
"<?123?>", // #275 Infinite loop issue "<?123?>", // #275 Infinite loop issue
"<svg", "<svg",
"<ns0:svg>", // namespace prefix undefined
"<ns0:svg xmlns:ns0=\"foo\">", // not the official svg namespace
"<ns0:svg xmlns:ns1=\"http://www.w3.org/2000/svg\">", // mismatching prefix
}; };
static { static {
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <?xml version="1.0" encoding="UTF-8" standalone="no"?>
<ns0:svg xmlns:ns0="http://www.w3.org/2000/svg" width="100" height="100" id="red-square" version="1.1"> <svg xmlns="http://www.w3.org/2000/svg" width="100" height="100" id="red-square" version="1.1">
<ns0:g id="layer1"> <g id="layer1">
<ns0:rect id="rect2985" width="100" height="100" x="0" y="0" <rect id="rect2985" width="100" height="100" x="0" y="0"
style="color:#000000;fill:#ff0000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" /> style="color:#000000;fill:#ff0000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
</ns0:g> </g>
</ns0:svg> </svg>

Before

Width:  |  Height:  |  Size: 465 B

After

Width:  |  Height:  |  Size: 441 B

+1 -1
View File
@@ -4,7 +4,7 @@
<parent> <parent>
<groupId>com.twelvemonkeys.imageio</groupId> <groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio</artifactId> <artifactId>imageio</artifactId>
<version>3.13.2-SNAPSHOT</version> <version>3.12.1-SNAPSHOT</version>
</parent> </parent>
<artifactId>imageio-bmp</artifactId> <artifactId>imageio-bmp</artifactId>
<name>TwelveMonkeys :: ImageIO :: BMP plugin</name> <name>TwelveMonkeys :: ImageIO :: BMP plugin</name>
+1 -1
View File
@@ -4,7 +4,7 @@
<parent> <parent>
<groupId>com.twelvemonkeys.imageio</groupId> <groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio</artifactId> <artifactId>imageio</artifactId>
<version>3.13.2-SNAPSHOT</version> <version>3.12.1-SNAPSHOT</version>
</parent> </parent>
<artifactId>imageio-clippath</artifactId> <artifactId>imageio-clippath</artifactId>
<name>TwelveMonkeys :: ImageIO :: Photoshop Path Support</name> <name>TwelveMonkeys :: ImageIO :: Photoshop Path Support</name>
+1 -1
View File
@@ -4,7 +4,7 @@
<parent> <parent>
<groupId>com.twelvemonkeys.imageio</groupId> <groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio</artifactId> <artifactId>imageio</artifactId>
<version>3.13.2-SNAPSHOT</version> <version>3.12.1-SNAPSHOT</version>
</parent> </parent>
<artifactId>imageio-core</artifactId> <artifactId>imageio-core</artifactId>
<name>TwelveMonkeys :: ImageIO :: Core</name> <name>TwelveMonkeys :: ImageIO :: Core</name>
+1 -1
View File
@@ -4,7 +4,7 @@
<parent> <parent>
<groupId>com.twelvemonkeys.imageio</groupId> <groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio</artifactId> <artifactId>imageio</artifactId>
<version>3.13.2-SNAPSHOT</version> <version>3.12.1-SNAPSHOT</version>
</parent> </parent>
<artifactId>imageio-dds</artifactId> <artifactId>imageio-dds</artifactId>
<name>TwelveMonkeys :: ImageIO :: DDS plugin</name> <name>TwelveMonkeys :: ImageIO :: DDS plugin</name>
@@ -32,7 +32,7 @@ package com.twelvemonkeys.imageio.plugins.dds;
@SuppressWarnings("unused") @SuppressWarnings("unused")
interface DDS { interface DDS {
int MAGIC = ('D' << 24) + ('D' << 16) + ('S' << 8) + ' '; //Big-Endian byte[] MAGIC = new byte[]{'D', 'D', 'S', ' '};
int HEADER_SIZE = 124; int HEADER_SIZE = 124;
// Header Flags // Header Flags
@@ -48,7 +48,4 @@ interface DDS {
// Pixel Format Flags // Pixel Format Flags
int PIXEL_FORMAT_FLAG_FOURCC = 0x04; int PIXEL_FORMAT_FLAG_FOURCC = 0x04;
int PIXEL_FORMAT_FLAG_RGB = 0x40; int PIXEL_FORMAT_FLAG_RGB = 0x40;
//DX10 Resource Dimensions
int D3D10_RESOURCE_DIMENSION_TEXTURE2D = 3;
} }
@@ -34,7 +34,8 @@ import javax.imageio.IIOException;
import javax.imageio.stream.ImageInputStream; import javax.imageio.stream.ImageInputStream;
import java.awt.Dimension; import java.awt.Dimension;
import java.io.IOException; import java.io.IOException;
import java.nio.ByteOrder; import java.math.BigInteger;
import java.util.Arrays;
final class DDSHeader { final class DDSHeader {
@@ -57,12 +58,11 @@ final class DDSHeader {
DDSHeader header = new DDSHeader(); DDSHeader header = new DDSHeader();
// Read MAGIC bytes [0,3] // Read MAGIC bytes [0,3]
imageInput.setByteOrder(ByteOrder.BIG_ENDIAN); byte[] magic = new byte[DDS.MAGIC.length];
int magic = imageInput.readInt(); imageInput.readFully(magic);
if (magic != DDS.MAGIC) { if (!Arrays.equals(DDS.MAGIC, magic)) {
throw new IIOException(String.format("Not a DDS file. Expected DDS magic 0x%8x', read 0x%8x", DDS.MAGIC, magic)); throw new IIOException(String.format("Not a DDS file. Expected DDS magic 0x%08x', read 0x%08x", new BigInteger(DDS.MAGIC), new BigInteger(magic)));
} }
imageInput.setByteOrder(ByteOrder.LITTLE_ENDIAN);
// DDS_HEADER structure // DDS_HEADER structure
// https://learn.microsoft.com/en-us/windows/win32/direct3ddds/dds-header // https://learn.microsoft.com/en-us/windows/win32/direct3ddds/dds-header
@@ -93,7 +93,8 @@ final class DDSHeader {
// build dimensions list // build dimensions list
header.addDimensions(dwWidth, dwHeight); header.addDimensions(dwWidth, dwHeight);
imageInput.skipBytes(44); byte[] dwReserved1 = new byte[11 * 4]; // [32,75]
imageInput.readFully(dwReserved1);
// DDS_PIXELFORMAT structure // DDS_PIXELFORMAT structure
int px_dwSize = imageInput.readInt(); // [76,79] int px_dwSize = imageInput.readInt(); // [76,79]
@@ -35,6 +35,7 @@ import com.twelvemonkeys.imageio.spi.ImageReaderSpiBase;
import javax.imageio.ImageReader; import javax.imageio.ImageReader;
import javax.imageio.stream.ImageInputStream; import javax.imageio.stream.ImageInputStream;
import java.io.IOException; import java.io.IOException;
import java.util.Arrays;
import java.util.Locale; import java.util.Locale;
public final class DDSImageReaderSpi extends ImageReaderSpiBase { public final class DDSImageReaderSpi extends ImageReaderSpiBase {
@@ -54,7 +55,10 @@ public final class DDSImageReaderSpi extends ImageReaderSpiBase {
stream.mark(); stream.mark();
try { try {
return stream.readInt() == DDS.MAGIC; byte[] magic = new byte[DDS.MAGIC.length];
stream.readFully(magic);
return Arrays.equals(DDS.MAGIC, magic);
} finally { } finally {
stream.reset(); stream.reset();
} }
@@ -74,19 +74,15 @@ final class DDSReader {
static final Order ARGB_ORDER = new Order(16, 8, 0, 24); static final Order ARGB_ORDER = new Order(16, 8, 0, 24);
private final DDSHeader header; private final DDSHeader header;
private DX10Header dxt10Header;
DDSReader(DDSHeader header) { DDSReader(DDSHeader header) {
this.header = header; this.header = header;
} }
int[] read(ImageInputStream imageInput, int imageIndex) throws IOException { int[] read(ImageInputStream imageInput, int imageIndex) throws IOException {
// type // type
DDSType type = getType(); DDSType type = getType();
if (type == DDSType.DXT10) {
dxt10Header = DX10Header.read(imageInput);
type = dxt10Header.getDDSType();
}
// offset buffer to index mipmap image // offset buffer to index mipmap image
byte[] buffer = null; byte[] buffer = null;
@@ -142,6 +138,7 @@ final class DDSReader {
// DXT // DXT
int type = header.getFourCC(); int type = header.getFourCC();
return DDSType.valueOf(type); return DDSType.valueOf(type);
} else if ((flags & DDS.PIXEL_FORMAT_FLAG_RGB) != 0) { } else if ((flags & DDS.PIXEL_FORMAT_FLAG_RGB) != 0) {
// RGB // RGB
int bitCount = header.getBitCount(); int bitCount = header.getBitCount();
@@ -227,7 +224,6 @@ final class DDSReader {
} }
} }
private static int[] decodeDXT1(int width, int height, byte[] buffer) { private static int[] decodeDXT1(int width, int height, byte[] buffer) {
int[] pixels = new int[width * height]; int[] pixels = new int[width * height];
int index = 0; int index = 0;
@@ -245,7 +241,7 @@ final class DDSReader {
int t1 = (buffer[index] & 0x0C) >> 2; int t1 = (buffer[index] & 0x0C) >> 2;
int t2 = (buffer[index] & 0x30) >> 4; int t2 = (buffer[index] & 0x30) >> 4;
int t3 = (buffer[index++] & 0xC0) >> 6; int t3 = (buffer[index++] & 0xC0) >> 6;
pixels[4 * width * i + 4 * j + width * k] = getDXTColor(c0, c1, 0xFF, t0); pixels[4 * width * i + 4 * j + width * k ] = getDXTColor(c0, c1, 0xFF, t0);
if (4 * j + 1 >= width) continue; if (4 * j + 1 >= width) continue;
pixels[4 * width * i + 4 * j + width * k + 1] = getDXTColor(c0, c1, 0xFF, t1); pixels[4 * width * i + 4 * j + width * k + 1] = getDXTColor(c0, c1, 0xFF, t1);
if (4 * j + 2 >= width) continue; if (4 * j + 2 >= width) continue;
@@ -290,7 +286,7 @@ final class DDSReader {
int t1 = (buffer[index] & 0x0C) >> 2; int t1 = (buffer[index] & 0x0C) >> 2;
int t2 = (buffer[index] & 0x30) >> 4; int t2 = (buffer[index] & 0x30) >> 4;
int t3 = (buffer[index++] & 0xC0) >> 6; int t3 = (buffer[index++] & 0xC0) >> 6;
pixels[4 * width * i + 4 * j + width * k] = getDXTColor(c0, c1, alphaTable[4 * k], t0); pixels[4 * width * i + 4 * j + width * k ] = getDXTColor(c0, c1, alphaTable[4 * k ], t0);
if (4 * j + 1 >= width) continue; if (4 * j + 1 >= width) continue;
pixels[4 * width * i + 4 * j + width * k + 1] = getDXTColor(c0, c1, alphaTable[4 * k + 1], t1); pixels[4 * width * i + 4 * j + width * k + 1] = getDXTColor(c0, c1, alphaTable[4 * k + 1], t1);
if (4 * j + 2 >= width) continue; if (4 * j + 2 >= width) continue;
@@ -348,7 +344,7 @@ final class DDSReader {
int t1 = (buffer[index] & 0x0C) >> 2; int t1 = (buffer[index] & 0x0C) >> 2;
int t2 = (buffer[index] & 0x30) >> 4; int t2 = (buffer[index] & 0x30) >> 4;
int t3 = (buffer[index++] & 0xC0) >> 6; int t3 = (buffer[index++] & 0xC0) >> 6;
pixels[4 * width * i + 4 * j + width * k] = getDXTColor(c0, c1, getDXT5Alpha(a0, a1, alphaTable[4 * k]), t0); pixels[4 * width * i + 4 * j + width * k ] = getDXTColor(c0, c1, getDXT5Alpha(a0, a1, alphaTable[4 * k ]), t0);
if (4 * j + 1 >= width) continue; if (4 * j + 1 >= width) continue;
pixels[4 * width * i + 4 * j + width * k + 1] = getDXTColor(c0, c1, getDXT5Alpha(a0, a1, alphaTable[4 * k + 1]), t1); pixels[4 * width * i + 4 * j + width * k + 1] = getDXTColor(c0, c1, getDXT5Alpha(a0, a1, alphaTable[4 * k + 1]), t1);
if (4 * j + 2 >= width) continue; if (4 * j + 2 >= width) continue;
@@ -31,12 +31,12 @@
package com.twelvemonkeys.imageio.plugins.dds; package com.twelvemonkeys.imageio.plugins.dds;
enum DDSType { enum DDSType {
DXT1(0x31545844), DXT1(0x31545844),
DXT2(0x32545844), DXT2(0x32545844),
DXT3(0x33545844), DXT3(0x33545844),
DXT4(0x34545844), DXT4(0x34545844),
DXT5(0x35545844), DXT5(0x35545844),
DXT10(0x30315844),
A1R5G5B5((1 << 16) | 2), A1R5G5B5((1 << 16) | 2),
X1R5G5B5((2 << 16) | 2), X1R5G5B5((2 << 16) | 2),
A4R4G4B4((3 << 16) | 2), A4R4G4B4((3 << 16) | 2),
@@ -1,50 +0,0 @@
package com.twelvemonkeys.imageio.plugins.dds;
import java.util.Arrays;
import java.util.function.IntPredicate;
/**
* Enum that lists a certain types of DXGI Format this reader supports to read.
*
* <a href="https://learn.microsoft.com/en-us/windows/win32/api/dxgiformat/ne-dxgiformat-dxgi_format">DXGI Format List</a>
*/
public enum DX10DXGIFormat {
BC1(DDSType.DXT1, rangeInclusive(70, 72)),
BC2(DDSType.DXT2, rangeInclusive(73, 75)),
BC3(DDSType.DXT5, rangeInclusive(76, 78)),
//BC7(99),
B8G8R8A8(DDSType.A8B8G8R8, exactly(87, 90, 91)),
B8G8R8X8(DDSType.X8B8G8R8, exactly(88, 92, 93)),
R8G8B8A8(DDSType.A8R8G8B8, rangeInclusive(27, 32));
private final DDSType ddsType;
private final IntPredicate dxgiFormat;
DX10DXGIFormat(DDSType ddsType, IntPredicate dxgiFormat) {
this.ddsType = ddsType;
this.dxgiFormat = dxgiFormat;
}
DDSType getCorrespondingType() {
return ddsType;
}
static DX10DXGIFormat getFormat(int value) {
for (DX10DXGIFormat format : values()) {
if (format.dxgiFormat.test(value)) return format;
}
throw new IllegalArgumentException("Unsupported DXGI_FORMAT : " + value);
}
/**
* @param acceptedValues values in DXGI Formats List, passed values are expected to be in ascending order
*/
private static IntPredicate exactly(int ... acceptedValues) {
return test -> Arrays.binarySearch(acceptedValues, test) >= 0;
}
private static IntPredicate rangeInclusive(int from, int to) {
return test -> from <= test && test <= to;
}
}
@@ -1,33 +0,0 @@
package com.twelvemonkeys.imageio.plugins.dds;
import javax.imageio.stream.ImageInputStream;
import java.io.IOException;
//https://learn.microsoft.com/en-us/windows/win32/direct3ddds/dds-header-dxt10
public final class DX10Header {
final DX10DXGIFormat dxgiFormat;
final int resourceDimension, miscFlag, arraySize, miscFlags2;
private DX10Header(int dxgiFormat, int resourceDimension, int miscFlag, int arraySize, int miscFlags2) {
this.dxgiFormat = DX10DXGIFormat.getFormat(dxgiFormat);
this.resourceDimension = resourceDimension;
if (this.resourceDimension != DDS.D3D10_RESOURCE_DIMENSION_TEXTURE2D)
throw new IllegalArgumentException("Resource dimension " + resourceDimension + " is not supported, expected 3.");
this.miscFlag = miscFlag;
this.arraySize = arraySize;
this.miscFlags2 = miscFlags2;
}
static DX10Header read(ImageInputStream inputStream) throws IOException {
int dxgiFormat = inputStream.readInt();
int resourceDimension = inputStream.readInt();
int miscFlag = inputStream.readInt();
int arraySize = inputStream.readInt();
int miscFlags2 = inputStream.readInt();
return new DX10Header(dxgiFormat, resourceDimension, miscFlag, arraySize, miscFlags2);
}
DDSType getDDSType() {
return dxgiFormat.getCorrespondingType();
}
}
@@ -86,13 +86,7 @@ public class DDSImageReaderTest extends ImageReaderAbstractTest<DDSImageReader>
new TestData(getClassLoaderResource("/dds/dds_X8B8G8R8.dds"), dim256), new TestData(getClassLoaderResource("/dds/dds_X8B8G8R8.dds"), dim256),
new TestData(getClassLoaderResource("/dds/dds_X8B8G8R8_mipmap.dds"), dim256, dim128, dim64), new TestData(getClassLoaderResource("/dds/dds_X8B8G8R8_mipmap.dds"), dim256, dim128, dim64),
new TestData(getClassLoaderResource("/dds/dds_X8R8G8B8.dds"), dim256), new TestData(getClassLoaderResource("/dds/dds_X8R8G8B8.dds"), dim256),
new TestData(getClassLoaderResource("/dds/dds_X8R8G8B8_mipmap.dds"), dim256, dim128, dim64), new TestData(getClassLoaderResource("/dds/dds_X8R8G8B8_mipmap.dds"), dim256, dim128, dim64)
new TestData(getClassLoaderResource("/dds/dxt10_BC1_sRGB.dds"), dim256),
new TestData(getClassLoaderResource("/dds/dxt10_BC2_sRGB.dds"), dim256),
new TestData(getClassLoaderResource("/dds/dxt10_BC3_sRGB.dds"), dim256),
new TestData(getClassLoaderResource("/dds/dxt10_B8G8R8A8.dds"), dim256),
new TestData(getClassLoaderResource("/dds/dxt10_B8G8R8X8.dds"), dim256),
new TestData(getClassLoaderResource("/dds/dxt10_R8G8B8A8.dds"), dim256)
); );
} }
+1 -1
View File
@@ -4,7 +4,7 @@
<parent> <parent>
<groupId>com.twelvemonkeys.imageio</groupId> <groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio</artifactId> <artifactId>imageio</artifactId>
<version>3.13.2-SNAPSHOT</version> <version>3.12.1-SNAPSHOT</version>
</parent> </parent>
<artifactId>imageio-hdr</artifactId> <artifactId>imageio-hdr</artifactId>
<name>TwelveMonkeys :: ImageIO :: HDR plugin</name> <name>TwelveMonkeys :: ImageIO :: HDR plugin</name>
+1 -1
View File
@@ -4,7 +4,7 @@
<parent> <parent>
<groupId>com.twelvemonkeys.imageio</groupId> <groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio</artifactId> <artifactId>imageio</artifactId>
<version>3.13.2-SNAPSHOT</version> <version>3.12.1-SNAPSHOT</version>
</parent> </parent>
<artifactId>imageio-icns</artifactId> <artifactId>imageio-icns</artifactId>
<name>TwelveMonkeys :: ImageIO :: ICNS plugin</name> <name>TwelveMonkeys :: ImageIO :: ICNS plugin</name>
+1 -1
View File
@@ -4,7 +4,7 @@
<parent> <parent>
<groupId>com.twelvemonkeys.imageio</groupId> <groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio</artifactId> <artifactId>imageio</artifactId>
<version>3.13.2-SNAPSHOT</version> <version>3.12.1-SNAPSHOT</version>
</parent> </parent>
<artifactId>imageio-iff</artifactId> <artifactId>imageio-iff</artifactId>
<name>TwelveMonkeys :: ImageIO :: IFF plugin</name> <name>TwelveMonkeys :: ImageIO :: IFF plugin</name>
+1 -1
View File
@@ -4,7 +4,7 @@
<parent> <parent>
<groupId>com.twelvemonkeys.imageio</groupId> <groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio</artifactId> <artifactId>imageio</artifactId>
<version>3.13.2-SNAPSHOT</version> <version>3.12.1-SNAPSHOT</version>
</parent> </parent>
<artifactId>imageio-jpeg-jai-interop</artifactId> <artifactId>imageio-jpeg-jai-interop</artifactId>
<name>TwelveMonkeys :: ImageIO :: JPEG/JAI TIFF Interop</name> <name>TwelveMonkeys :: ImageIO :: JPEG/JAI TIFF Interop</name>
+1 -1
View File
@@ -4,7 +4,7 @@
<parent> <parent>
<groupId>com.twelvemonkeys.imageio</groupId> <groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio</artifactId> <artifactId>imageio</artifactId>
<version>3.13.2-SNAPSHOT</version> <version>3.12.1-SNAPSHOT</version>
</parent> </parent>
<artifactId>imageio-jpeg-jep262-interop</artifactId> <artifactId>imageio-jpeg-jep262-interop</artifactId>
<name>TwelveMonkeys :: ImageIO :: JPEG/JEP-262 Interop</name> <name>TwelveMonkeys :: ImageIO :: JPEG/JEP-262 Interop</name>
+1 -1
View File
@@ -4,7 +4,7 @@
<parent> <parent>
<groupId>com.twelvemonkeys.imageio</groupId> <groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio</artifactId> <artifactId>imageio</artifactId>
<version>3.13.2-SNAPSHOT</version> <version>3.12.1-SNAPSHOT</version>
</parent> </parent>
<artifactId>imageio-jpeg</artifactId> <artifactId>imageio-jpeg</artifactId>
<name>TwelveMonkeys :: ImageIO :: JPEG plugin</name> <name>TwelveMonkeys :: ImageIO :: JPEG plugin</name>
@@ -212,9 +212,7 @@ final class JPEGLosslessDecoder {
final int[] firstValue = new int[numComp]; final int[] firstValue = new int[numComp];
for (int i = 0; i < numComp; i++) { for (int i = 0; i < numComp; i++) {
// scan.approxLow is the point transformation (Pt) value firstValue[i] = (1 << (precision - 1));
// ref. ISO/IEC 10918-1 H.1.2.1
firstValue[i] = (1 << (precision - scan.approxLow - 1));
} }
final int[] pred = new int[numComp]; final int[] pred = new int[numComp];
@@ -235,11 +233,6 @@ final class JPEGLosslessDecoder {
current = decode(pred, temp, index); current = decode(pred, temp, index);
} }
if ((current == JPEG.EOI) && (xLoc == xDim - 1) && (yLoc == yDim - 1)) {
// Output value left in pred if EOI is hit while decoding last pixel
output(pred);
}
break; //current=MARKER break; //current=MARKER
} }
@@ -275,17 +268,6 @@ final class JPEGLosslessDecoder {
// TODO oe: 05.05.2018 Is it correct loop? Content of outputData from previous iteration is always lost. // TODO oe: 05.05.2018 Is it correct loop? Content of outputData from previous iteration is always lost.
} while ((current != JPEG.EOI) && ((xLoc < xDim) && (yLoc < yDim)) && (scanNum == 0)); } while ((current != JPEG.EOI) && ((xLoc < xDim) && (yLoc < yDim)) && (scanNum == 0));
// Apply point transform to output. This must be done after it has finished being
// used for predictive purposes.
if (scan.approxLow != 0) {
for (int componentIndex = 0; componentIndex < numComp; ++componentIndex) {
int[] comp = outputData[componentIndex];
for (int i = 0; i < comp.length; i++) {
comp[i] = mask & (comp[i] << scan.approxLow);
}
}
}
return outputData; return outputData;
} }
@@ -347,11 +329,9 @@ final class JPEGLosslessDecoder {
private int decodeSingle(final int[] prev, final int[] temp, final int[] index) throws IOException { private int decodeSingle(final int[] prev, final int[] temp, final int[] index) throws IOException {
// At the beginning of the first line and // At the beginning of the first line and
// at the beginning of each restart interval the prediction value of 2P – 1 is used, where P is the input precision. // at the beginning of each restart interval the prediction value of 2P – 1 is used, where P is the input precision.
// If the point transformation parameter (see A.4) is non-zero, the prediction value at the beginning of the first lines and the
// beginning of each restart interval is 2P – Pt – 1 , where Pt is the value of the point transformation parameter
if (restarting) { if (restarting) {
restarting = false; restarting = false;
prev[0] = (1 << (frame.samplePrecision - scan.approxLow - 1)); prev[0] = (1 << (frame.samplePrecision - 1));
} }
else { else {
final int[] outputData = this.outputData[0]; final int[] outputData = this.outputData[0];
@@ -706,7 +686,7 @@ final class JPEGLosslessDecoder {
return getPreviousY(data); return getPreviousY(data);
} }
else { else {
return (1 << (frame.samplePrecision - scan.approxLow - 1)); return (1 << (frame.samplePrecision - 1));
} }
} }
@@ -2033,65 +2033,4 @@ public class JPEGImageReaderTest extends ImageReaderAbstractTest<JPEGImageReader
} }
}); });
} }
@Test
public void testReadLosslessJPEGGradient() throws IOException {
JPEGImageReader reader = createReader();
try (ImageInputStream stream = ImageIO.createImageInputStream(getClassLoaderResource("/jpeg-lossless/gradient_ls.jpg"))) {
reader.setInput(stream);
assertEquals(256, reader.getWidth(0));
assertEquals(256, reader.getHeight(0));
BufferedImage image = reader.read(0, null);
assertNotNull(image);
assertEquals(256, image.getWidth());
assertEquals(256, image.getHeight());
assertEquals(16, image.getColorModel().getComponentSize(0));
for (int y = 0; y < 256; y++) {
for (int x = 0; x < 256; x++) {
assertEquals((y << 8) | x, image.getRaster().getSample(x, y, 0));
}
}
}
finally {
reader.dispose();
}
}
@Test
public void testReadLosslessJPEGGradientWithPointTransform() throws IOException {
JPEGImageReader reader = createReader();
try (ImageInputStream stream = ImageIO.createImageInputStream(getClassLoaderResource("/jpeg-lossless/gradient_ls_pt.jpg"))) {
reader.setInput(stream);
assertEquals(256, reader.getWidth(0));
assertEquals(256, reader.getHeight(0));
BufferedImage image = reader.read(0, null);
assertNotNull(image);
assertEquals(256, image.getWidth());
assertEquals(256, image.getHeight());
assertEquals(16, image.getColorModel().getComponentSize(0));
for (int y = 0; y < 256; y++) {
for (int x = 0; x < 256; x++) {
int expected = (y << 8) | x;
// Simulate effect of precision loss due to point transform = 4
expected = (expected >> 4) << 4;
assertEquals(expected, image.getRaster().getSample(x, y, 0));
}
}
}
finally {
reader.dispose();
}
}
} }
Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.2 KiB

+1 -1
View File
@@ -3,7 +3,7 @@
<parent> <parent>
<groupId>com.twelvemonkeys.imageio</groupId> <groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio</artifactId> <artifactId>imageio</artifactId>
<version>3.13.2-SNAPSHOT</version> <version>3.12.1-SNAPSHOT</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<artifactId>imageio-metadata</artifactId> <artifactId>imageio-metadata</artifactId>
@@ -41,11 +41,7 @@ import javax.imageio.stream.ImageOutputStream;
import java.io.IOException; import java.io.IOException;
import java.nio.ByteOrder; import java.nio.ByteOrder;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.util.ArrayList; import java.util.*;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import static com.twelvemonkeys.imageio.metadata.tiff.TIFFEntry.getType; import static com.twelvemonkeys.imageio.metadata.tiff.TIFFEntry.getType;
import static com.twelvemonkeys.imageio.metadata.tiff.TIFFEntry.getValueLength; import static com.twelvemonkeys.imageio.metadata.tiff.TIFFEntry.getValueLength;
@@ -180,7 +176,7 @@ public final class TIFFWriter extends MetadataWriter {
stream.seek(dataOffset); stream.seek(dataOffset);
Directory subIFD = (Directory) value; Directory subIFD = (Directory) value;
writeIFD(subIFD, stream, true); writeIFD(subIFD, stream, true);
dataOffset += computeDataSize(subIFD) + directoryCountLength + subIFD.size() * entryLength; dataOffset += computeDataSize(subIFD);
stream.seek(streamPosition); stream.seek(streamPosition);
} }
else { else {
@@ -30,23 +30,14 @@
package com.twelvemonkeys.imageio.metadata.tiff; package com.twelvemonkeys.imageio.metadata.tiff;
import com.twelvemonkeys.imageio.metadata.AbstractDirectory; import com.twelvemonkeys.imageio.metadata.*;
import com.twelvemonkeys.imageio.metadata.AbstractEntry;
import com.twelvemonkeys.imageio.metadata.CompoundDirectory;
import com.twelvemonkeys.imageio.metadata.Directory;
import com.twelvemonkeys.imageio.metadata.Entry;
import com.twelvemonkeys.imageio.metadata.MetadataWriterAbstractTest;
import com.twelvemonkeys.imageio.metadata.exif.EXIF;
import com.twelvemonkeys.imageio.stream.ByteArrayImageInputStream; import com.twelvemonkeys.imageio.stream.ByteArrayImageInputStream;
import com.twelvemonkeys.io.FastByteArrayOutputStream; import com.twelvemonkeys.io.FastByteArrayOutputStream;
import org.junit.jupiter.api.Test;
import javax.imageio.ImageIO; import javax.imageio.ImageIO;
import javax.imageio.stream.ImageInputStream;
import javax.imageio.stream.ImageOutputStream; import javax.imageio.stream.ImageOutputStream;
import javax.imageio.stream.ImageOutputStreamImpl; import javax.imageio.stream.ImageOutputStreamImpl;
import javax.imageio.stream.MemoryCacheImageOutputStream;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
@@ -55,10 +46,8 @@ import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import static org.junit.jupiter.api.Assertions.assertArrayEquals; import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.*;
import static org.junit.jupiter.api.Assertions.assertInstanceOf;
import static org.junit.jupiter.api.Assertions.assertNotNull;
/** /**
* TIFFWriterTest * TIFFWriterTest
@@ -283,7 +272,7 @@ public class TIFFWriterTest extends MetadataWriterAbstractTest {
Directory read = new TIFFReader().read(new ByteArrayImageInputStream(data)); Directory read = new TIFFReader().read(new ByteArrayImageInputStream(data));
assertNotNull(read.getEntryById(TIFF.TAG_SOFTWARE)); assertNotNull(read.getEntryById(TIFF.TAG_SOFTWARE));
assertInstanceOf(String[].class, read.getEntryById(TIFF.TAG_SOFTWARE).getValue(), "value not an string array"); assertTrue(read.getEntryById(TIFF.TAG_SOFTWARE).getValue() instanceof String[], "value not an string array");
assertArrayEquals(strings, (String[]) read.getEntryById(TIFF.TAG_SOFTWARE).getValue()); assertArrayEquals(strings, (String[]) read.getEntryById(TIFF.TAG_SOFTWARE).getValue());
} }
@@ -296,7 +285,7 @@ public class TIFFWriterTest extends MetadataWriterAbstractTest {
TIFFEntry subSubIFD = new TIFFEntry(TIFF.TAG_SUB_IFD, TIFF.TYPE_LONG, new IFD(Collections.singletonList(subSubSubIFD))); TIFFEntry subSubIFD = new TIFFEntry(TIFF.TAG_SUB_IFD, TIFF.TYPE_LONG, new IFD(Collections.singletonList(subSubSubIFD)));
TIFFEntry subIFD = new TIFFEntry(TIFF.TAG_SUB_IFD, TIFF.TYPE_LONG, new IFD(Collections.singletonList(subSubIFD))); TIFFEntry subIFD = new TIFFEntry(TIFF.TAG_SUB_IFD, TIFF.TYPE_LONG, new IFD(Collections.singletonList(subSubIFD)));
List<Entry> entries = Collections.singletonList(subIFD); List<Entry> entries = Collections.<Entry>singletonList(subIFD);
TIFFWriter writer = createWriter(); TIFFWriter writer = createWriter();
@@ -307,67 +296,24 @@ public class TIFFWriterTest extends MetadataWriterAbstractTest {
assertEquals(96, stream.getStreamPosition()); // 96 = 4 + 5 * (2 + 12) + 22 assertEquals(96, stream.getStreamPosition()); // 96 = 4 + 5 * (2 + 12) + 22
} }
@Test private static class NullImageOutputStream extends ImageOutputStreamImpl {
void testWriteNestedExifIFD() throws IOException {
String expectedUserComment = "This ia the expected user comment";
String expectedDateTime = "2026:01:01 00:00:01";
List<Entry> entries = new ArrayList<>();
List<Entry> subDirectoryEntries = new ArrayList<>();
subDirectoryEntries.add(new TIFFEntry(EXIF.TAG_USER_COMMENT, TIFF.TYPE_ASCII, expectedUserComment));
entries.add(new TIFFEntry(TIFF.TAG_DATE_TIME, expectedDateTime));
entries.add(new TIFFEntry(TIFF.TAG_EXIF_IFD, TIFF.TYPE_IFD, new IFD(subDirectoryEntries)));
// NOTE! For the test, it is important that this tag is > Exif IFD and inside IDF0 (even if this is an Exif tag)
entries.add(new TIFFEntry(EXIF.TAG_DATE_TIME_ORIGINAL, TIFF.TYPE_ASCII, expectedDateTime));
IFD expectedSub = new IFD(subDirectoryEntries);
IFD expected = new IFD(entries);
try (ByteArrayOutputStream bytes = new ByteArrayOutputStream()) {
// Write the TIFF w/Exif sub IFD
try (ImageOutputStream stream = new MemoryCacheImageOutputStream(bytes)) {
new TIFFWriter().write(expected, stream);
}
try (ImageInputStream stream = new ByteArrayImageInputStream(bytes.toByteArray())) {
// Read the TIFF back, and compare content
Directory directory = new TIFFReader().read(stream);
Entry dateTimeEntry = directory.getEntryById(EXIF.TAG_DATE_TIME_ORIGINAL);
assertNotNull(dateTimeEntry);
assertEquals(expectedDateTime, dateTimeEntry.getValue());
Entry exifEntry = directory.getEntryById(TIFF.TAG_EXIF_IFD);
IFD exifIFD = (IFD) exifEntry.getValue();
Entry userCommentEntry = exifIFD.getEntryById(EXIF.TAG_USER_COMMENT);
assertNotNull(userCommentEntry);
assertEquals(expectedUserComment, userCommentEntry.getValue());
assertEquals(expectedSub, exifIFD);
assertEquals(expected, ((CompoundDirectory) directory).getDirectory(0));
}
}
}
private static final class NullImageOutputStream extends ImageOutputStreamImpl {
@Override @Override
public void write(int b) { public void write(int b) throws IOException {
streamPos++; streamPos++;
} }
@Override @Override
public void write(byte[] b, int off, int len) { public void write(byte[] b, int off, int len) throws IOException {
streamPos += len; streamPos += len;
} }
@Override @Override
public int read() { public int read() throws IOException {
throw new UnsupportedOperationException("Method read not implemented"); throw new UnsupportedOperationException("Method read not implemented");
} }
@Override @Override
public int read(byte[] b, int off, int len) { public int read(byte[] b, int off, int len) throws IOException {
throw new UnsupportedOperationException("Method read not implemented"); throw new UnsupportedOperationException("Method read not implemented");
} }
} }
+1 -1
View File
@@ -4,7 +4,7 @@
<parent> <parent>
<groupId>com.twelvemonkeys.imageio</groupId> <groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio</artifactId> <artifactId>imageio</artifactId>
<version>3.13.2-SNAPSHOT</version> <version>3.12.1-SNAPSHOT</version>
</parent> </parent>
<artifactId>imageio-pcx</artifactId> <artifactId>imageio-pcx</artifactId>
<name>TwelveMonkeys :: ImageIO :: PCX plugin</name> <name>TwelveMonkeys :: ImageIO :: PCX plugin</name>
+1 -1
View File
@@ -4,7 +4,7 @@
<parent> <parent>
<groupId>com.twelvemonkeys.imageio</groupId> <groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio</artifactId> <artifactId>imageio</artifactId>
<version>3.13.2-SNAPSHOT</version> <version>3.12.1-SNAPSHOT</version>
</parent> </parent>
<artifactId>imageio-pdf</artifactId> <artifactId>imageio-pdf</artifactId>
<name>TwelveMonkeys :: ImageIO :: PDF plugin</name> <name>TwelveMonkeys :: ImageIO :: PDF plugin</name>
+1 -1
View File
@@ -4,7 +4,7 @@
<parent> <parent>
<groupId>com.twelvemonkeys.imageio</groupId> <groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio</artifactId> <artifactId>imageio</artifactId>
<version>3.13.2-SNAPSHOT</version> <version>3.12.1-SNAPSHOT</version>
</parent> </parent>
<artifactId>imageio-pict</artifactId> <artifactId>imageio-pict</artifactId>
<name>TwelveMonkeys :: ImageIO :: PICT plugin</name> <name>TwelveMonkeys :: ImageIO :: PICT plugin</name>
+1 -1
View File
@@ -4,7 +4,7 @@
<parent> <parent>
<groupId>com.twelvemonkeys.imageio</groupId> <groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio</artifactId> <artifactId>imageio</artifactId>
<version>3.13.2-SNAPSHOT</version> <version>3.12.1-SNAPSHOT</version>
</parent> </parent>
<artifactId>imageio-pnm</artifactId> <artifactId>imageio-pnm</artifactId>
<name>TwelveMonkeys :: ImageIO :: PNM plugin</name> <name>TwelveMonkeys :: ImageIO :: PNM plugin</name>
+1 -1
View File
@@ -4,7 +4,7 @@
<parent> <parent>
<groupId>com.twelvemonkeys.imageio</groupId> <groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio</artifactId> <artifactId>imageio</artifactId>
<version>3.13.2-SNAPSHOT</version> <version>3.12.1-SNAPSHOT</version>
</parent> </parent>
<artifactId>imageio-psd</artifactId> <artifactId>imageio-psd</artifactId>
<name>TwelveMonkeys :: ImageIO :: PSD plugin</name> <name>TwelveMonkeys :: ImageIO :: PSD plugin</name>
@@ -410,9 +410,9 @@ public final class PSDMetadata extends AbstractMetadata {
if ((psdLayerInfo.blendMode.flags & 0x01) != 0) { if ((psdLayerInfo.blendMode.flags & 0x01) != 0) {
node.setAttribute("transparencyProtected", "true"); node.setAttribute("transparencyProtected", "true");
} }
// Include always, to avoid ambiguity, as the flag is really "hidden", not "visible"... if ((psdLayerInfo.blendMode.flags & 0x02) != 0) {
boolean hidden = (psdLayerInfo.blendMode.flags & 0x02) != 0; node.setAttribute("visible", "true");
node.setAttribute("visible", hidden ? "false" : "true"); }
if ((psdLayerInfo.blendMode.flags & 0x04) != 0) { if ((psdLayerInfo.blendMode.flags & 0x04) != 0) {
node.setAttribute("obsolete", "true"); node.setAttribute("obsolete", "true");
} }
@@ -1,119 +0,0 @@
package com.twelvemonkeys.imageio.plugins.psd;
import static org.junit.jupiter.api.Assertions.*;
import java.io.IOException;
import java.net.URL;
import javax.imageio.ImageIO;
import javax.imageio.metadata.IIOMetadata;
import javax.imageio.metadata.IIOMetadataNode;
import javax.imageio.spi.IIORegistry;
import javax.imageio.spi.ImageReaderSpi;
import javax.imageio.stream.ImageInputStream;
import org.junit.jupiter.api.Test;
import org.w3c.dom.NodeList;
import com.twelvemonkeys.imageio.stream.URLImageInputStreamSpi;
class PSDMetadataTest {
static {
IIORegistry.getDefaultInstance().registerServiceProvider(new URLImageInputStreamSpi());
ImageIO.setUseCache(false);
}
protected final PSDImageReaderSpi provider = createProvider();
private PSDImageReaderSpi createProvider() {
return new PSDImageReaderSpi();
}
private PSDImageReader createReader() throws IOException {
return (PSDImageReader) provider.createReaderInstance(null);
}
protected URL getClassLoaderResource(final String resource) {
return getClass().getResource(resource);
}
@Test
void testLayerInfo() throws IOException {
PSDImageReader imageReader = createReader();
try (ImageInputStream stream = ImageIO.createImageInputStream(getClassLoaderResource("/psd/photoshopping.psd"))) {
imageReader.setInput(stream);
IIOMetadata metadata = imageReader.getImageMetadata(0);
IIOMetadataNode root = (IIOMetadataNode) metadata.getAsTree(PSDMetadata.NATIVE_METADATA_FORMAT_NAME);
NodeList layerInfos = root.getElementsByTagName("LayerInfo");
assertEquals(5, layerInfos.getLength()); // Sanity
IIOMetadataNode layer1Info = (IIOMetadataNode) layerInfos.item(0);
assertEquals("Layer 1", layer1Info.getAttribute("name"));
assertEquals("2", layer1Info.getAttribute("layerId"));
assertEquals("0", layer1Info.getAttribute("top"));
assertEquals("0", layer1Info.getAttribute("left"));
assertEquals("225", layer1Info.getAttribute("bottom"));
assertEquals("300", layer1Info.getAttribute("right"));
assertEquals("norm", layer1Info.getAttribute("blendMode"));
assertEquals("255", layer1Info.getAttribute("opacity"));
assertEquals("base", layer1Info.getAttribute("clipping"));
assertEquals("true", layer1Info.getAttribute("visible"));
assertEquals("8", layer1Info.getAttribute("flags"));
IIOMetadataNode layer2Info = (IIOMetadataNode) layerInfos.item(1);
assertEquals("Layer 0 copy", layer2Info.getAttribute("name"));
assertEquals("11", layer2Info.getAttribute("layerId"));
assertEquals("0", layer2Info.getAttribute("top"));
assertEquals("0", layer2Info.getAttribute("left"));
assertEquals("225", layer2Info.getAttribute("bottom"));
assertEquals("300", layer2Info.getAttribute("right"));
assertEquals("norm", layer2Info.getAttribute("blendMode"));
assertEquals("255", layer2Info.getAttribute("opacity"));
assertEquals("base", layer2Info.getAttribute("clipping"));
assertEquals("true", layer2Info.getAttribute("visible"));
assertEquals("8", layer2Info.getAttribute("flags"));
IIOMetadataNode layer3Info = (IIOMetadataNode) layerInfos.item(2);
assertEquals("Layer 0 copy 2", layer3Info.getAttribute("name"));
assertEquals("12", layer3Info.getAttribute("layerId"));
assertEquals("0", layer3Info.getAttribute("top"));
assertEquals("0", layer3Info.getAttribute("left"));
assertEquals("225", layer3Info.getAttribute("bottom"));
assertEquals("159", layer3Info.getAttribute("right"));
assertEquals("norm", layer3Info.getAttribute("blendMode"));
assertEquals("255", layer3Info.getAttribute("opacity"));
assertEquals("base", layer3Info.getAttribute("clipping"));
assertEquals("true", layer3Info.getAttribute("visible"));
assertEquals("8", layer3Info.getAttribute("flags"));
IIOMetadataNode layer4Info = (IIOMetadataNode) layerInfos.item(3);
assertEquals("Layer 0 copy 3", layer4Info.getAttribute("name"));
assertEquals("13", layer4Info.getAttribute("layerId"));
assertEquals("0", layer4Info.getAttribute("top"));
assertEquals("0", layer4Info.getAttribute("left"));
assertEquals("225", layer4Info.getAttribute("bottom"));
assertEquals("300", layer4Info.getAttribute("right"));
assertEquals("norm", layer4Info.getAttribute("blendMode"));
assertEquals("255", layer4Info.getAttribute("opacity"));
assertEquals("base", layer4Info.getAttribute("clipping"));
assertEquals("false", layer4Info.getAttribute("visible"));
assertEquals("10", layer4Info.getAttribute("flags"));
IIOMetadataNode layer5Info = (IIOMetadataNode) layerInfos.item(4);
assertEquals("Layer 0", layer5Info.getAttribute("name"));
assertEquals("3", layer5Info.getAttribute("layerId"));
assertEquals("0", layer5Info.getAttribute("top"));
assertEquals("0", layer5Info.getAttribute("left"));
assertEquals("225", layer5Info.getAttribute("bottom"));
assertEquals("300", layer5Info.getAttribute("right"));
assertEquals("norm", layer5Info.getAttribute("blendMode"));
assertEquals("255", layer5Info.getAttribute("opacity"));
assertEquals("base", layer5Info.getAttribute("clipping"));
assertEquals("false", layer5Info.getAttribute("visible"));
assertEquals("10", layer5Info.getAttribute("flags"));
}
}
}
+1 -1
View File
@@ -4,7 +4,7 @@
<parent> <parent>
<groupId>com.twelvemonkeys.imageio</groupId> <groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio</artifactId> <artifactId>imageio</artifactId>
<version>3.13.2-SNAPSHOT</version> <version>3.12.1-SNAPSHOT</version>
</parent> </parent>
<artifactId>imageio-reference</artifactId> <artifactId>imageio-reference</artifactId>
<name>TwelveMonkeys :: ImageIO :: JDK Reference Tests</name> <name>TwelveMonkeys :: ImageIO :: JDK Reference Tests</name>
@@ -111,12 +111,6 @@ public class JPEGImageReaderTest extends ImageReaderAbstractTest<JPEGImageReader
super.testReadAsRenderedImageIndexOutOfBounds(); super.testReadAsRenderedImageIndexOutOfBounds();
} }
@Test
@Disabled("JDK 25 now supports reading Exif thumbnails, but does not report thumbnail progress")
public void testThumbnailProgress() throws IOException {
super.testThumbnailProgress();
}
@Test @Test
@Disabled("No test data with JFIF thumbnail") @Disabled("No test data with JFIF thumbnail")
@Override @Override
+1 -1
View File
@@ -4,7 +4,7 @@
<parent> <parent>
<groupId>com.twelvemonkeys.imageio</groupId> <groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio</artifactId> <artifactId>imageio</artifactId>
<version>3.13.2-SNAPSHOT</version> <version>3.12.1-SNAPSHOT</version>
</parent> </parent>
<artifactId>imageio-sgi</artifactId> <artifactId>imageio-sgi</artifactId>
<name>TwelveMonkeys :: ImageIO :: SGI plugin</name> <name>TwelveMonkeys :: ImageIO :: SGI plugin</name>
+1 -1
View File
@@ -4,7 +4,7 @@
<parent> <parent>
<groupId>com.twelvemonkeys.imageio</groupId> <groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio</artifactId> <artifactId>imageio</artifactId>
<version>3.13.2-SNAPSHOT</version> <version>3.12.1-SNAPSHOT</version>
</parent> </parent>
<artifactId>imageio-tga</artifactId> <artifactId>imageio-tga</artifactId>
<name>TwelveMonkeys :: ImageIO :: TGA plugin</name> <name>TwelveMonkeys :: ImageIO :: TGA plugin</name>
+1 -1
View File
@@ -4,7 +4,7 @@
<parent> <parent>
<groupId>com.twelvemonkeys.imageio</groupId> <groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio</artifactId> <artifactId>imageio</artifactId>
<version>3.13.2-SNAPSHOT</version> <version>3.12.1-SNAPSHOT</version>
</parent> </parent>
<artifactId>imageio-thumbsdb</artifactId> <artifactId>imageio-thumbsdb</artifactId>
<name>TwelveMonkeys :: ImageIO :: Thumbs.db plugin</name> <name>TwelveMonkeys :: ImageIO :: Thumbs.db plugin</name>
+1 -1
View File
@@ -4,7 +4,7 @@
<parent> <parent>
<groupId>com.twelvemonkeys.imageio</groupId> <groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio</artifactId> <artifactId>imageio</artifactId>
<version>3.13.2-SNAPSHOT</version> <version>3.12.1-SNAPSHOT</version>
</parent> </parent>
<artifactId>imageio-tiff-jai-interop</artifactId> <artifactId>imageio-tiff-jai-interop</artifactId>
<name>TwelveMonkeys :: ImageIO :: TIFF/JAI Metadata Interop</name> <name>TwelveMonkeys :: ImageIO :: TIFF/JAI Metadata Interop</name>
+1 -1
View File
@@ -4,7 +4,7 @@
<parent> <parent>
<groupId>com.twelvemonkeys.imageio</groupId> <groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio</artifactId> <artifactId>imageio</artifactId>
<version>3.13.2-SNAPSHOT</version> <version>3.12.1-SNAPSHOT</version>
</parent> </parent>
<artifactId>imageio-tiff-jdk-interop</artifactId> <artifactId>imageio-tiff-jdk-interop</artifactId>
<name>TwelveMonkeys :: ImageIO :: TIFF/JDK JPEG Interop</name> <name>TwelveMonkeys :: ImageIO :: TIFF/JDK JPEG Interop</name>
+1 -1
View File
@@ -4,7 +4,7 @@
<parent> <parent>
<groupId>com.twelvemonkeys.imageio</groupId> <groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio</artifactId> <artifactId>imageio</artifactId>
<version>3.13.2-SNAPSHOT</version> <version>3.12.1-SNAPSHOT</version>
</parent> </parent>
<artifactId>imageio-tiff</artifactId> <artifactId>imageio-tiff</artifactId>
<name>TwelveMonkeys :: ImageIO :: TIFF plugin</name> <name>TwelveMonkeys :: ImageIO :: TIFF plugin</name>
@@ -71,16 +71,18 @@ public final class TIFFImageMetadata extends AbstractMetadata {
/** /**
* Creates an empty TIFF metadata object. * Creates an empty TIFF metadata object.
*
* Client code can update or change the metadata using the * Client code can update or change the metadata using the
* {@link #setFromTree(String, Node)} * {@link #setFromTree(String, Node)}
* or {@link #mergeTree(String, Node)} methods. * or {@link #mergeTree(String, Node)} methods.
*/ */
public TIFFImageMetadata() { public TIFFImageMetadata() {
this(new IFD(Collections.emptyList())); this(new IFD(Collections.<Entry>emptyList()));
} }
/** /**
* Creates a TIFF metadata object, using the values from the given IFD. * Creates a TIFF metadata object, using the values from the given IFD.
*
* Client code can update or change the metadata using the * Client code can update or change the metadata using the
* {@link #setFromTree(String, Node)} * {@link #setFromTree(String, Node)}
* or {@link #mergeTree(String, Node)} methods. * or {@link #mergeTree(String, Node)} methods.
@@ -93,6 +95,7 @@ public final class TIFFImageMetadata extends AbstractMetadata {
/** /**
* Creates a TIFF metadata object, using the values from the given entries. * Creates a TIFF metadata object, using the values from the given entries.
*
* Client code can update or change the metadata using the * Client code can update or change the metadata using the
* {@link #setFromTree(String, Node)} * {@link #setFromTree(String, Node)}
* or {@link #mergeTree(String, Node)} methods. * or {@link #mergeTree(String, Node)} methods.
@@ -490,10 +493,10 @@ public final class TIFFImageMetadata extends AbstractMetadata {
compressionTypeName.setAttribute("value", "CCITT RLE"); compressionTypeName.setAttribute("value", "CCITT RLE");
break; break;
case TIFFExtension.COMPRESSION_CCITT_T4: case TIFFExtension.COMPRESSION_CCITT_T4:
compressionTypeName.setAttribute("value", "CCITT T.4"); compressionTypeName.setAttribute("value", "CCITT T4");
break; break;
case TIFFExtension.COMPRESSION_CCITT_T6: case TIFFExtension.COMPRESSION_CCITT_T6:
compressionTypeName.setAttribute("value", "CCITT T.6"); compressionTypeName.setAttribute("value", "CCITT T6");
break; break;
case TIFFExtension.COMPRESSION_LZW: case TIFFExtension.COMPRESSION_LZW:
compressionTypeName.setAttribute("value", "LZW"); compressionTypeName.setAttribute("value", "LZW");
@@ -1035,7 +1038,7 @@ public final class TIFFImageMetadata extends AbstractMetadata {
} }
// If we have resolution // If we have resolution
if (xRes != null) { // yRes != null too if (xRes != null && yRes != null) {
// If old unit was DPI, convert values and keep DPI, otherwise use PPCM // If old unit was DPI, convert values and keep DPI, otherwise use PPCM
Entry resUnitEntry = entries.get(TIFF.TAG_RESOLUTION_UNIT); Entry resUnitEntry = entries.get(TIFF.TAG_RESOLUTION_UNIT);
int resUnitValue = resUnitEntry != null && resUnitEntry.getValue() != null int resUnitValue = resUnitEntry != null && resUnitEntry.getValue() != null
@@ -188,102 +188,6 @@ public class TIFFImageMetadataTest {
assertEquals("HP IL v1.1", ((Element) textEntry).getAttribute("value")); assertEquals("HP IL v1.1", ((Element) textEntry).getAttribute("value"));
} }
@Test
public void testMetadataStandardFormat_CCITT300dpi() throws IOException {
IIOMetadata metadata = createMetadata("/tiff/CCITT-G4-300dpi-StripByteCounts0.tif");
Node root = metadata.getAsTree(IIOMetadataFormatImpl.standardMetadataFormatName);
// Root: "javax_imageio_1.0"
assertNotNull(root);
assertEquals(IIOMetadataFormatImpl.standardMetadataFormatName, root.getNodeName());
assertEquals(5, root.getChildNodes().getLength());
// "Chroma"
Node chroma = root.getFirstChild();
assertEquals("Chroma", chroma.getNodeName());
assertEquals(3, chroma.getChildNodes().getLength());
Node colorSpaceType = chroma.getFirstChild();
assertEquals("ColorSpaceType", colorSpaceType.getNodeName());
assertEquals("GRAY", ((Element) colorSpaceType).getAttribute("name"));
Node numChannels = colorSpaceType.getNextSibling();
assertEquals("NumChannels", numChannels.getNodeName());
assertEquals("1", ((Element) numChannels).getAttribute("value"));
Node blackIsZero = numChannels.getNextSibling();
assertEquals("BlackIsZero", blackIsZero.getNodeName());
assertEquals("FALSE", ((Element) blackIsZero).getAttribute("value"));
// "Compression"
Node compression = chroma.getNextSibling();
assertEquals("Compression", compression.getNodeName());
assertEquals(2, compression.getChildNodes().getLength());
Node compressionTypeName = compression.getFirstChild();
assertEquals("CompressionTypeName", compressionTypeName.getNodeName());
assertEquals("CCITT T.6", ((Element) compressionTypeName).getAttribute("value"));
Node lossless = compressionTypeName.getNextSibling();
assertEquals("Lossless", lossless.getNodeName());
assertEquals(0, lossless.getAttributes().getLength());
// "Data"
Node data = compression.getNextSibling();
assertEquals("Data", data.getNodeName());
assertEquals(4, data.getChildNodes().getLength());
Node planarConfiguration = data.getFirstChild();
assertEquals("PlanarConfiguration", planarConfiguration.getNodeName());
assertEquals("PixelInterleaved", ((Element) planarConfiguration).getAttribute("value"));
Node sampleFormat = planarConfiguration.getNextSibling();
assertEquals("SampleFormat", sampleFormat.getNodeName());
assertEquals("UnsignedIntegral", ((Element) sampleFormat).getAttribute("value"));
Node bitsPerSample = sampleFormat.getNextSibling();
assertEquals("BitsPerSample", bitsPerSample.getNodeName());
assertEquals("1", ((Element) bitsPerSample).getAttribute("value"));
Node sampleMSB = bitsPerSample.getNextSibling();
assertEquals("SampleMSB", sampleMSB.getNodeName());
assertEquals("0", ((Element) sampleMSB).getAttribute("value"));
// "Dimension"
Node dimension = data.getNextSibling();
assertEquals("Dimension", dimension.getNodeName());
assertEquals(4, dimension.getChildNodes().getLength());
Node pixelAspectRatio = dimension.getFirstChild();
assertEquals("PixelAspectRatio", pixelAspectRatio.getNodeName());
assertEquals("1.0", ((Element) pixelAspectRatio).getAttribute("value"));
Node imageOrientation = pixelAspectRatio.getNextSibling();
assertEquals("ImageOrientation", imageOrientation.getNodeName());
assertEquals("Normal", ((Element) imageOrientation).getAttribute("value"));
Node horizontalPixelSize = imageOrientation.getNextSibling();
assertEquals("HorizontalPixelSize", horizontalPixelSize.getNodeName());
assertEquals("0.08466666666666667", ((Element) horizontalPixelSize).getAttribute("value"));
Node verticalPixelSize = horizontalPixelSize.getNextSibling();
assertEquals("VerticalPixelSize", verticalPixelSize.getNodeName());
assertEquals("0.08466666666666667", ((Element) verticalPixelSize).getAttribute("value"));
// "Document"
Node document = dimension.getNextSibling();
assertEquals("Document", document.getNodeName());
assertEquals(1, document.getChildNodes().getLength());
Node formatVersion = document.getFirstChild();
assertEquals("FormatVersion", formatVersion.getNodeName());
assertEquals("6.0", ((Element) formatVersion).getAttribute("value"));
// No more elements
assertNull(document.getNextSibling());
}
@Test @Test
public void testMetadataNativeFormat() throws IOException { public void testMetadataNativeFormat() throws IOException {
IIOMetadata metadata = createMetadata("/tiff/quad-lzw.tif"); IIOMetadata metadata = createMetadata("/tiff/quad-lzw.tif");
+1 -1
View File
@@ -4,7 +4,7 @@
<parent> <parent>
<groupId>com.twelvemonkeys.imageio</groupId> <groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio</artifactId> <artifactId>imageio</artifactId>
<version>3.13.2-SNAPSHOT</version> <version>3.12.1-SNAPSHOT</version>
</parent> </parent>
<artifactId>imageio-webp</artifactId> <artifactId>imageio-webp</artifactId>
<name>TwelveMonkeys :: ImageIO :: WebP plugin</name> <name>TwelveMonkeys :: ImageIO :: WebP plugin</name>
@@ -565,7 +565,7 @@ final class WebPImageReader extends ImageReaderBase {
readVP8Lossless(tempRaster, null, width, height); readVP8Lossless(tempRaster, null, width, height);
// Copy from green (band 1) in temp to alpha in destination // Copy from green (band 1) in temp to alpha in destination
WritableRaster alphaChannel = tempRaster.createWritableChild(0, 0, width, height, 0, 0, new int[]{1}); WritableRaster alphaChannel = tempRaster.createWritableChild(0, 0, tempRaster.getWidth(), tempRaster.getHeight(), 0, 0, new int[]{1});
alphaFilter(alphaChannel, filtering); alphaFilter(alphaChannel, filtering);
copyIntoRasterWithParams(alphaChannel, alphaRaster, param); copyIntoRasterWithParams(alphaChannel, alphaRaster, param);
break; break;
@@ -166,79 +166,71 @@ final class HuffmanTable {
if (numPosCodeLens == 1) { if (numPosCodeLens == 1) {
// Length is 0 so mask to clear length bits // Length is 0 so mask to clear length bits
Arrays.fill(level1, lengthsAndSymbols[0] & 0xffff); Arrays.fill(level1, lengthsAndSymbols[0] & 0xffff);
return;
} }
// Due to the layout of the elements this effectively first sorts by length and then symbol. // Due to the layout of the elements this effectively first sorts by length and then symbol.
Arrays.sort(lengthsAndSymbols); Arrays.sort(lengthsAndSymbols);
int[] count = new int[16];
for (int lengthAndSymbol : lengthsAndSymbols) {
count[lengthAndSymbol >>> 16]++;
}
// The next code, in the bit order it would appear on the input stream, i.e. it is reversed. // The next code, in the bit order it would appear on the input stream, i.e. it is reversed.
// Only the lowest bits (corresponding to the bit length of the code) are considered. // Only the lowest bits (corresponding to the bit length of the code) are considered.
// Example: code 0..010 (length 2) would appear as 0..001. // Example: code 0..010 (length 2) would appear as 0..001.
int code = 0; int code = 0;
int step = 2;
index = 0;
for (int length = 1; length <= LEVEL1_BITS; length++, step <<= 1) { // Used for level2 lookup
for (; count[length] > 0; count[length]--) {
int lengthAndSymbol = lengthsAndSymbols[index++];
for (int j = code; j < level1.length; j += step) {
level1[j] = lengthAndSymbol;
}
code = nextCode(code, length);
}
}
int rootMask = (1 << LEVEL1_BITS) - 1;
int rootEntry = -1; int rootEntry = -1;
int[] currentTable = null; int[] currentTable = null;
step = 2; for (int i = 0; i < lengthsAndSymbols.length; i++) {
for (int length = LEVEL1_BITS + 1; length <= 15; length++, step <<= 1) { int lengthAndSymbol = lengthsAndSymbols[i];
for (; count[length] > 0; count[length]--) {
int lengthAndSymbol = lengthsAndSymbols[index++];
if ((code & rootMask) != rootEntry) { int length = lengthAndSymbol >>> 16;
int level2Bits = nextTableBitSize(count, length, LEVEL1_BITS);
int level2Size = 1 << level2Bits;
currentTable = new int[level2Size]; if (length <= LEVEL1_BITS) {
rootEntry = code & rootMask; for (int j = code; j < level1.length; j += 1 << length) {
level1[j] = lengthAndSymbol;
}
}
else {
// Existing level2 table not fitting
if ((code & ((1 << LEVEL1_BITS) - 1)) != rootEntry) {
// Figure out needed table size.
// Start at current symbol and length.
// Every symbol uses 1 slot at the current bit length.
// Going up 1 bit in length multiplies the slots by 2.
// No more open slots indicate the table size to be big enough.
int maxLength = length;
for (int j = i, openSlots = 1 << (length - LEVEL1_BITS);
j < lengthsAndSymbols.length && openSlots > 0;
j++, openSlots--) {
int innerLength = lengthsAndSymbols[j] >>> 16;
while (innerLength != maxLength) {
maxLength++;
openSlots <<= 1;
}
}
int level2Size = maxLength - LEVEL1_BITS;
currentTable = new int[1 << level2Size];
rootEntry = code & ((1 << LEVEL1_BITS) - 1);
level2.add(currentTable); level2.add(currentTable);
// Set root table indirection // Set root table indirection
level1[rootEntry] = (LEVEL1_BITS + level2Bits) << 16 | (level2.size() - 1); level1[rootEntry] = (LEVEL1_BITS + level2Size) << 16 | (level2.size() - 1);
} }
int value = (length - LEVEL1_BITS) << 16 | (lengthAndSymbol & 0xffff); // Add to existing (or newly generated) 2nd level table
for (int j = (code >>> LEVEL1_BITS); j < currentTable.length; j += step) { for (int j = (code >>> LEVEL1_BITS); j < currentTable.length; j += 1 << (length - LEVEL1_BITS)) {
currentTable[j] = value; currentTable[j] = (length - LEVEL1_BITS) << 16 | (lengthAndSymbol & 0xffff);
} }
code = nextCode(code, length);
} }
}
}
private static int nextTableBitSize(int[] count, int length, int rootBits) { code = nextCode(code, length);
int left = 1 << (length - rootBits);
while (length < 15) {
left -= count[length];
if (left <= 0) {
break;
}
length++;
left <<= 1;
}
return length - rootBits; }
} }
/** /**
@@ -148,7 +148,8 @@ public final class VP8LDecoder {
if (param.getSourceRegion() != null && !param.getSourceRegion().contains(bounds) || if (param.getSourceRegion() != null && !param.getSourceRegion().contains(bounds) ||
param.getSourceXSubsampling() != 1 || param.getSourceYSubsampling() != 1) { param.getSourceXSubsampling() != 1 || param.getSourceYSubsampling() != 1) {
// Can't reuse existing // Can't reuse existing
return createCompatibleRaster(raster, bounds.width, bounds.height); return Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE, bounds.width, bounds.height,
4 * bounds.width, 4, new int[] {0, 1, 2, 3}, null);
} }
else { else {
bounds.setLocation(param.getDestinationOffset()); bounds.setLocation(param.getDestinationOffset());
@@ -158,7 +159,8 @@ public final class VP8LDecoder {
if (!raster.getBounds().contains(bounds)) { if (!raster.getBounds().contains(bounds)) {
// Can't reuse existing // Can't reuse existing
return createCompatibleRaster(raster, bounds.width, bounds.height); return Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE, bounds.width, bounds.height, 4 * bounds.width,
4, new int[] {0, 1, 2, 3}, null);
} }
return originSet ? return originSet ?
@@ -167,11 +169,6 @@ public final class VP8LDecoder {
raster; raster;
} }
private static WritableRaster createCompatibleRaster(WritableRaster src, int width, int height) {
SampleModel sampleModel = src.getSampleModel().createCompatibleSampleModel(width, height);
return Raster.createWritableRaster(sampleModel, sampleModel.createDataBuffer(), null);
}
/** /**
* Copy a source raster into a destination raster with optional settings applied. * Copy a source raster into a destination raster with optional settings applied.
*/ */
@@ -185,8 +182,7 @@ public final class VP8LDecoder {
if (sourceXSubsampling == 1 && sourceYSubsampling == 1) { if (sourceXSubsampling == 1 && sourceYSubsampling == 1) {
// Only apply offset (and limit to requested region) // Only apply offset (and limit to requested region)
dstRaster.setRect(destinationOffset.x, destinationOffset.y, srcRaster.createChild( dstRaster.setRect(destinationOffset.x, destinationOffset.y, srcRaster);
sourceRegion.x, sourceRegion.y, sourceRegion.width, sourceRegion.height, 0, 0, null));
} }
else { else {
// Subsampled case // Subsampled case
@@ -276,12 +272,6 @@ public final class VP8LDecoder {
private int decodeBwRef(WritableRaster raster, ColorCache colorCache, int width, HuffmanCodeGroup curCodeGroup, byte[] rgba, short code, int x, int y) throws IOException { private int decodeBwRef(WritableRaster raster, ColorCache colorCache, int width, HuffmanCodeGroup curCodeGroup, byte[] rgba, short code, int x, int y) throws IOException {
int length = lz77decode(code - 256); int length = lz77decode(code - 256);
int remaining = width * raster.getHeight() - (y * width + x);
if (length > remaining) {
throw new IIOException("Corrupt WebP stream, backward reference exceeds image bounds: length=" + length +
", remaining=" + remaining + ", x=" + x + ", y=" + y);
}
short distancePrefix = curCodeGroup.distanceCode.readSymbol(lsbBitReader); short distancePrefix = curCodeGroup.distanceCode.readSymbol(lsbBitReader);
int distanceCode = lz77decode(distancePrefix); int distanceCode = lz77decode(distancePrefix);
@@ -308,11 +298,6 @@ public final class VP8LDecoder {
ySrc++; ySrc++;
} }
if (ySrc < 0 || ySrc >= raster.getHeight()) {
throw new IIOException("Corrupt WebP stream, backward reference outside image: distance=" + distanceCode +
", x=" + x + ", y=" + y + ", xSrc=" + xSrc + ", ySrc=" + ySrc);
}
for (int l = length; l > 0; x++, l--) { for (int l = length; l > 0; x++, l--) {
// Check length and xSrc, ySrc not falling outside raster? (Should not occur if image is correct) // Check length and xSrc, ySrc not falling outside raster? (Should not occur if image is correct)
if (x == width) { if (x == width) {
@@ -1,4 +1,3 @@
package com.twelvemonkeys.imageio.plugins.webp; package com.twelvemonkeys.imageio.plugins.webp;
import com.twelvemonkeys.imageio.util.ImageReaderAbstractTest; import com.twelvemonkeys.imageio.util.ImageReaderAbstractTest;
@@ -12,8 +11,6 @@ import javax.imageio.stream.MemoryCacheImageInputStream;
import java.awt.*; import java.awt.*;
import java.awt.image.*; import java.awt.image.*;
import java.io.IOException; import java.io.IOException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.List; import java.util.List;
import static java.util.Arrays.asList; import static java.util.Arrays.asList;
@@ -46,7 +43,6 @@ public class WebPImageReaderTest extends ImageReaderAbstractTest<WebPImageReader
new TestData(getClassLoaderResource("/webp/1_webp_ll.webp"), new Dimension(400, 301)), new TestData(getClassLoaderResource("/webp/1_webp_ll.webp"), new Dimension(400, 301)),
new TestData(getClassLoaderResource("/webp/2_webp_ll.webp"), new Dimension(386, 395)), new TestData(getClassLoaderResource("/webp/2_webp_ll.webp"), new Dimension(386, 395)),
new TestData(getClassLoaderResource("/webp/2_webp_ll_alt.webp"), new Dimension(386, 395)), new TestData(getClassLoaderResource("/webp/2_webp_ll_alt.webp"), new Dimension(386, 395)),
new TestData(getClassLoaderResource("/webp/2_webp_ll_noalpha.webp"), new Dimension(386, 395)),
new TestData(getClassLoaderResource("/webp/3_webp_ll.webp"), new Dimension(800, 600)), new TestData(getClassLoaderResource("/webp/3_webp_ll.webp"), new Dimension(800, 600)),
new TestData(getClassLoaderResource("/webp/4_webp_ll.webp"), new Dimension(421, 163)), new TestData(getClassLoaderResource("/webp/4_webp_ll.webp"), new Dimension(421, 163)),
new TestData(getClassLoaderResource("/webp/5_webp_ll.webp"), new Dimension(300, 300)), new TestData(getClassLoaderResource("/webp/5_webp_ll.webp"), new Dimension(300, 300)),
@@ -192,153 +188,4 @@ public class WebPImageReaderTest extends ImageReaderAbstractTest<WebPImageReader
reader.dispose(); reader.dispose();
} }
} }
@Test
public void testLosslessSourceRegionSubsampling() throws IOException {
WebPImageReader reader = createReader();
try (ImageInputStream stream = ImageIO.createImageInputStream(getClassLoaderResource("/webp/2_webp_ll_noalpha.webp"))) {
reader.setInput(stream);
// We'll read a small portion of the image using a subsampling factor of 2
ImageReadParam param = reader.getDefaultReadParam();
param.setSourceRegion(new Rectangle(100, 20, 200, 200));
param.setSourceSubsampling(2, 2, 0, 0);
BufferedImage image = reader.read(0, param);
for (int x = 0; x < 23; x++) {
assertRGBEquals("Expected white at (" + x + ", 0)", 0xFFFFFFFF, image.getRGB(x, 0), 0);
}
for (int x = 24; x < 29; x++) {
assertRGBEquals("Expected black at (" + x + ", 0)", 0xFF000000, image.getRGB(x, 0), 0);
}
for (int x = 30; x < 64; x++) {
assertRGBEquals("Expected grey at (" + x + ", 0)", 0xFFF1F1F1, image.getRGB(x, 0), 0);
}
for (int x = 66; x < 69; x++) {
assertRGBEquals("Expected black at (" + x + ", 0)", 0xFF000000, image.getRGB(x, 0), 0);
}
for (int x = 70; x < 100; x++) {
assertRGBEquals("Expected white at (" + x + ", 0)", 0xFFFFFFFF, image.getRGB(x, 0), 0);
}
}
finally {
reader.dispose();
}
}
@Test
public void testLosslessSourceRegionNoSubsampling() throws IOException {
WebPImageReader reader = createReader();
try (ImageInputStream stream = ImageIO.createImageInputStream(getClassLoaderResource("/webp/2_webp_ll_noalpha.webp"))) {
reader.setInput(stream);
// We'll read a small portion of the image without using subsampling
ImageReadParam param = reader.getDefaultReadParam();
param.setSourceRegion(new Rectangle(100, 20, 200, 200));
BufferedImage image = reader.read(0, param);
for (int x = 0; x < 45; x++) {
assertRGBEquals("Expected white at (" + x + ", 0)", 0xFFFFFFFF, image.getRGB(x, 0), 0);
}
for (int x = 48; x < 58; x++) {
assertRGBEquals("Expected black at (" + x + ", 0)", 0xFF000000, image.getRGB(x, 0), 0);
}
for (int x = 60; x < 128; x++) {
assertRGBEquals("Expected grey at (" + x + ", 0)", 0xFFF1F1F1, image.getRGB(x, 0), 0);
}
for (int x = 131; x < 138; x++) {
assertRGBEquals("Expected black at (" + x + ", 0)", 0xFF000000, image.getRGB(x, 0), 0);
}
for (int x = 140; x < 200; x++) {
assertRGBEquals("Expected white at (" + x + ", 0)", 0xFFFFFFFF, image.getRGB(x, 0), 0);
}
}
finally {
reader.dispose();
}
}
/**
* This test compares alpha channel information that is decoded by the WebPImageReader with the known "good" alpha
* channel information. To generate the known "good" alpha channel information, we use the command line and libwebp,
* e.g.
*
* <pre>{@code
* dwebp imageio/imageio-webp/src/test/resources/webp/lossless.transparent.webp -o /tmp/lossless.transparent.png
* magick /tmp/lossless.transparent.png -alpha extract -depth 8 gray:/tmp/lossless.transparent-alpha.raw
* shasum -a 256 /tmp/lossless.transparent-alpha.raw
* }</pre>
*
* @throws IOException
*/
@Test
public void testReadWriteTransparentWebP() throws IOException {
WebPImageReader reader = createReader();
try (ImageInputStream stream = ImageIO.createImageInputStream(getClassLoaderResource("/webp/lossless.transparent.webp"))) {
reader.setInput(stream);
// Read dimensions
int width = reader.getWidth(0);
int height = reader.getHeight(0);
assertEquals(1920, width, "Expected width of 1920");
assertEquals(1477, height, "Expected height of 1477");
// Read the full image and validate alpha output (exercises long LZ77 back-references).
BufferedImage image = reader.read(0);
assertNotNull(image, "Image should not be null");
assertEquals(width, image.getWidth(), "Image width should match");
assertEquals(height, image.getHeight(), "Image height should match");
assertTrue(image.getColorModel().hasAlpha(), "Image should have alpha channel");
assertEquals("79ffff20392a9cef308b317cbac9d3e57f78e26a4f49fb38b3f3b4dbc4e63c50",
sha256Alpha(image), "Alpha plane hash mismatch");
}
finally {
reader.dispose();
}
}
private static String sha256Alpha(BufferedImage image) {
WritableRaster alphaRaster = image.getAlphaRaster();
assertNotNull(alphaRaster, "Image should have alpha raster");
int width = alphaRaster.getWidth();
int height = alphaRaster.getHeight();
int[] samples = alphaRaster.getSamples(0, 0, width, height, 0, (int[]) null);
MessageDigest digest;
try {
digest = MessageDigest.getInstance("SHA-256");
}
catch (NoSuchAlgorithmException e) {
throw new AssertionError("SHA-256 not available", e);
}
for (int sample : samples) {
digest.update((byte) sample);
}
return toHex(digest.digest());
}
private static String toHex(byte[] bytes) {
StringBuilder builder = new StringBuilder(bytes.length * 2);
for (byte b : bytes) {
builder.append(Character.forDigit((b >>> 4) & 0x0f, 16));
builder.append(Character.forDigit(b & 0x0f, 16));
}
return builder.toString();
}
} }
Binary file not shown.

Before

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 63 KiB

+1 -1
View File
@@ -4,7 +4,7 @@
<parent> <parent>
<groupId>com.twelvemonkeys.imageio</groupId> <groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio</artifactId> <artifactId>imageio</artifactId>
<version>3.13.2-SNAPSHOT</version> <version>3.12.1-SNAPSHOT</version>
</parent> </parent>
<artifactId>imageio-xwd</artifactId> <artifactId>imageio-xwd</artifactId>
<name>TwelveMonkeys :: ImageIO :: XWD plugin</name> <name>TwelveMonkeys :: ImageIO :: XWD plugin</name>
+2 -2
View File
@@ -3,7 +3,7 @@
<parent> <parent>
<groupId>com.twelvemonkeys</groupId> <groupId>com.twelvemonkeys</groupId>
<artifactId>twelvemonkeys</artifactId> <artifactId>twelvemonkeys</artifactId>
<version>3.13.2-SNAPSHOT</version> <version>3.12.1-SNAPSHOT</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<groupId>com.twelvemonkeys.imageio</groupId> <groupId>com.twelvemonkeys.imageio</groupId>
@@ -61,7 +61,7 @@
</modules> </modules>
<properties> <properties>
<junit.jupiter.version>5.14.2</junit.jupiter.version> <junit.jupiter.version>5.13.0</junit.jupiter.version>
</properties> </properties>
<dependencies> <dependencies>
+20 -20
View File
@@ -4,7 +4,7 @@
<groupId>com.twelvemonkeys</groupId> <groupId>com.twelvemonkeys</groupId>
<artifactId>twelvemonkeys</artifactId> <artifactId>twelvemonkeys</artifactId>
<version>3.13.2-SNAPSHOT</version> <version>3.12.1-SNAPSHOT</version>
<packaging>pom</packaging> <packaging>pom</packaging>
<name>TwelveMonkeys</name> <name>TwelveMonkeys</name>
<description>TwelveMonkeys parent POM</description> <description>TwelveMonkeys parent POM</description>
@@ -85,8 +85,8 @@
<distributionManagement> <distributionManagement>
<snapshotRepository> <snapshotRepository>
<id>central</id> <id>ossrh</id>
<url>https://central.sonatype.com/repository/maven-snapshots/</url> <url>https://oss.sonatype.org/content/repositories/snapshots</url>
</snapshotRepository> </snapshotRepository>
</distributionManagement> </distributionManagement>
@@ -98,7 +98,7 @@
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId> <artifactId>maven-gpg-plugin</artifactId>
<version>3.2.8</version> <version>3.2.7</version>
<executions> <executions>
<execution> <execution>
<id>sign-artifacts</id> <id>sign-artifacts</id>
@@ -112,7 +112,7 @@
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId> <artifactId>maven-javadoc-plugin</artifactId>
<version>3.12.0</version> <version>3.11.2</version>
<executions> <executions>
<execution> <execution>
<id>attach-javadocs</id> <id>attach-javadocs</id>
@@ -160,7 +160,7 @@
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId> <artifactId>maven-source-plugin</artifactId>
<version>3.4.0</version> <version>3.3.1</version>
<executions> <executions>
<execution> <execution>
<phase>package</phase> <phase>package</phase>
@@ -174,14 +174,14 @@
</plugin> </plugin>
<plugin> <plugin>
<groupId>org.sonatype.central</groupId> <groupId>org.sonatype.plugins</groupId>
<artifactId>central-publishing-maven-plugin</artifactId> <artifactId>nexus-staging-maven-plugin</artifactId>
<version>0.10.0</version> <version>1.7.0</version>
<extensions>true</extensions> <extensions>true</extensions>
<configuration> <configuration>
<publishingServerId>central</publishingServerId> <serverId>ossrh</serverId>
<autoPublish>true</autoPublish> <nexusUrl>https://oss.sonatype.org/</nexusUrl>
<waitUntil>published</waitUntil> <autoReleaseAfterClose>true</autoReleaseAfterClose>
</configuration> </configuration>
</plugin> </plugin>
</plugins> </plugins>
@@ -191,7 +191,7 @@
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId> <artifactId>maven-resources-plugin</artifactId>
<version>3.4.0</version> <version>3.3.1</version>
<configuration> <configuration>
<encoding>UTF-8</encoding> <encoding>UTF-8</encoding>
</configuration> </configuration>
@@ -199,7 +199,7 @@
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId> <artifactId>maven-jar-plugin</artifactId>
<version>3.5.0</version> <version>3.4.2</version>
<inherited>true</inherited> <inherited>true</inherited>
<executions> <executions>
<execution> <execution>
@@ -250,7 +250,7 @@
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId> <artifactId>maven-compiler-plugin</artifactId>
<version>3.15.0</version> <version>3.14.0</version>
<inherited>true</inherited> <inherited>true</inherited>
<configuration> <configuration>
<source>8</source> <source>8</source>
@@ -265,7 +265,7 @@
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId> <artifactId>maven-surefire-plugin</artifactId>
<version>3.5.4</version> <version>3.5.3</version>
<configuration> <configuration>
<systemProperties> <systemProperties>
<property> <property>
@@ -278,7 +278,7 @@
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-release-plugin</artifactId> <artifactId>maven-release-plugin</artifactId>
<version>3.3.1</version> <version>3.1.1</version>
<configuration> <configuration>
<autoVersionSubmodules>true</autoVersionSubmodules> <autoVersionSubmodules>true</autoVersionSubmodules>
<releaseProfiles>release</releaseProfiles> <releaseProfiles>release</releaseProfiles>
@@ -288,7 +288,7 @@
<dependency> <dependency>
<groupId>org.apache.maven.scm</groupId> <groupId>org.apache.maven.scm</groupId>
<artifactId>maven-scm-provider-gitexe</artifactId> <artifactId>maven-scm-provider-gitexe</artifactId>
<version>2.2.1</version> <version>2.1.0</version>
</dependency> </dependency>
</dependencies> </dependencies>
</plugin> </plugin>
@@ -300,7 +300,7 @@
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-report-plugin</artifactId> <artifactId>maven-surefire-report-plugin</artifactId>
<version>3.5.4</version> <version>3.5.3</version>
</plugin> </plugin>
<plugin> <plugin>
<groupId>org.codehaus.mojo</groupId> <groupId>org.codehaus.mojo</groupId>
@@ -310,7 +310,7 @@
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-pmd-plugin</artifactId> <artifactId>maven-pmd-plugin</artifactId>
<version>3.28.0</version> <version>3.26.0</version>
</plugin> </plugin>
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
+4 -4
View File
@@ -3,7 +3,7 @@
<parent> <parent>
<groupId>com.twelvemonkeys</groupId> <groupId>com.twelvemonkeys</groupId>
<artifactId>twelvemonkeys</artifactId> <artifactId>twelvemonkeys</artifactId>
<version>3.13.2-SNAPSHOT</version> <version>3.12.1-SNAPSHOT</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
@@ -15,7 +15,7 @@
</description> </description>
<properties> <properties>
<junit.jupiter.version>5.14.2</junit.jupiter.version> <junit.jupiter.version>5.13.0</junit.jupiter.version>
</properties> </properties>
<dependencies> <dependencies>
@@ -61,7 +61,7 @@
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId> <artifactId>maven-jar-plugin</artifactId>
<version>3.5.0</version> <version>3.4.2</version>
<configuration> <configuration>
<archive> <archive>
<manifestEntries> <manifestEntries>
@@ -82,7 +82,7 @@
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId> <artifactId>maven-shade-plugin</artifactId>
<version>3.6.1</version> <version>3.6.0</version>
<executions> <executions>
<execution> <execution>
<id>jakarta</id> <id>jakarta</id>