mirror of
https://github.com/haraldk/TwelveMonkeys.git
synced 2026-05-19 00:00:03 -04:00
Compare commits
97 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 7fb443a768 | |||
| b302b4f0d1 | |||
| 29dcf83c47 | |||
| d54d84371d | |||
| 4de2a38dd8 | |||
| 5b4fa64dc0 | |||
| 2ad522a9fa | |||
| 20af575fbd | |||
| 02a6ed1ac1 | |||
| 146d5926bb | |||
| 561b25022c | |||
| 4cd6b893de | |||
| dabff3abce | |||
| 1b889b1b4b | |||
| 29a3bd591d | |||
| cd79ef4409 | |||
| a604cb83fb | |||
| eb1735ab33 | |||
| 357eeb2236 | |||
| d634b9d93f | |||
| 7e3241d64b | |||
| b86d82720d | |||
| 47e90a657a | |||
| bdd8b2f1fb | |||
| 8d08c9565b | |||
| c11f61d132 | |||
| e6b38cb547 | |||
| e11d888809 | |||
| 46a399ff02 | |||
| a09629be32 | |||
| 57fb1ca1bb | |||
| c9063ca02d | |||
| 340e79eb8a | |||
| 355a916225 | |||
| 8da45b5f05 | |||
| 6c8b0cdc2f | |||
| 8af219e669 | |||
| 7e10b9242d | |||
| 36103046a5 | |||
| 95787449ea | |||
| 3223743f2c | |||
| 234c7f59d4 | |||
| 1cb0da2967 | |||
| d1525828fa | |||
| 194fd5a446 | |||
| 21e5a465b9 | |||
| 6309bc5765 | |||
| 5011e98184 | |||
| a9aa5cc66e | |||
| ac107196eb | |||
| 489a419df1 | |||
| 51891b45ea | |||
| 90e60f509d | |||
| 53e5eff0c9 | |||
| 8670e1fd8a | |||
| 6395fd33e9 | |||
| 0834a2b1be | |||
| 6c75661ab4 | |||
| 9c25c962cc | |||
| 1328dbf763 | |||
| 8bccdef371 | |||
| 2d6f7d89fa | |||
| 1afa35ccd6 | |||
| 5b184a2a8a | |||
| 39bd218085 | |||
| 87af2f6212 | |||
| 598ea1e486 | |||
| 93180e7a2d | |||
| 2cc6d1d28e | |||
| 8ea9d6f318 | |||
| 029fa843f6 | |||
| 2cb4c0a661 | |||
| bf40c81123 | |||
| 78a90fab95 | |||
| b03f7a5582 | |||
| 96470c3897 | |||
| 365b19998f | |||
| b1846e1aed | |||
| ec63fbbd85 | |||
| fbea929bc5 | |||
| 18372944f1 | |||
| 488608b312 | |||
| b3ae8a8ba6 | |||
| fc3455d2c6 | |||
| f653279c62 | |||
| 0eff483d72 | |||
| 9c044b132b | |||
| 1ec4088e49 | |||
| 5ac415d019 | |||
| 133eafc8c2 | |||
| 85346a82e1 | |||
| e718e58b65 | |||
| 13a64ed3bb | |||
| 3c6df6ad1b | |||
| 9abe154ed3 | |||
| 0e752a2d2c | |||
| 867a46d281 |
@@ -5,9 +5,13 @@ updates:
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
cooldown:
|
||||
default-days: 7
|
||||
open-pull-requests-limit: 10
|
||||
# GitHub actions updates
|
||||
- package-ecosystem: "github-actions"
|
||||
directory: "/.github/workflows"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
cooldown:
|
||||
default-days: 7
|
||||
|
||||
+40
-24
@@ -17,13 +17,16 @@ jobs:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ ubuntu-latest, windows-latest, macos-latest ]
|
||||
java: [ 11, 17, 21, 23 ]
|
||||
java: [ 8, 11, 17, 21, 25 ]
|
||||
exclude:
|
||||
- os: macos-latest
|
||||
java: 8
|
||||
runs-on: ${{ matrix.os }}
|
||||
permissions:
|
||||
checks: write
|
||||
steps:
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
- uses: actions/setup-java@c5195efecf7bdfc987ee8bae7a71cb8b11521c00 # v4.7.1
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0
|
||||
with:
|
||||
distribution: 'temurin'
|
||||
java-version: ${{ matrix.java }}
|
||||
@@ -32,33 +35,29 @@ jobs:
|
||||
- name: Run Tests
|
||||
run: mvn --batch-mode --no-transfer-progress test
|
||||
- name: Publish Test Report
|
||||
uses: mikepenz/action-junit-report@65fe03598d8d251738592a497a9e8547a5c48eaa # v5
|
||||
uses: mikepenz/action-junit-report@74626db7353a25a20a72816467ebf035f674c5f8 # v5
|
||||
if: ${{ !cancelled() }}
|
||||
with:
|
||||
report_paths: "**/target/surefire-reports/TEST*.xml"
|
||||
check_name: Unit Test Results for OpenJDK ${{ matrix.java }} on ${{ matrix.os }}
|
||||
|
||||
test-jdk8:
|
||||
name: Test OpenJDK ${{ matrix.java }} on ${{ matrix.os }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ ubuntu-latest, windows-latest, macos-13 ]
|
||||
runs-on: ${{ matrix.os }}
|
||||
test-jdk8-macos:
|
||||
name: Test OpenJDK 8 on macos-14
|
||||
runs-on: macos-14
|
||||
permissions:
|
||||
checks: write
|
||||
steps:
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
- uses: actions/setup-java@c5195efecf7bdfc987ee8bae7a71cb8b11521c00 # v4.7.1
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0
|
||||
with:
|
||||
distribution: 'temurin'
|
||||
distribution: 'zulu'
|
||||
java-version: '8'
|
||||
java-package: jdk
|
||||
cache: 'maven'
|
||||
- name: Run Tests
|
||||
run: mvn --batch-mode --no-transfer-progress test
|
||||
- name: Publish Test Report
|
||||
uses: mikepenz/action-junit-report@65fe03598d8d251738592a497a9e8547a5c48eaa # v5
|
||||
uses: mikepenz/action-junit-report@74626db7353a25a20a72816467ebf035f674c5f8 # v5
|
||||
if: ${{ !cancelled() }}
|
||||
with:
|
||||
report_paths: "**/target/surefire-reports/TEST*.xml"
|
||||
@@ -73,11 +72,11 @@ jobs:
|
||||
matrix:
|
||||
kcms: [ true, false ]
|
||||
steps:
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
- run: |
|
||||
download_url="https://javadl.oracle.com/webapps/download/AutoDL?BundleId=245038_d3c52aa6bfa54d3ca74e617f18309292"
|
||||
wget -O $RUNNER_TEMP/java_package.tar.gz $download_url
|
||||
- uses: actions/setup-java@c5195efecf7bdfc987ee8bae7a71cb8b11521c00 # v4.7.1
|
||||
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0
|
||||
with:
|
||||
distribution: 'jdkfile'
|
||||
jdkFile: ${{ runner.temp }}/java_package.tar.gz
|
||||
@@ -92,26 +91,43 @@ jobs:
|
||||
- name: Run Tests
|
||||
run: mvn --batch-mode --no-transfer-progress test
|
||||
- name: Publish Test Report
|
||||
uses: mikepenz/action-junit-report@65fe03598d8d251738592a497a9e8547a5c48eaa # v5
|
||||
uses: mikepenz/action-junit-report@74626db7353a25a20a72816467ebf035f674c5f8 # v5
|
||||
if: ${{ !cancelled() }}
|
||||
with:
|
||||
report_paths: "**/target/surefire-reports/TEST*.xml"
|
||||
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:
|
||||
name: Deploy
|
||||
needs: [ test, test-jdk8, test-oracle ]
|
||||
needs: [ test, test-jdk8-macos, test-oracle, javadoc ]
|
||||
if: github.ref == 'refs/heads/master' # only perform on latest master
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
- name: Set up Maven Central
|
||||
uses: actions/setup-java@c5195efecf7bdfc987ee8bae7a71cb8b11521c00 # v4.7.1
|
||||
uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0
|
||||
with: # running setup-java again overwrites the settings.xml
|
||||
distribution: 'temurin'
|
||||
java-version: '8'
|
||||
java-package: jdk
|
||||
server-id: ossrh # Value of the distributionManagement/repository/id field of the pom.xml
|
||||
server-id: central # Value of the distributionManagement/repository/id field of the pom.xml
|
||||
server-username: MAVEN_CENTRAL_USERNAME # env variable for username in deploy (1)
|
||||
server-password: MAVEN_CENTRAL_PASSWORD # env variable for token in deploy (2)
|
||||
- name: Get Project Version
|
||||
@@ -121,7 +137,7 @@ jobs:
|
||||
if: ${{ endsWith(env.PROJECT_VERSION, '-SNAPSHOT') }}
|
||||
run: mvn --batch-mode --no-transfer-progress deploy -P release -DskipTests -Dgpg.signer=bc
|
||||
env:
|
||||
MAVEN_CENTRAL_USERNAME: ${{ secrets.SONATYPE_USERNAME }} # must be the same env variable name as (1)
|
||||
MAVEN_CENTRAL_PASSWORD: ${{ secrets.SONATYPE_PASSWORD }} # must be the same env variable name as (2)
|
||||
MAVEN_CENTRAL_USERNAME: ${{ secrets.CENTRAL_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_GPG_KEY: ${{ secrets.GPG_KEY }} # Value of the GPG private key to import
|
||||
MAVEN_GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }}
|
||||
|
||||
@@ -33,11 +33,11 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@fca7ace96b7d713c7035871441bd52efbe39e27e # v3.28.19
|
||||
uses: github/codeql-action/init@45cbd0c69e560cd9e7cd7f8c32362050c9b7ded2 # v4.32.2
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
# 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).
|
||||
# If this step fails, then you should remove it and run the build manually (see below)
|
||||
- name: Autobuild
|
||||
uses: github/codeql-action/autobuild@fca7ace96b7d713c7035871441bd52efbe39e27e # v3.28.19
|
||||
uses: github/codeql-action/autobuild@45cbd0c69e560cd9e7cd7f8c32362050c9b7ded2 # v4.32.2
|
||||
|
||||
# ℹ️ 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
|
||||
@@ -64,6 +64,6 @@ jobs:
|
||||
# ./location_of_script_within_repo/buildscript.sh
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@fca7ace96b7d713c7035871441bd52efbe39e27e # v3.28.19
|
||||
uses: github/codeql-action/analyze@45cbd0c69e560cd9e7cd7f8c32362050c9b7ded2 # v4.32.2
|
||||
with:
|
||||
category: "/language:${{matrix.language}}"
|
||||
|
||||
@@ -26,12 +26,12 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: "Checkout code"
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
- name: "Run analysis"
|
||||
uses: ossf/scorecard-action@05b42c624433fc40578a4040d5cf5e36ddca8cde # v2.4.2
|
||||
uses: ossf/scorecard-action@4eaacf0543bb3f2c246792bd56e8cdeffafb205a # v2.4.3
|
||||
with:
|
||||
results_file: results.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
|
||||
# format to the repository Actions tab.
|
||||
- name: "Upload artifact"
|
||||
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
|
||||
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
|
||||
with:
|
||||
name: SARIF file
|
||||
path: results.sarif
|
||||
@@ -57,6 +57,6 @@ jobs:
|
||||
|
||||
# Upload the results to GitHub's code scanning dashboard.
|
||||
- name: "Upload to code-scanning"
|
||||
uses: github/codeql-action/upload-sarif@fca7ace96b7d713c7035871441bd52efbe39e27e # v3.28.19
|
||||
uses: github/codeql-action/upload-sarif@45cbd0c69e560cd9e7cd7f8c32362050c9b7ded2 # v4.32.2
|
||||
with:
|
||||
sarif_file: results.sarif
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
[](https://www.bestpractices.dev/projects/7900)
|
||||
|
||||
[](https://search.maven.org/search?q=g:com.twelvemonkeys.imageio)
|
||||
[](https://oss.sonatype.org/content/repositories/snapshots/com/twelvemonkeys/)
|
||||
[](https://central.sonatype.com/repository/maven-snapshots/com/twelvemonkeys/imageio/imageio/maven-metadata.xml)
|
||||
[](https://stackoverflow.com/questions/tagged/twelvemonkeys)
|
||||
[](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>
|
||||
<groupId>com.twelvemonkeys.imageio</groupId>
|
||||
<artifactId>imageio-jpeg</artifactId>
|
||||
<version>3.12.0</version>
|
||||
<version>3.13.1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.twelvemonkeys.imageio</groupId>
|
||||
<artifactId>imageio-tiff</artifactId>
|
||||
<version>3.12.0</version>
|
||||
<version>3.13.1</version>
|
||||
</dependency>
|
||||
|
||||
<!--
|
||||
@@ -331,7 +331,7 @@ To depend on the JPEG and TIFF plugin using Maven, add the following to your POM
|
||||
<dependency>
|
||||
<groupId>com.twelvemonkeys.servlet</groupId>
|
||||
<artifactId>servlet</artifactId>
|
||||
<version>3.12.0</version>
|
||||
<version>3.13.1</version>
|
||||
</dependency>
|
||||
|
||||
<!--
|
||||
@@ -340,7 +340,7 @@ To depend on the JPEG and TIFF plugin using Maven, add the following to your POM
|
||||
<dependency>
|
||||
<groupId>com.twelvemonkeys.servlet</groupId>
|
||||
<artifactId>servlet</artifactId>
|
||||
<version>3.12.0</version>
|
||||
<version>3.13.1</version>
|
||||
<classifier>jakarta</classifier>
|
||||
</dependency>
|
||||
</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:
|
||||
|
||||
twelvemonkeys-common-lang-3.12.0.jar
|
||||
twelvemonkeys-common-io-3.12.0.jar
|
||||
twelvemonkeys-common-image-3.12.0.jar
|
||||
twelvemonkeys-imageio-core-3.12.0.jar
|
||||
twelvemonkeys-imageio-metadata-3.12.0.jar
|
||||
twelvemonkeys-imageio-jpeg-3.12.0.jar
|
||||
twelvemonkeys-imageio-tiff-3.12.0.jar
|
||||
twelvemonkeys-common-lang-3.13.1.jar
|
||||
twelvemonkeys-common-io-3.13.1.jar
|
||||
twelvemonkeys-common-image-3.13.1.jar
|
||||
twelvemonkeys-imageio-core-3.13.1.jar
|
||||
twelvemonkeys-imageio-metadata-3.13.1.jar
|
||||
twelvemonkeys-imageio-jpeg-3.13.1.jar
|
||||
twelvemonkeys-imageio-tiff-3.13.1.jar
|
||||
|
||||
#### 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
|
||||
|
||||
##### Latest version (3.12.0)
|
||||
##### Latest version (3.13.1)
|
||||
|
||||
The latest version that will run on Java 7 is 3.9.4. Later versions will require Java 8 or later.
|
||||
|
||||
Common dependencies
|
||||
* [common-lang-3.12.0.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/common/common-lang/3.12.0/common-lang-3.12.0.jar)
|
||||
* [common-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.12.0.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/common/common-image/3.12.0/common-image-3.12.0.jar)
|
||||
* [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-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-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)
|
||||
|
||||
ImageIO dependencies
|
||||
* [imageio-core-3.12.0.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-core/3.12.0/imageio-core-3.12.0.jar)
|
||||
* [imageio-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-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-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 plugins
|
||||
* [imageio-bmp-3.12.0.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-bmp/3.12.0/imageio-bmp-3.12.0.jar)
|
||||
* [imageio-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.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.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.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.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.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.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.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.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.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.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.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.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.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.12.0.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-xwd/3.12.0/imageio-xwd-3.12.0.jar)
|
||||
* [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-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-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-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-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-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-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-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-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-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-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-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-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-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-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-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 plugins requiring 3rd party libs
|
||||
* [imageio-batik-3.12.0.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-batik/3.12.0/imageio-batik-3.12.0.jar)
|
||||
* [imageio-batik-3.13.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-batik/3.13.1/imageio-batik-3.13.1.jar)
|
||||
|
||||
Photoshop Path support for ImageIO
|
||||
* [imageio-clippath-3.12.0.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-clippath/3.12.0/imageio-clippath-3.12.0.jar)
|
||||
* [imageio-clippath-3.13.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-clippath/3.13.1/imageio-clippath-3.13.1.jar)
|
||||
|
||||
Servlet support
|
||||
* [servlet-3.12.0.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/servlet/servlet/3.12.0/servlet-3.12.0.jar) for legacy Java EE (javax.servlet)
|
||||
* [servlet-3.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)
|
||||
* [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.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)
|
||||
|
||||
## License
|
||||
|
||||
|
||||
+1
-1
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<groupId>com.twelvemonkeys</groupId>
|
||||
<artifactId>twelvemonkeys</artifactId>
|
||||
<version>3.12.1-SNAPSHOT</version>
|
||||
<version>3.13.2-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<groupId>com.twelvemonkeys.bom</groupId>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<groupId>com.twelvemonkeys.common</groupId>
|
||||
<artifactId>common</artifactId>
|
||||
<version>3.12.1-SNAPSHOT</version>
|
||||
<version>3.13.2-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>common-image</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
@@ -47,10 +47,10 @@ import java.util.Random;
|
||||
* |3|5|1|
|
||||
* - - -->
|
||||
* </p>
|
||||
* <table border="1" cellpadding="4" cellspacing="0">
|
||||
* <table border="1">
|
||||
* <caption>Floyd-Steinberg error-diffusion weights</caption>
|
||||
* <tr><td bgcolor="#000000"> </td><td class="TableHeadingColor"
|
||||
* align="center">x</td><td>7/16</td></tr>
|
||||
* <tr><td style="background:#000000"> </td><td class="TableHeadingColor"
|
||||
* style="text-align:center">x</td><td>7/16</td></tr>
|
||||
* <tr><td>3/16</td><td>5/16</td><td>1/16</td></tr>
|
||||
* </table>
|
||||
* <p>
|
||||
|
||||
@@ -162,7 +162,7 @@ public final class ImageUtil {
|
||||
|
||||
/**
|
||||
* The sharpen kernel. Uses the following 3 by 3 matrix:
|
||||
* <table border="1" cellspacing="0">
|
||||
* <table border="1">
|
||||
* <caption>Sharpen Kernel Matrix</caption>
|
||||
* <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>
|
||||
@@ -1078,7 +1078,7 @@ public final class ImageUtil {
|
||||
/**
|
||||
* Sharpens an image using a convolution matrix.
|
||||
* The sharpen kernel used, is defined by the following 3 by 3 matrix:
|
||||
* <table border="1" cellspacing="0">
|
||||
* <table border="1">
|
||||
* <caption>Sharpen Kernel Matrix</caption>
|
||||
* <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>
|
||||
@@ -1100,7 +1100,7 @@ public final class ImageUtil {
|
||||
/**
|
||||
* Sharpens an image using a convolution matrix.
|
||||
* The sharpen kernel used, is defined by the following 3 by 3 matrix:
|
||||
* <table border="1" cellspacing="0">
|
||||
* <table border="1">
|
||||
* <caption>Sharpen Kernel Matrix</caption>
|
||||
* <tr><td>0.0</td><td>-{@code pAmount}</td><td>0.0</td></tr>
|
||||
* <tr><td>-{@code pAmount}</td>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<groupId>com.twelvemonkeys.common</groupId>
|
||||
<artifactId>common</artifactId>
|
||||
<version>3.12.1-SNAPSHOT</version>
|
||||
<version>3.13.2-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>common-io</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<groupId>com.twelvemonkeys.common</groupId>
|
||||
<artifactId>common</artifactId>
|
||||
<version>3.12.1-SNAPSHOT</version>
|
||||
<version>3.13.2-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>common-lang</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
@@ -1765,12 +1765,11 @@ public final class StringUtil {
|
||||
* expression.
|
||||
* <p>
|
||||
* An invocation of this method of the form
|
||||
* <tt>matches(<i>str</i>, <i>regex</i>)</tt> yields exactly the
|
||||
* {@code matches(str, regex)} yields exactly the
|
||||
* same result as the expression
|
||||
* </p>
|
||||
* <blockquote><tt> {@link Pattern}.
|
||||
* {@link Pattern#matches(String, CharSequence) matches}
|
||||
* (<i>regex</i>, <i>str</i>)</tt></blockquote>
|
||||
* <blockquote>{@link Pattern}.
|
||||
* {@link Pattern#matches(String, CharSequence) matches(regex, str)}</blockquote>
|
||||
*
|
||||
* @param pString the string
|
||||
* @param pRegex the regular expression to which this string is to be matched
|
||||
@@ -1789,16 +1788,14 @@ public final class StringUtil {
|
||||
* regular expression with the given pReplacement.
|
||||
* <p>
|
||||
* An invocation of this method of the form
|
||||
* <tt>
|
||||
* replaceFirst(<i>str</i>, <i>regex</i>, <i>repl</i>)
|
||||
* </tt>
|
||||
* {@code replaceFirst(str, regex, repl)}
|
||||
* yields exactly the same result as the expression:
|
||||
* </p>
|
||||
* <blockquote><tt>
|
||||
* {@link Pattern}.{@link Pattern#compile(String) compile}(<i>regex</i>).
|
||||
* {@link Pattern#matcher matcher}(<i>str</i>).
|
||||
* {@link java.util.regex.Matcher#replaceFirst replaceFirst}(<i>repl</i>)
|
||||
* </tt></blockquote>
|
||||
* <blockquote>
|
||||
* {@link Pattern#compile(String) Pattern.compile(regex)}
|
||||
* {@link Pattern#matcher .matcher(str)}
|
||||
* {@link java.util.regex.Matcher#replaceFirst .replaceFirst(repl)}
|
||||
* </blockquote>
|
||||
*
|
||||
* @param pString the string
|
||||
* @param pRegex the regular expression to which this string is to be matched
|
||||
@@ -1817,14 +1814,14 @@ public final class StringUtil {
|
||||
* regular expression with the given pReplacement.
|
||||
* <p>
|
||||
* An invocation of this method of the form
|
||||
* <tt>replaceAll(<i>str</i>, <i>pRegex</i>, <i>repl</i>)</tt>
|
||||
* {@code replaceAll(str, pRegex, repl)}
|
||||
* yields exactly the same result as the expression
|
||||
* </p>
|
||||
* <blockquote><tt>
|
||||
* {@link Pattern}.{@link Pattern#compile(String) compile}(<i>pRegex</i>).
|
||||
* {@link Pattern#matcher matcher}(<i>str</i>{@code ).
|
||||
* {@link java.util.regex.Matcher#replaceAll replaceAll}(}<i>repl</i>{@code )}
|
||||
* </tt></blockquote>
|
||||
* <blockquote>
|
||||
* {@link Pattern#compile(String) Pattern.compile(pRegex)}
|
||||
* {@link Pattern#matcher .matcher(str)}
|
||||
* {@link java.util.regex.Matcher#replaceAll .replaceAll(repl)}
|
||||
* </blockquote>
|
||||
*
|
||||
* @param pString the string
|
||||
* @param pRegex the regular expression to which this string is to be matched
|
||||
@@ -1862,12 +1859,12 @@ public final class StringUtil {
|
||||
* </p>
|
||||
* <p>
|
||||
* An invocation of this method of the form
|
||||
* <tt>split(<i>str</i>, <i>regex</i>, <i>n</i>)</tt>
|
||||
* {@code split(str, regex, n)}
|
||||
* yields the same result as the expression:
|
||||
* </p>
|
||||
* <blockquote>{@link Pattern}.
|
||||
* {@link Pattern#compile(String) compile}<tt>(<i>regex</i>).
|
||||
* {@link Pattern#split(CharSequence,int) split}(<i>str</i>, <i>n</i>)</tt>
|
||||
* {@link Pattern#compile(String) compile(regex)}.
|
||||
* {@link Pattern#split(CharSequence,int) split(str, n)}
|
||||
* </blockquote>
|
||||
*
|
||||
* @param pString the string
|
||||
|
||||
+8
-3
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<groupId>com.twelvemonkeys</groupId>
|
||||
<artifactId>twelvemonkeys</artifactId>
|
||||
<version>3.12.1-SNAPSHOT</version>
|
||||
<version>3.13.2-SNAPSHOT</version>
|
||||
</parent>
|
||||
<groupId>com.twelvemonkeys.common</groupId>
|
||||
<artifactId>common</artifactId>
|
||||
@@ -20,6 +20,10 @@
|
||||
<module>common-image</module>
|
||||
</modules>
|
||||
|
||||
<properties>
|
||||
<junit.jupiter.version>5.14.2</junit.jupiter.version>
|
||||
</properties>
|
||||
|
||||
<dependencyManagement>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
@@ -43,17 +47,18 @@
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter-api</artifactId>
|
||||
<version>5.12.2</version>
|
||||
<version>${junit.jupiter.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter-params</artifactId>
|
||||
<version>5.12.2</version>
|
||||
<version>${junit.jupiter.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
+8
-3
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<groupId>com.twelvemonkeys</groupId>
|
||||
<artifactId>twelvemonkeys</artifactId>
|
||||
<version>3.12.1-SNAPSHOT</version>
|
||||
<version>3.13.2-SNAPSHOT</version>
|
||||
</parent>
|
||||
<groupId>com.twelvemonkeys.contrib</groupId>
|
||||
<artifactId>contrib</artifactId>
|
||||
@@ -13,6 +13,11 @@
|
||||
Contributions to TwelveMonkeys and code that doesn't fit anywhere else.
|
||||
</description>
|
||||
|
||||
<properties>
|
||||
<junit.jupiter.version>5.14.2</junit.jupiter.version>
|
||||
</properties>
|
||||
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.twelvemonkeys.common</groupId>
|
||||
@@ -64,13 +69,13 @@
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter-engine</artifactId>
|
||||
<version>5.12.2</version>
|
||||
<version>${junit.jupiter.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter-api</artifactId>
|
||||
<version>5.12.2</version>
|
||||
<version>${junit.jupiter.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<groupId>com.twelvemonkeys.imageio</groupId>
|
||||
<artifactId>imageio</artifactId>
|
||||
<version>3.12.1-SNAPSHOT</version>
|
||||
<version>3.13.2-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>imageio-batik</artifactId>
|
||||
<name>TwelveMonkeys :: ImageIO :: Batik Plugin</name>
|
||||
@@ -63,7 +63,7 @@
|
||||
<dependency>
|
||||
<groupId>commons-io</groupId>
|
||||
<artifactId>commons-io</artifactId>
|
||||
<version>2.19.0</version>
|
||||
<version>2.21.0</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
|
||||
+46
-1
@@ -36,9 +36,11 @@ import com.twelvemonkeys.lang.SystemUtil;
|
||||
import javax.imageio.ImageReader;
|
||||
import javax.imageio.spi.ServiceRegistry;
|
||||
import javax.imageio.stream.ImageInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.EOFException;
|
||||
import java.io.IOException;
|
||||
import java.util.Locale;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import static com.twelvemonkeys.imageio.util.IIOUtil.deregisterProvider;
|
||||
|
||||
@@ -134,10 +136,42 @@ public final class SVGImageReaderSpi extends ImageReaderSpiBase {
|
||||
if (buffer[0] == 's' && buffer[1] == 'v' && buffer[2] == 'g'
|
||||
&& (Character.isWhitespace((char) buffer[3]) || buffer[3] == ':')) {
|
||||
// It's SVG, identified by root tag
|
||||
// TODO: Support svg with prefix + recognize namespace (http://www.w3.org/2000/svg)!
|
||||
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
|
||||
return false;
|
||||
}
|
||||
@@ -157,6 +191,17 @@ 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 {
|
||||
return new SVGImageReader(this);
|
||||
}
|
||||
|
||||
+4
-1
@@ -56,7 +56,7 @@ public class SVGImageReaderSpiTest {
|
||||
"/svg/Android_robot.svg", // Minimal, no xml dec, no namespace
|
||||
"/svg/batikLogo.svg", // xml dec, comments, namespace
|
||||
"/svg/blue-square.svg", // xml dec, namespace
|
||||
"/svg/red-square.svg",
|
||||
"/svg/red-square.svg", // prefixed namespace
|
||||
};
|
||||
|
||||
private static final String[] INVALID_INPUTS = {
|
||||
@@ -70,6 +70,9 @@ public class SVGImageReaderSpiTest {
|
||||
"<!-- ", // #275 Infinite loop issue
|
||||
"<?123?>", // #275 Infinite loop issue
|
||||
"<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 {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100" id="red-square" version="1.1">
|
||||
<g id="layer1">
|
||||
<rect id="rect2985" width="100" height="100" x="0" y="0"
|
||||
<ns0:svg xmlns:ns0="http://www.w3.org/2000/svg" width="100" height="100" id="red-square" version="1.1">
|
||||
<ns0:g id="layer1">
|
||||
<ns0: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" />
|
||||
</g>
|
||||
</svg>
|
||||
</ns0:g>
|
||||
</ns0:svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 441 B After Width: | Height: | Size: 465 B |
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<groupId>com.twelvemonkeys.imageio</groupId>
|
||||
<artifactId>imageio</artifactId>
|
||||
<version>3.12.1-SNAPSHOT</version>
|
||||
<version>3.13.2-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>imageio-bmp</artifactId>
|
||||
<name>TwelveMonkeys :: ImageIO :: BMP plugin</name>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<groupId>com.twelvemonkeys.imageio</groupId>
|
||||
<artifactId>imageio</artifactId>
|
||||
<version>3.12.1-SNAPSHOT</version>
|
||||
<version>3.13.2-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>imageio-clippath</artifactId>
|
||||
<name>TwelveMonkeys :: ImageIO :: Photoshop Path Support</name>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<groupId>com.twelvemonkeys.imageio</groupId>
|
||||
<artifactId>imageio</artifactId>
|
||||
<version>3.12.1-SNAPSHOT</version>
|
||||
<version>3.13.2-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>imageio-core</artifactId>
|
||||
<name>TwelveMonkeys :: ImageIO :: Core</name>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<groupId>com.twelvemonkeys.imageio</groupId>
|
||||
<artifactId>imageio</artifactId>
|
||||
<version>3.12.1-SNAPSHOT</version>
|
||||
<version>3.13.2-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>imageio-dds</artifactId>
|
||||
<name>TwelveMonkeys :: ImageIO :: DDS plugin</name>
|
||||
|
||||
@@ -32,7 +32,7 @@ package com.twelvemonkeys.imageio.plugins.dds;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
interface DDS {
|
||||
byte[] MAGIC = new byte[]{'D', 'D', 'S', ' '};
|
||||
int MAGIC = ('D' << 24) + ('D' << 16) + ('S' << 8) + ' '; //Big-Endian
|
||||
int HEADER_SIZE = 124;
|
||||
|
||||
// Header Flags
|
||||
@@ -48,4 +48,7 @@ interface DDS {
|
||||
// Pixel Format Flags
|
||||
int PIXEL_FORMAT_FLAG_FOURCC = 0x04;
|
||||
int PIXEL_FORMAT_FLAG_RGB = 0x40;
|
||||
|
||||
//DX10 Resource Dimensions
|
||||
int D3D10_RESOURCE_DIMENSION_TEXTURE2D = 3;
|
||||
}
|
||||
|
||||
+7
-8
@@ -34,8 +34,7 @@ import javax.imageio.IIOException;
|
||||
import javax.imageio.stream.ImageInputStream;
|
||||
import java.awt.Dimension;
|
||||
import java.io.IOException;
|
||||
import java.math.BigInteger;
|
||||
import java.util.Arrays;
|
||||
import java.nio.ByteOrder;
|
||||
|
||||
final class DDSHeader {
|
||||
|
||||
@@ -58,11 +57,12 @@ final class DDSHeader {
|
||||
DDSHeader header = new DDSHeader();
|
||||
|
||||
// Read MAGIC bytes [0,3]
|
||||
byte[] magic = new byte[DDS.MAGIC.length];
|
||||
imageInput.readFully(magic);
|
||||
if (!Arrays.equals(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.BIG_ENDIAN);
|
||||
int magic = imageInput.readInt();
|
||||
if (magic != DDS.MAGIC) {
|
||||
throw new IIOException(String.format("Not a DDS file. Expected DDS magic 0x%8x', read 0x%8x", DDS.MAGIC, magic));
|
||||
}
|
||||
imageInput.setByteOrder(ByteOrder.LITTLE_ENDIAN);
|
||||
|
||||
// DDS_HEADER structure
|
||||
// https://learn.microsoft.com/en-us/windows/win32/direct3ddds/dds-header
|
||||
@@ -93,8 +93,7 @@ final class DDSHeader {
|
||||
// build dimensions list
|
||||
header.addDimensions(dwWidth, dwHeight);
|
||||
|
||||
byte[] dwReserved1 = new byte[11 * 4]; // [32,75]
|
||||
imageInput.readFully(dwReserved1);
|
||||
imageInput.skipBytes(44);
|
||||
|
||||
// DDS_PIXELFORMAT structure
|
||||
int px_dwSize = imageInput.readInt(); // [76,79]
|
||||
|
||||
+1
-5
@@ -35,7 +35,6 @@ import com.twelvemonkeys.imageio.spi.ImageReaderSpiBase;
|
||||
import javax.imageio.ImageReader;
|
||||
import javax.imageio.stream.ImageInputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Locale;
|
||||
|
||||
public final class DDSImageReaderSpi extends ImageReaderSpiBase {
|
||||
@@ -55,10 +54,7 @@ public final class DDSImageReaderSpi extends ImageReaderSpiBase {
|
||||
stream.mark();
|
||||
|
||||
try {
|
||||
byte[] magic = new byte[DDS.MAGIC.length];
|
||||
stream.readFully(magic);
|
||||
|
||||
return Arrays.equals(DDS.MAGIC, magic);
|
||||
return stream.readInt() == DDS.MAGIC;
|
||||
} finally {
|
||||
stream.reset();
|
||||
}
|
||||
|
||||
+9
-5
@@ -74,15 +74,19 @@ final class DDSReader {
|
||||
static final Order ARGB_ORDER = new Order(16, 8, 0, 24);
|
||||
|
||||
private final DDSHeader header;
|
||||
private DX10Header dxt10Header;
|
||||
|
||||
DDSReader(DDSHeader header) {
|
||||
this.header = header;
|
||||
}
|
||||
|
||||
int[] read(ImageInputStream imageInput, int imageIndex) throws IOException {
|
||||
|
||||
// type
|
||||
DDSType type = getType();
|
||||
if (type == DDSType.DXT10) {
|
||||
dxt10Header = DX10Header.read(imageInput);
|
||||
type = dxt10Header.getDDSType();
|
||||
}
|
||||
|
||||
// offset buffer to index mipmap image
|
||||
byte[] buffer = null;
|
||||
@@ -138,7 +142,6 @@ final class DDSReader {
|
||||
// DXT
|
||||
int type = header.getFourCC();
|
||||
return DDSType.valueOf(type);
|
||||
|
||||
} else if ((flags & DDS.PIXEL_FORMAT_FLAG_RGB) != 0) {
|
||||
// RGB
|
||||
int bitCount = header.getBitCount();
|
||||
@@ -224,6 +227,7 @@ final class DDSReader {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static int[] decodeDXT1(int width, int height, byte[] buffer) {
|
||||
int[] pixels = new int[width * height];
|
||||
int index = 0;
|
||||
@@ -241,7 +245,7 @@ final class DDSReader {
|
||||
int t1 = (buffer[index] & 0x0C) >> 2;
|
||||
int t2 = (buffer[index] & 0x30) >> 4;
|
||||
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;
|
||||
pixels[4 * width * i + 4 * j + width * k + 1] = getDXTColor(c0, c1, 0xFF, t1);
|
||||
if (4 * j + 2 >= width) continue;
|
||||
@@ -286,7 +290,7 @@ final class DDSReader {
|
||||
int t1 = (buffer[index] & 0x0C) >> 2;
|
||||
int t2 = (buffer[index] & 0x30) >> 4;
|
||||
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;
|
||||
pixels[4 * width * i + 4 * j + width * k + 1] = getDXTColor(c0, c1, alphaTable[4 * k + 1], t1);
|
||||
if (4 * j + 2 >= width) continue;
|
||||
@@ -344,7 +348,7 @@ final class DDSReader {
|
||||
int t1 = (buffer[index] & 0x0C) >> 2;
|
||||
int t2 = (buffer[index] & 0x30) >> 4;
|
||||
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;
|
||||
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;
|
||||
|
||||
+1
-1
@@ -31,12 +31,12 @@
|
||||
package com.twelvemonkeys.imageio.plugins.dds;
|
||||
|
||||
enum DDSType {
|
||||
|
||||
DXT1(0x31545844),
|
||||
DXT2(0x32545844),
|
||||
DXT3(0x33545844),
|
||||
DXT4(0x34545844),
|
||||
DXT5(0x35545844),
|
||||
DXT10(0x30315844),
|
||||
A1R5G5B5((1 << 16) | 2),
|
||||
X1R5G5B5((2 << 16) | 2),
|
||||
A4R4G4B4((3 << 16) | 2),
|
||||
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
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();
|
||||
}
|
||||
}
|
||||
+7
-1
@@ -86,7 +86,13 @@ public class DDSImageReaderTest extends ImageReaderAbstractTest<DDSImageReader>
|
||||
new TestData(getClassLoaderResource("/dds/dds_X8B8G8R8.dds"), dim256),
|
||||
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_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)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<groupId>com.twelvemonkeys.imageio</groupId>
|
||||
<artifactId>imageio</artifactId>
|
||||
<version>3.12.1-SNAPSHOT</version>
|
||||
<version>3.13.2-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>imageio-hdr</artifactId>
|
||||
<name>TwelveMonkeys :: ImageIO :: HDR plugin</name>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<groupId>com.twelvemonkeys.imageio</groupId>
|
||||
<artifactId>imageio</artifactId>
|
||||
<version>3.12.1-SNAPSHOT</version>
|
||||
<version>3.13.2-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>imageio-icns</artifactId>
|
||||
<name>TwelveMonkeys :: ImageIO :: ICNS plugin</name>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<groupId>com.twelvemonkeys.imageio</groupId>
|
||||
<artifactId>imageio</artifactId>
|
||||
<version>3.12.1-SNAPSHOT</version>
|
||||
<version>3.13.2-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>imageio-iff</artifactId>
|
||||
<name>TwelveMonkeys :: ImageIO :: IFF plugin</name>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<groupId>com.twelvemonkeys.imageio</groupId>
|
||||
<artifactId>imageio</artifactId>
|
||||
<version>3.12.1-SNAPSHOT</version>
|
||||
<version>3.13.2-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>imageio-jpeg-jai-interop</artifactId>
|
||||
<name>TwelveMonkeys :: ImageIO :: JPEG/JAI TIFF Interop</name>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<groupId>com.twelvemonkeys.imageio</groupId>
|
||||
<artifactId>imageio</artifactId>
|
||||
<version>3.12.1-SNAPSHOT</version>
|
||||
<version>3.13.2-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>imageio-jpeg-jep262-interop</artifactId>
|
||||
<name>TwelveMonkeys :: ImageIO :: JPEG/JEP-262 Interop</name>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<groupId>com.twelvemonkeys.imageio</groupId>
|
||||
<artifactId>imageio</artifactId>
|
||||
<version>3.12.1-SNAPSHOT</version>
|
||||
<version>3.13.2-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>imageio-jpeg</artifactId>
|
||||
<name>TwelveMonkeys :: ImageIO :: JPEG plugin</name>
|
||||
|
||||
+23
-3
@@ -212,7 +212,9 @@ final class JPEGLosslessDecoder {
|
||||
|
||||
final int[] firstValue = new int[numComp];
|
||||
for (int i = 0; i < numComp; i++) {
|
||||
firstValue[i] = (1 << (precision - 1));
|
||||
// scan.approxLow is the point transformation (Pt) value
|
||||
// ref. ISO/IEC 10918-1 H.1.2.1
|
||||
firstValue[i] = (1 << (precision - scan.approxLow - 1));
|
||||
}
|
||||
|
||||
final int[] pred = new int[numComp];
|
||||
@@ -232,6 +234,11 @@ final class JPEGLosslessDecoder {
|
||||
output(pred);
|
||||
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
|
||||
}
|
||||
@@ -268,6 +275,17 @@ final class JPEGLosslessDecoder {
|
||||
// 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));
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
@@ -329,9 +347,11 @@ final class JPEGLosslessDecoder {
|
||||
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 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) {
|
||||
restarting = false;
|
||||
prev[0] = (1 << (frame.samplePrecision - 1));
|
||||
prev[0] = (1 << (frame.samplePrecision - scan.approxLow - 1));
|
||||
}
|
||||
else {
|
||||
final int[] outputData = this.outputData[0];
|
||||
@@ -686,7 +706,7 @@ final class JPEGLosslessDecoder {
|
||||
return getPreviousY(data);
|
||||
}
|
||||
else {
|
||||
return (1 << (frame.samplePrecision - 1));
|
||||
return (1 << (frame.samplePrecision - scan.approxLow - 1));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+61
@@ -2033,4 +2033,65 @@ 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.
|
After Width: | Height: | Size: 16 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 9.2 KiB |
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>com.twelvemonkeys.imageio</groupId>
|
||||
<artifactId>imageio</artifactId>
|
||||
<version>3.12.1-SNAPSHOT</version>
|
||||
<version>3.13.2-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>imageio-metadata</artifactId>
|
||||
|
||||
+6
-2
@@ -41,7 +41,11 @@ import javax.imageio.stream.ImageOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteOrder;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.*;
|
||||
import java.util.ArrayList;
|
||||
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.getValueLength;
|
||||
@@ -176,7 +180,7 @@ public final class TIFFWriter extends MetadataWriter {
|
||||
stream.seek(dataOffset);
|
||||
Directory subIFD = (Directory) value;
|
||||
writeIFD(subIFD, stream, true);
|
||||
dataOffset += computeDataSize(subIFD);
|
||||
dataOffset += computeDataSize(subIFD) + directoryCountLength + subIFD.size() * entryLength;
|
||||
stream.seek(streamPosition);
|
||||
}
|
||||
else {
|
||||
|
||||
+64
-10
@@ -30,14 +30,23 @@
|
||||
|
||||
package com.twelvemonkeys.imageio.metadata.tiff;
|
||||
|
||||
import com.twelvemonkeys.imageio.metadata.*;
|
||||
import com.twelvemonkeys.imageio.metadata.AbstractDirectory;
|
||||
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.io.FastByteArrayOutputStream;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import javax.imageio.stream.ImageInputStream;
|
||||
import javax.imageio.stream.ImageOutputStream;
|
||||
import javax.imageio.stream.ImageOutputStreamImpl;
|
||||
import javax.imageio.stream.MemoryCacheImageOutputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
@@ -46,8 +55,10 @@ import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertInstanceOf;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
|
||||
/**
|
||||
* TIFFWriterTest
|
||||
@@ -272,7 +283,7 @@ public class TIFFWriterTest extends MetadataWriterAbstractTest {
|
||||
Directory read = new TIFFReader().read(new ByteArrayImageInputStream(data));
|
||||
|
||||
assertNotNull(read.getEntryById(TIFF.TAG_SOFTWARE));
|
||||
assertTrue(read.getEntryById(TIFF.TAG_SOFTWARE).getValue() instanceof String[], "value not an string array");
|
||||
assertInstanceOf(String[].class, read.getEntryById(TIFF.TAG_SOFTWARE).getValue(), "value not an string array");
|
||||
assertArrayEquals(strings, (String[]) read.getEntryById(TIFF.TAG_SOFTWARE).getValue());
|
||||
}
|
||||
|
||||
@@ -285,7 +296,7 @@ public class TIFFWriterTest extends MetadataWriterAbstractTest {
|
||||
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)));
|
||||
|
||||
List<Entry> entries = Collections.<Entry>singletonList(subIFD);
|
||||
List<Entry> entries = Collections.singletonList(subIFD);
|
||||
|
||||
TIFFWriter writer = createWriter();
|
||||
|
||||
@@ -296,24 +307,67 @@ public class TIFFWriterTest extends MetadataWriterAbstractTest {
|
||||
assertEquals(96, stream.getStreamPosition()); // 96 = 4 + 5 * (2 + 12) + 22
|
||||
}
|
||||
|
||||
private static class NullImageOutputStream extends ImageOutputStreamImpl {
|
||||
@Test
|
||||
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
|
||||
public void write(int b) throws IOException {
|
||||
public void write(int b) {
|
||||
streamPos++;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(byte[] b, int off, int len) throws IOException {
|
||||
public void write(byte[] b, int off, int len) {
|
||||
streamPos += len;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read() throws IOException {
|
||||
public int read() {
|
||||
throw new UnsupportedOperationException("Method read not implemented");
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read(byte[] b, int off, int len) throws IOException {
|
||||
public int read(byte[] b, int off, int len) {
|
||||
throw new UnsupportedOperationException("Method read not implemented");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<groupId>com.twelvemonkeys.imageio</groupId>
|
||||
<artifactId>imageio</artifactId>
|
||||
<version>3.12.1-SNAPSHOT</version>
|
||||
<version>3.13.2-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>imageio-pcx</artifactId>
|
||||
<name>TwelveMonkeys :: ImageIO :: PCX plugin</name>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<groupId>com.twelvemonkeys.imageio</groupId>
|
||||
<artifactId>imageio</artifactId>
|
||||
<version>3.12.1-SNAPSHOT</version>
|
||||
<version>3.13.2-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>imageio-pdf</artifactId>
|
||||
<name>TwelveMonkeys :: ImageIO :: PDF plugin</name>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<groupId>com.twelvemonkeys.imageio</groupId>
|
||||
<artifactId>imageio</artifactId>
|
||||
<version>3.12.1-SNAPSHOT</version>
|
||||
<version>3.13.2-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>imageio-pict</artifactId>
|
||||
<name>TwelveMonkeys :: ImageIO :: PICT plugin</name>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<groupId>com.twelvemonkeys.imageio</groupId>
|
||||
<artifactId>imageio</artifactId>
|
||||
<version>3.12.1-SNAPSHOT</version>
|
||||
<version>3.13.2-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>imageio-pnm</artifactId>
|
||||
<name>TwelveMonkeys :: ImageIO :: PNM plugin</name>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<groupId>com.twelvemonkeys.imageio</groupId>
|
||||
<artifactId>imageio</artifactId>
|
||||
<version>3.12.1-SNAPSHOT</version>
|
||||
<version>3.13.2-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>imageio-psd</artifactId>
|
||||
<name>TwelveMonkeys :: ImageIO :: PSD plugin</name>
|
||||
|
||||
+3
-3
@@ -410,9 +410,9 @@ public final class PSDMetadata extends AbstractMetadata {
|
||||
if ((psdLayerInfo.blendMode.flags & 0x01) != 0) {
|
||||
node.setAttribute("transparencyProtected", "true");
|
||||
}
|
||||
if ((psdLayerInfo.blendMode.flags & 0x02) != 0) {
|
||||
node.setAttribute("visible", "true");
|
||||
}
|
||||
// Include always, to avoid ambiguity, as the flag is really "hidden", not "visible"...
|
||||
boolean hidden = (psdLayerInfo.blendMode.flags & 0x02) != 0;
|
||||
node.setAttribute("visible", hidden ? "false" : "true");
|
||||
if ((psdLayerInfo.blendMode.flags & 0x04) != 0) {
|
||||
node.setAttribute("obsolete", "true");
|
||||
}
|
||||
|
||||
+119
@@ -0,0 +1,119 @@
|
||||
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"));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<groupId>com.twelvemonkeys.imageio</groupId>
|
||||
<artifactId>imageio</artifactId>
|
||||
<version>3.12.1-SNAPSHOT</version>
|
||||
<version>3.13.2-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>imageio-reference</artifactId>
|
||||
<name>TwelveMonkeys :: ImageIO :: JDK Reference Tests</name>
|
||||
|
||||
+6
@@ -111,6 +111,12 @@ public class JPEGImageReaderTest extends ImageReaderAbstractTest<JPEGImageReader
|
||||
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
|
||||
@Disabled("No test data with JFIF thumbnail")
|
||||
@Override
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<groupId>com.twelvemonkeys.imageio</groupId>
|
||||
<artifactId>imageio</artifactId>
|
||||
<version>3.12.1-SNAPSHOT</version>
|
||||
<version>3.13.2-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>imageio-sgi</artifactId>
|
||||
<name>TwelveMonkeys :: ImageIO :: SGI plugin</name>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<groupId>com.twelvemonkeys.imageio</groupId>
|
||||
<artifactId>imageio</artifactId>
|
||||
<version>3.12.1-SNAPSHOT</version>
|
||||
<version>3.13.2-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>imageio-tga</artifactId>
|
||||
<name>TwelveMonkeys :: ImageIO :: TGA plugin</name>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<groupId>com.twelvemonkeys.imageio</groupId>
|
||||
<artifactId>imageio</artifactId>
|
||||
<version>3.12.1-SNAPSHOT</version>
|
||||
<version>3.13.2-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>imageio-thumbsdb</artifactId>
|
||||
<name>TwelveMonkeys :: ImageIO :: Thumbs.db plugin</name>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<groupId>com.twelvemonkeys.imageio</groupId>
|
||||
<artifactId>imageio</artifactId>
|
||||
<version>3.12.1-SNAPSHOT</version>
|
||||
<version>3.13.2-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>imageio-tiff-jai-interop</artifactId>
|
||||
<name>TwelveMonkeys :: ImageIO :: TIFF/JAI Metadata Interop</name>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<groupId>com.twelvemonkeys.imageio</groupId>
|
||||
<artifactId>imageio</artifactId>
|
||||
<version>3.12.1-SNAPSHOT</version>
|
||||
<version>3.13.2-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>imageio-tiff-jdk-interop</artifactId>
|
||||
<name>TwelveMonkeys :: ImageIO :: TIFF/JDK JPEG Interop</name>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<groupId>com.twelvemonkeys.imageio</groupId>
|
||||
<artifactId>imageio</artifactId>
|
||||
<version>3.12.1-SNAPSHOT</version>
|
||||
<version>3.13.2-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>imageio-tiff</artifactId>
|
||||
<name>TwelveMonkeys :: ImageIO :: TIFF plugin</name>
|
||||
|
||||
+4
-7
@@ -71,18 +71,16 @@ public final class TIFFImageMetadata extends AbstractMetadata {
|
||||
|
||||
/**
|
||||
* Creates an empty TIFF metadata object.
|
||||
*
|
||||
* Client code can update or change the metadata using the
|
||||
* {@link #setFromTree(String, Node)}
|
||||
* or {@link #mergeTree(String, Node)} methods.
|
||||
*/
|
||||
public TIFFImageMetadata() {
|
||||
this(new IFD(Collections.<Entry>emptyList()));
|
||||
this(new IFD(Collections.emptyList()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a TIFF metadata object, using the values from the given IFD.
|
||||
*
|
||||
* Client code can update or change the metadata using the
|
||||
* {@link #setFromTree(String, Node)}
|
||||
* or {@link #mergeTree(String, Node)} methods.
|
||||
@@ -95,7 +93,6 @@ public final class TIFFImageMetadata extends AbstractMetadata {
|
||||
|
||||
/**
|
||||
* Creates a TIFF metadata object, using the values from the given entries.
|
||||
*
|
||||
* Client code can update or change the metadata using the
|
||||
* {@link #setFromTree(String, Node)}
|
||||
* or {@link #mergeTree(String, Node)} methods.
|
||||
@@ -493,10 +490,10 @@ public final class TIFFImageMetadata extends AbstractMetadata {
|
||||
compressionTypeName.setAttribute("value", "CCITT RLE");
|
||||
break;
|
||||
case TIFFExtension.COMPRESSION_CCITT_T4:
|
||||
compressionTypeName.setAttribute("value", "CCITT T4");
|
||||
compressionTypeName.setAttribute("value", "CCITT T.4");
|
||||
break;
|
||||
case TIFFExtension.COMPRESSION_CCITT_T6:
|
||||
compressionTypeName.setAttribute("value", "CCITT T6");
|
||||
compressionTypeName.setAttribute("value", "CCITT T.6");
|
||||
break;
|
||||
case TIFFExtension.COMPRESSION_LZW:
|
||||
compressionTypeName.setAttribute("value", "LZW");
|
||||
@@ -1038,7 +1035,7 @@ public final class TIFFImageMetadata extends AbstractMetadata {
|
||||
}
|
||||
|
||||
// If we have resolution
|
||||
if (xRes != null && yRes != null) {
|
||||
if (xRes != null) { // yRes != null too
|
||||
// If old unit was DPI, convert values and keep DPI, otherwise use PPCM
|
||||
Entry resUnitEntry = entries.get(TIFF.TAG_RESOLUTION_UNIT);
|
||||
int resUnitValue = resUnitEntry != null && resUnitEntry.getValue() != null
|
||||
|
||||
+96
@@ -188,6 +188,102 @@ public class TIFFImageMetadataTest {
|
||||
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
|
||||
public void testMetadataNativeFormat() throws IOException {
|
||||
IIOMetadata metadata = createMetadata("/tiff/quad-lzw.tif");
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<groupId>com.twelvemonkeys.imageio</groupId>
|
||||
<artifactId>imageio</artifactId>
|
||||
<version>3.12.1-SNAPSHOT</version>
|
||||
<version>3.13.2-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>imageio-webp</artifactId>
|
||||
<name>TwelveMonkeys :: ImageIO :: WebP plugin</name>
|
||||
|
||||
+1
-1
@@ -565,7 +565,7 @@ final class WebPImageReader extends ImageReaderBase {
|
||||
readVP8Lossless(tempRaster, null, width, height);
|
||||
|
||||
// Copy from green (band 1) in temp to alpha in destination
|
||||
WritableRaster alphaChannel = tempRaster.createWritableChild(0, 0, tempRaster.getWidth(), tempRaster.getHeight(), 0, 0, new int[]{1});
|
||||
WritableRaster alphaChannel = tempRaster.createWritableChild(0, 0, width, height, 0, 0, new int[]{1});
|
||||
alphaFilter(alphaChannel, filtering);
|
||||
copyIntoRasterWithParams(alphaChannel, alphaRaster, param);
|
||||
break;
|
||||
|
||||
+50
-42
@@ -166,73 +166,81 @@ final class HuffmanTable {
|
||||
if (numPosCodeLens == 1) {
|
||||
// Length is 0 so mask to clear length bits
|
||||
Arrays.fill(level1, lengthsAndSymbols[0] & 0xffff);
|
||||
return;
|
||||
}
|
||||
|
||||
// Due to the layout of the elements this effectively first sorts by length and then symbol.
|
||||
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.
|
||||
// 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.
|
||||
int code = 0;
|
||||
int step = 2;
|
||||
index = 0;
|
||||
|
||||
// Used for level2 lookup
|
||||
for (int length = 1; length <= LEVEL1_BITS; length++, step <<= 1) {
|
||||
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[] currentTable = null;
|
||||
|
||||
for (int i = 0; i < lengthsAndSymbols.length; i++) {
|
||||
int lengthAndSymbol = lengthsAndSymbols[i];
|
||||
step = 2;
|
||||
for (int length = LEVEL1_BITS + 1; length <= 15; length++, step <<= 1) {
|
||||
for (; count[length] > 0; count[length]--) {
|
||||
int lengthAndSymbol = lengthsAndSymbols[index++];
|
||||
|
||||
int length = lengthAndSymbol >>> 16;
|
||||
if ((code & rootMask) != rootEntry) {
|
||||
int level2Bits = nextTableBitSize(count, length, LEVEL1_BITS);
|
||||
int level2Size = 1 << level2Bits;
|
||||
|
||||
if (length <= LEVEL1_BITS) {
|
||||
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);
|
||||
currentTable = new int[level2Size];
|
||||
rootEntry = code & rootMask;
|
||||
level2.add(currentTable);
|
||||
|
||||
// Set root table indirection
|
||||
level1[rootEntry] = (LEVEL1_BITS + level2Size) << 16 | (level2.size() - 1);
|
||||
level1[rootEntry] = (LEVEL1_BITS + level2Bits) << 16 | (level2.size() - 1);
|
||||
}
|
||||
|
||||
// Add to existing (or newly generated) 2nd level table
|
||||
for (int j = (code >>> LEVEL1_BITS); j < currentTable.length; j += 1 << (length - LEVEL1_BITS)) {
|
||||
currentTable[j] = (length - LEVEL1_BITS) << 16 | (lengthAndSymbol & 0xffff);
|
||||
int value = (length - LEVEL1_BITS) << 16 | (lengthAndSymbol & 0xffff);
|
||||
for (int j = (code >>> LEVEL1_BITS); j < currentTable.length; j += step) {
|
||||
currentTable[j] = value;
|
||||
}
|
||||
|
||||
code = nextCode(code, length);
|
||||
}
|
||||
|
||||
code = nextCode(code, length);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private static int nextTableBitSize(int[] count, int length, int rootBits) {
|
||||
int left = 1 << (length - rootBits);
|
||||
while (length < 15) {
|
||||
left -= count[length];
|
||||
if (left <= 0) {
|
||||
break;
|
||||
}
|
||||
length++;
|
||||
left <<= 1;
|
||||
}
|
||||
|
||||
return length - rootBits;
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes the next code
|
||||
*
|
||||
|
||||
+20
-5
@@ -148,8 +148,7 @@ public final class VP8LDecoder {
|
||||
if (param.getSourceRegion() != null && !param.getSourceRegion().contains(bounds) ||
|
||||
param.getSourceXSubsampling() != 1 || param.getSourceYSubsampling() != 1) {
|
||||
// Can't reuse existing
|
||||
return Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE, bounds.width, bounds.height,
|
||||
4 * bounds.width, 4, new int[] {0, 1, 2, 3}, null);
|
||||
return createCompatibleRaster(raster, bounds.width, bounds.height);
|
||||
}
|
||||
else {
|
||||
bounds.setLocation(param.getDestinationOffset());
|
||||
@@ -159,8 +158,7 @@ public final class VP8LDecoder {
|
||||
|
||||
if (!raster.getBounds().contains(bounds)) {
|
||||
// Can't reuse existing
|
||||
return Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE, bounds.width, bounds.height, 4 * bounds.width,
|
||||
4, new int[] {0, 1, 2, 3}, null);
|
||||
return createCompatibleRaster(raster, bounds.width, bounds.height);
|
||||
}
|
||||
|
||||
return originSet ?
|
||||
@@ -169,6 +167,11 @@ public final class VP8LDecoder {
|
||||
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.
|
||||
*/
|
||||
@@ -182,7 +185,8 @@ public final class VP8LDecoder {
|
||||
|
||||
if (sourceXSubsampling == 1 && sourceYSubsampling == 1) {
|
||||
// Only apply offset (and limit to requested region)
|
||||
dstRaster.setRect(destinationOffset.x, destinationOffset.y, srcRaster);
|
||||
dstRaster.setRect(destinationOffset.x, destinationOffset.y, srcRaster.createChild(
|
||||
sourceRegion.x, sourceRegion.y, sourceRegion.width, sourceRegion.height, 0, 0, null));
|
||||
}
|
||||
else {
|
||||
// Subsampled case
|
||||
@@ -272,6 +276,12 @@ 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 {
|
||||
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);
|
||||
int distanceCode = lz77decode(distancePrefix);
|
||||
|
||||
@@ -298,6 +308,11 @@ public final class VP8LDecoder {
|
||||
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--) {
|
||||
// Check length and xSrc, ySrc not falling outside raster? (Should not occur if image is correct)
|
||||
if (x == width) {
|
||||
|
||||
+153
@@ -1,3 +1,4 @@
|
||||
|
||||
package com.twelvemonkeys.imageio.plugins.webp;
|
||||
|
||||
import com.twelvemonkeys.imageio.util.ImageReaderAbstractTest;
|
||||
@@ -11,6 +12,8 @@ import javax.imageio.stream.MemoryCacheImageInputStream;
|
||||
import java.awt.*;
|
||||
import java.awt.image.*;
|
||||
import java.io.IOException;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.List;
|
||||
|
||||
import static java.util.Arrays.asList;
|
||||
@@ -43,6 +46,7 @@ public class WebPImageReaderTest extends ImageReaderAbstractTest<WebPImageReader
|
||||
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_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/4_webp_ll.webp"), new Dimension(421, 163)),
|
||||
new TestData(getClassLoaderResource("/webp/5_webp_ll.webp"), new Dimension(300, 300)),
|
||||
@@ -188,4 +192,153 @@ public class WebPImageReaderTest extends ImageReaderAbstractTest<WebPImageReader
|
||||
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.
|
After Width: | Height: | Size: 27 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 63 KiB |
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<groupId>com.twelvemonkeys.imageio</groupId>
|
||||
<artifactId>imageio</artifactId>
|
||||
<version>3.12.1-SNAPSHOT</version>
|
||||
<version>3.13.2-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>imageio-xwd</artifactId>
|
||||
<name>TwelveMonkeys :: ImageIO :: XWD plugin</name>
|
||||
|
||||
+4
-7
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>com.twelvemonkeys</groupId>
|
||||
<artifactId>twelvemonkeys</artifactId>
|
||||
<version>3.12.1-SNAPSHOT</version>
|
||||
<version>3.13.2-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>com.twelvemonkeys.imageio</groupId>
|
||||
@@ -61,8 +61,7 @@
|
||||
</modules>
|
||||
|
||||
<properties>
|
||||
<core.version>3.1-SNAPSHOT</core.version>
|
||||
<imageio.core.version>3.1-SNAPSHOT</imageio.core.version>
|
||||
<junit.jupiter.version>5.14.2</junit.jupiter.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
@@ -98,23 +97,21 @@
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter-engine</artifactId>
|
||||
<version>5.12.2</version>
|
||||
<version>${junit.jupiter.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter-api</artifactId>
|
||||
<version>5.12.2</version>
|
||||
<version>${junit.jupiter.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.mockito</groupId>
|
||||
<artifactId>mockito-core</artifactId>
|
||||
<version>4.11.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.hamcrest</groupId>
|
||||
<artifactId>hamcrest</artifactId>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
<groupId>com.twelvemonkeys</groupId>
|
||||
<artifactId>twelvemonkeys</artifactId>
|
||||
<version>3.12.1-SNAPSHOT</version>
|
||||
<version>3.13.2-SNAPSHOT</version>
|
||||
<packaging>pom</packaging>
|
||||
<name>TwelveMonkeys</name>
|
||||
<description>TwelveMonkeys parent POM</description>
|
||||
@@ -85,8 +85,8 @@
|
||||
|
||||
<distributionManagement>
|
||||
<snapshotRepository>
|
||||
<id>ossrh</id>
|
||||
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
|
||||
<id>central</id>
|
||||
<url>https://central.sonatype.com/repository/maven-snapshots/</url>
|
||||
</snapshotRepository>
|
||||
</distributionManagement>
|
||||
|
||||
@@ -98,7 +98,7 @@
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-gpg-plugin</artifactId>
|
||||
<version>3.2.7</version>
|
||||
<version>3.2.8</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>sign-artifacts</id>
|
||||
@@ -112,7 +112,7 @@
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-javadoc-plugin</artifactId>
|
||||
<version>3.11.2</version>
|
||||
<version>3.12.0</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>attach-javadocs</id>
|
||||
@@ -160,7 +160,7 @@
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-source-plugin</artifactId>
|
||||
<version>3.3.1</version>
|
||||
<version>3.4.0</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
@@ -174,14 +174,14 @@
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<groupId>org.sonatype.plugins</groupId>
|
||||
<artifactId>nexus-staging-maven-plugin</artifactId>
|
||||
<version>1.7.0</version>
|
||||
<groupId>org.sonatype.central</groupId>
|
||||
<artifactId>central-publishing-maven-plugin</artifactId>
|
||||
<version>0.10.0</version>
|
||||
<extensions>true</extensions>
|
||||
<configuration>
|
||||
<serverId>ossrh</serverId>
|
||||
<nexusUrl>https://oss.sonatype.org/</nexusUrl>
|
||||
<autoReleaseAfterClose>true</autoReleaseAfterClose>
|
||||
<publishingServerId>central</publishingServerId>
|
||||
<autoPublish>true</autoPublish>
|
||||
<waitUntil>published</waitUntil>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
@@ -191,7 +191,7 @@
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-resources-plugin</artifactId>
|
||||
<version>3.3.1</version>
|
||||
<version>3.4.0</version>
|
||||
<configuration>
|
||||
<encoding>UTF-8</encoding>
|
||||
</configuration>
|
||||
@@ -199,7 +199,7 @@
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-jar-plugin</artifactId>
|
||||
<version>3.4.2</version>
|
||||
<version>3.5.0</version>
|
||||
<inherited>true</inherited>
|
||||
<executions>
|
||||
<execution>
|
||||
@@ -250,7 +250,7 @@
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.14.0</version>
|
||||
<version>3.15.0</version>
|
||||
<inherited>true</inherited>
|
||||
<configuration>
|
||||
<source>8</source>
|
||||
@@ -265,7 +265,7 @@
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<version>3.5.3</version>
|
||||
<version>3.5.4</version>
|
||||
<configuration>
|
||||
<systemProperties>
|
||||
<property>
|
||||
@@ -278,7 +278,7 @@
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-release-plugin</artifactId>
|
||||
<version>3.1.1</version>
|
||||
<version>3.3.1</version>
|
||||
<configuration>
|
||||
<autoVersionSubmodules>true</autoVersionSubmodules>
|
||||
<releaseProfiles>release</releaseProfiles>
|
||||
@@ -288,7 +288,7 @@
|
||||
<dependency>
|
||||
<groupId>org.apache.maven.scm</groupId>
|
||||
<artifactId>maven-scm-provider-gitexe</artifactId>
|
||||
<version>2.1.0</version>
|
||||
<version>2.2.1</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</plugin>
|
||||
@@ -300,7 +300,7 @@
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-report-plugin</artifactId>
|
||||
<version>3.5.3</version>
|
||||
<version>3.5.4</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
@@ -310,7 +310,7 @@
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-pmd-plugin</artifactId>
|
||||
<version>3.26.0</version>
|
||||
<version>3.28.0</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
|
||||
+9
-5
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>com.twelvemonkeys</groupId>
|
||||
<artifactId>twelvemonkeys</artifactId>
|
||||
<version>3.12.1-SNAPSHOT</version>
|
||||
<version>3.13.2-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
@@ -14,6 +14,10 @@
|
||||
TwelveMonkeys Servlet support classes.
|
||||
</description>
|
||||
|
||||
<properties>
|
||||
<junit.jupiter.version>5.14.2</junit.jupiter.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
@@ -24,13 +28,13 @@
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter-api</artifactId>
|
||||
<version>5.12.2</version>
|
||||
<version>${junit.jupiter.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter-engine</artifactId>
|
||||
<version>5.12.2</version>
|
||||
<version>${junit.jupiter.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
@@ -57,7 +61,7 @@
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-jar-plugin</artifactId>
|
||||
<version>3.4.2</version>
|
||||
<version>3.5.0</version>
|
||||
<configuration>
|
||||
<archive>
|
||||
<manifestEntries>
|
||||
@@ -78,7 +82,7 @@
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<version>3.6.0</version>
|
||||
<version>3.6.1</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>jakarta</id>
|
||||
|
||||
Reference in New Issue
Block a user